Make WordPress Core

Changeset 52244


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.

Location:
trunk
Files:
7 added
33 deleted
26 edited
34 copied
11 moved

Legend:

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

    r50842 r52244  
    33 * Authentication provider interface
    44 *
    5  * @package Requests
    6  * @subpackage Authentication
     5 * @package Requests\Authentication
    76 */
     7
     8namespace WpOrg\Requests;
     9
     10use WpOrg\Requests\Hooks;
    811
    912/**
     
    1518 * makes it much easier for users to use your provider.
    1619 *
    17  * @see Requests_Hooks
    18  * @package Requests
    19  * @subpackage Authentication
     20 * @see \WpOrg\Requests\Hooks
     21 *
     22 * @package Requests\Authentication
    2023 */
    21 interface Requests_Auth {
     24interface Auth {
    2225        /**
    2326         * Register hooks as needed
    2427         *
    25          * This method is called in {@see Requests::request} when the user has set
    26          * an instance as the 'auth' option. Use this callback to register all the
     28         * This method is called in {@see \WpOrg\Requests\Requests::request()} when the user
     29         * has set an instance as the 'auth' option. Use this callback to register all the
    2730         * hooks you'll need.
    2831         *
    29          * @see Requests_Hooks::register
    30          * @param Requests_Hooks $hooks Hook system
     32         * @see \WpOrg\Requests\Hooks::register()
     33         * @param \WpOrg\Requests\Hooks $hooks Hook system
    3134         */
    32         public function register(Requests_Hooks $hooks);
     35        public function register(Hooks $hooks);
    3336}
  • trunk/src/wp-includes/Requests/Auth/Basic.php

    r50842 r52244  
    33 * Basic Authentication provider
    44 *
    5  * @package Requests
    6  * @subpackage Authentication
     5 * @package Requests\Authentication
    76 */
     7
     8namespace WpOrg\Requests\Auth;
     9
     10use WpOrg\Requests\Auth;
     11use WpOrg\Requests\Exception\ArgumentCount;
     12use WpOrg\Requests\Exception\InvalidArgument;
     13use WpOrg\Requests\Hooks;
    814
    915/**
     
    1319 * header.
    1420 *
    15  * @package Requests
    16  * @subpackage Authentication
     21 * @package Requests\Authentication
    1722 */
    18 class Requests_Auth_Basic implements Requests_Auth {
     23class Basic implements Auth {
    1924        /**
    2025         * Username
     
    3439         * Constructor
    3540         *
    36          * @throws Requests_Exception On incorrect number of arguments (`authbasicbadargs`)
     41         * @since 2.0 Throws an `InvalidArgument` exception.
     42         * @since 2.0 Throws an `ArgumentCount` exception instead of the Requests base `Exception.
     43         *
    3744         * @param array|null $args Array of user and password. Must have exactly two elements
     45         *
     46         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not an array or null.
     47         * @throws \WpOrg\Requests\Exception\ArgumentCount   On incorrect number of array elements (`authbasicbadargs`).
    3848         */
    3949        public function __construct($args = null) {
    4050                if (is_array($args)) {
    4151                        if (count($args) !== 2) {
    42                                 throw new Requests_Exception('Invalid number of arguments', 'authbasicbadargs');
     52                                throw ArgumentCount::create('an array with exactly two elements', count($args), 'authbasicbadargs');
    4353                        }
    4454
    4555                        list($this->user, $this->pass) = $args;
     56                        return;
     57                }
     58
     59                if ($args !== null) {
     60                        throw InvalidArgument::create(1, '$args', 'array|null', gettype($args));
    4661                }
    4762        }
     
    5065         * Register the necessary callbacks
    5166         *
    52          * @see curl_before_send
    53          * @see fsockopen_header
    54          * @param Requests_Hooks $hooks Hook system
     67         * @see \WpOrg\Requests\Auth\Basic::curl_before_send()
     68         * @see \WpOrg\Requests\Auth\Basic::fsockopen_header()
     69         * @param \WpOrg\Requests\Hooks $hooks Hook system
    5570         */
    56         public function register(Requests_Hooks $hooks) {
    57                 $hooks->register('curl.before_send', array($this, 'curl_before_send'));
    58                 $hooks->register('fsockopen.after_headers', array($this, 'fsockopen_header'));
     71        public function register(Hooks $hooks) {
     72                $hooks->register('curl.before_send', [$this, 'curl_before_send']);
     73                $hooks->register('fsockopen.after_headers', [$this, 'fsockopen_header']);
    5974        }
    6075
     
    6277         * Set cURL parameters before the data is sent
    6378         *
    64          * @param resource $handle cURL resource
     79         * @param resource|\CurlHandle $handle cURL handle
    6580         */
    6681        public function curl_before_send(&$handle) {
  • trunk/src/wp-includes/Requests/Cookie.php

    r50842 r52244  
    33 * Cookie storage object
    44 *
    5  * @package Requests
    6  * @subpackage Cookies
     5 * @package Requests\Cookies
    76 */
     7
     8namespace WpOrg\Requests;
     9
     10use WpOrg\Requests\Exception\InvalidArgument;
     11use WpOrg\Requests\Iri;
     12use WpOrg\Requests\Response\Headers;
     13use WpOrg\Requests\Utility\CaseInsensitiveDictionary;
     14use WpOrg\Requests\Utility\InputValidator;
    815
    916/**
    1017 * Cookie storage object
    1118 *
    12  * @package Requests
    13  * @subpackage Cookies
     19 * @package Requests\Cookies
    1420 */
    15 class Requests_Cookie {
     21class Cookie {
    1622        /**
    1723         * Cookie name.
     
    3440         * httponly.
    3541         *
    36          * @var Requests_Utility_CaseInsensitiveDictionary|array Array-like object
    37          */
    38         public $attributes = array();
     42         * @var \WpOrg\Requests\Utility\CaseInsensitiveDictionary|array Array-like object
     43         */
     44        public $attributes = [];
    3945
    4046        /**
     
    4652         * @var array
    4753         */
    48         public $flags = array();
     54        public $flags = [];
    4955
    5056        /**
     
    6369         * @param string $name
    6470         * @param string $value
    65          * @param array|Requests_Utility_CaseInsensitiveDictionary $attributes Associative array of attribute data
    66          */
    67         public function __construct($name, $value, $attributes = array(), $flags = array(), $reference_time = null) {
     71         * @param array|\WpOrg\Requests\Utility\CaseInsensitiveDictionary $attributes Associative array of attribute data
     72         * @param array $flags
     73         * @param int|null $reference_time
     74         *
     75         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $name argument is not a string.
     76         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $value argument is not a string.
     77         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $attributes argument is not an array or iterable object with array access.
     78         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $flags argument is not an array.
     79         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $reference_time argument is not an integer or null.
     80         */
     81        public function __construct($name, $value, $attributes = [], $flags = [], $reference_time = null) {
     82                if (is_string($name) === false) {
     83                        throw InvalidArgument::create(1, '$name', 'string', gettype($name));
     84                }
     85
     86                if (is_string($value) === false) {
     87                        throw InvalidArgument::create(2, '$value', 'string', gettype($value));
     88                }
     89
     90                if (InputValidator::has_array_access($attributes) === false || InputValidator::is_iterable($attributes) === false) {
     91                        throw InvalidArgument::create(3, '$attributes', 'array|ArrayAccess&Traversable', gettype($attributes));
     92                }
     93
     94                if (is_array($flags) === false) {
     95                        throw InvalidArgument::create(4, '$flags', 'array', gettype($flags));
     96                }
     97
     98                if ($reference_time !== null && is_int($reference_time) === false) {
     99                        throw InvalidArgument::create(5, '$reference_time', 'integer|null', gettype($reference_time));
     100                }
     101
    68102                $this->name       = $name;
    69103                $this->value      = $value;
    70104                $this->attributes = $attributes;
    71                 $default_flags    = array(
     105                $default_flags    = [
    72106                        'creation'    => time(),
    73107                        'last-access' => time(),
    74108                        'persistent'  => false,
    75109                        'host-only'   => true,
    76                 );
     110                ];
    77111                $this->flags      = array_merge($default_flags, $flags);
    78112
     
    83117
    84118                $this->normalize();
     119        }
     120
     121        /**
     122         * Get the cookie value
     123         *
     124         * Attributes and other data can be accessed via methods.
     125         */
     126        public function __toString() {
     127                return $this->value;
    85128        }
    86129
     
    114157         * Check if a cookie is valid for a given URI
    115158         *
    116          * @param Requests_IRI $uri URI to check
     159         * @param \WpOrg\Requests\Iri $uri URI to check
    117160         * @return boolean Whether the cookie is valid for the given URI
    118161         */
    119         public function uri_matches(Requests_IRI $uri) {
     162        public function uri_matches(Iri $uri) {
    120163                if (!$this->domain_matches($uri->host)) {
    121164                        return false;
     
    132175         * Check if a cookie is valid for a given domain
    133176         *
    134          * @param string $string Domain to check
     177         * @param string $domain Domain to check
    135178         * @return boolean Whether the cookie is valid for the given domain
    136179         */
    137         public function domain_matches($string) {
     180        public function domain_matches($domain) {
     181                if (is_string($domain) === false) {
     182                        return false;
     183                }
     184
    138185                if (!isset($this->attributes['domain'])) {
    139186                        // Cookies created manually; cookies created by Requests will set
     
    142189                }
    143190
    144                 $domain_string = $this->attributes['domain'];
    145                 if ($domain_string === $string) {
    146                         // The domain string and the string are identical.
     191                $cookie_domain = $this->attributes['domain'];
     192                if ($cookie_domain === $domain) {
     193                        // The cookie domain and the passed domain are identical.
    147194                        return true;
    148195                }
     
    154201                }
    155202
    156                 if (strlen($string) <= strlen($domain_string)) {
    157                         // For obvious reasons, the string cannot be a suffix if the domain
    158                         // is shorter than the domain string
    159                         return false;
    160                 }
    161 
    162                 if (substr($string, -1 * strlen($domain_string)) !== $domain_string) {
    163                         // The domain string should be a suffix of the string.
    164                         return false;
    165                 }
    166 
    167                 $prefix = substr($string, 0, strlen($string) - strlen($domain_string));
     203                if (strlen($domain) <= strlen($cookie_domain)) {
     204                        // For obvious reasons, the cookie domain cannot be a suffix if the passed domain
     205                        // is shorter than the cookie domain
     206                        return false;
     207                }
     208
     209                if (substr($domain, -1 * strlen($cookie_domain)) !== $cookie_domain) {
     210                        // The cookie domain should be a suffix of the passed domain.
     211                        return false;
     212                }
     213
     214                $prefix = substr($domain, 0, strlen($domain) - strlen($cookie_domain));
    168215                if (substr($prefix, -1) !== '.') {
    169                         // The last character of the string that is not included in the
     216                        // The last character of the passed domain that is not included in the
    170217                        // domain string should be a %x2E (".") character.
    171218                        return false;
    172219                }
    173220
    174                 // The string should be a host name (i.e., not an IP address).
    175                 return !preg_match('#^(.+\.)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $string);
     221                // The passed domain should be a host name (i.e., not an IP address).
     222                return !preg_match('#^(.+\.)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $domain);
    176223        }
    177224
     
    194241                        // the path to the requested path
    195242                        return true;
     243                }
     244
     245                if (is_scalar($request_path) === false) {
     246                        return false;
    196247                }
    197248
     
    318369
    319370        /**
    320          * Format a cookie for a Cookie header
    321          *
    322          * @codeCoverageIgnore
    323          * @deprecated Use {@see Requests_Cookie::format_for_header}
    324          * @return string
    325          */
    326         public function formatForHeader() {
    327                 return $this->format_for_header();
    328         }
    329 
    330         /**
    331371         * Format a cookie for a Set-Cookie header
    332372         *
     
    339379                $header_value = $this->format_for_header();
    340380                if (!empty($this->attributes)) {
    341                         $parts = array();
     381                        $parts = [];
    342382                        foreach ($this->attributes as $key => $value) {
    343383                                // Ignore non-associative attributes
     
    356396
    357397        /**
    358          * Format a cookie for a Set-Cookie header
    359          *
    360          * @codeCoverageIgnore
    361          * @deprecated Use {@see Requests_Cookie::format_for_set_cookie}
    362          * @return string
    363          */
    364         public function formatForSetCookie() {
    365                 return $this->format_for_set_cookie();
    366         }
    367 
    368         /**
    369          * Get the cookie value
    370          *
    371          * Attributes and other data can be accessed via methods.
    372          */
    373         public function __toString() {
    374                 return $this->value;
    375         }
    376 
    377         /**
    378398         * Parse a cookie string into a cookie object
    379399         *
     
    382402         * specifies some of this handling, but not in a thorough manner.
    383403         *
    384          * @param string Cookie header value (from a Set-Cookie header)
    385          * @return Requests_Cookie Parsed cookie object
    386          */
    387         public static function parse($string, $name = '', $reference_time = null) {
    388                 $parts   = explode(';', $string);
     404         * @param string $cookie_header Cookie header value (from a Set-Cookie header)
     405         * @param string $name
     406         * @param int|null $reference_time
     407         * @return \WpOrg\Requests\Cookie Parsed cookie object
     408         *
     409         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $cookie_header argument is not a string.
     410         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $name argument is not a string.
     411         */
     412        public static function parse($cookie_header, $name = '', $reference_time = null) {
     413                if (is_string($cookie_header) === false) {
     414                        throw InvalidArgument::create(1, '$cookie_header', 'string', gettype($cookie_header));
     415                }
     416
     417                if (is_string($name) === false) {
     418                        throw InvalidArgument::create(2, '$name', 'string', gettype($name));
     419                }
     420
     421                $parts   = explode(';', $cookie_header);
    389422                $kvparts = array_shift($parts);
    390423
    391424                if (!empty($name)) {
    392                         $value = $string;
     425                        $value = $cookie_header;
    393426                }
    394427                elseif (strpos($kvparts, '=') === false) {
     
    407440                $value = trim($value);
    408441
    409                 // Attribute key are handled case-insensitively
    410                 $attributes = new Requests_Utility_CaseInsensitiveDictionary();
     442                // Attribute keys are handled case-insensitively
     443                $attributes = new CaseInsensitiveDictionary();
    411444
    412445                if (!empty($parts)) {
     
    426459                }
    427460
    428                 return new Requests_Cookie($name, $value, $attributes, array(), $reference_time);
     461                return new static($name, $value, $attributes, [], $reference_time);
    429462        }
    430463
     
    432465         * Parse all Set-Cookie headers from request headers
    433466         *
    434          * @param Requests_Response_Headers $headers Headers to parse from
    435          * @param Requests_IRI|null $origin URI for comparing cookie origins
     467         * @param \WpOrg\Requests\Response\Headers $headers Headers to parse from
     468         * @param \WpOrg\Requests\Iri|null $origin URI for comparing cookie origins
    436469         * @param int|null $time Reference time for expiration calculation
    437470         * @return array
    438471         */
    439         public static function parse_from_headers(Requests_Response_Headers $headers, Requests_IRI $origin = null, $time = null) {
     472        public static function parse_from_headers(Headers $headers, Iri $origin = null, $time = null) {
    440473                $cookie_headers = $headers->getValues('Set-Cookie');
    441474                if (empty($cookie_headers)) {
    442                         return array();
    443                 }
    444 
    445                 $cookies = array();
     475                        return [];
     476                }
     477
     478                $cookies = [];
    446479                foreach ($cookie_headers as $header) {
    447480                        $parsed = self::parse($header, '', $time);
     
    492525                return $cookies;
    493526        }
    494 
    495         /**
    496          * Parse all Set-Cookie headers from request headers
    497          *
    498          * @codeCoverageIgnore
    499          * @deprecated Use {@see Requests_Cookie::parse_from_headers}
    500          * @return array
    501          */
    502         public static function parseFromHeaders(Requests_Response_Headers $headers) {
    503                 return self::parse_from_headers($headers);
    504         }
    505527}
  • trunk/src/wp-includes/Requests/Cookie/Jar.php

    r50842 r52244  
    33 * Cookie holder object
    44 *
    5  * @package Requests
    6  * @subpackage Cookies
     5 * @package Requests\Cookies
    76 */
     7
     8namespace WpOrg\Requests\Cookie;
     9
     10use ArrayAccess;
     11use ArrayIterator;
     12use IteratorAggregate;
     13use ReturnTypeWillChange;
     14use WpOrg\Requests\Cookie;
     15use WpOrg\Requests\Exception;
     16use WpOrg\Requests\Exception\InvalidArgument;
     17use WpOrg\Requests\HookManager;
     18use WpOrg\Requests\Iri;
     19use WpOrg\Requests\Response;
    820
    921/**
    1022 * Cookie holder object
    1123 *
    12  * @package Requests
    13  * @subpackage Cookies
     24 * @package Requests\Cookies
    1425 */
    15 class Requests_Cookie_Jar implements ArrayAccess, IteratorAggregate {
     26class Jar implements ArrayAccess, IteratorAggregate {
    1627        /**
    1728         * Actual item data
     
    1930         * @var array
    2031         */
    21         protected $cookies = array();
     32        protected $cookies = [];
    2233
    2334        /**
     
    2536         *
    2637         * @param array $cookies Existing cookie values
     38         *
     39         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not an array.
    2740         */
    28         public function __construct($cookies = array()) {
     41        public function __construct($cookies = []) {
     42                if (is_array($cookies) === false) {
     43                        throw InvalidArgument::create(1, '$cookies', 'array', gettype($cookies));
     44                }
     45
    2946                $this->cookies = $cookies;
    3047        }
    3148
    3249        /**
    33          * Normalise cookie data into a Requests_Cookie
     50         * Normalise cookie data into a \WpOrg\Requests\Cookie
    3451         *
    35          * @param string|Requests_Cookie $cookie
    36          * @return Requests_Cookie
     52         * @param string|\WpOrg\Requests\Cookie $cookie
     53         * @return \WpOrg\Requests\Cookie
    3754         */
    38         public function normalize_cookie($cookie, $key = null) {
    39                 if ($cookie instanceof Requests_Cookie) {
     55        public function normalize_cookie($cookie, $key = '') {
     56                if ($cookie instanceof Cookie) {
    4057                        return $cookie;
    4158                }
    4259
    43                 return Requests_Cookie::parse($cookie, $key);
    44         }
    45 
    46         /**
    47          * Normalise cookie data into a Requests_Cookie
    48          *
    49          * @codeCoverageIgnore
    50          * @deprecated Use {@see Requests_Cookie_Jar::normalize_cookie}
    51          * @return Requests_Cookie
    52          */
    53         public function normalizeCookie($cookie, $key = null) {
    54                 return $this->normalize_cookie($cookie, $key);
     60                return Cookie::parse($cookie, $key);
    5561        }
    5662
     
    5864         * Check if the given item exists
    5965         *
    60          * @param string $key Item key
     66         * @param string $offset Item key
    6167         * @return boolean Does the item exist?
    6268         */
    63         public function offsetExists($key) {
    64                 return isset($this->cookies[$key]);
     69        #[ReturnTypeWillChange]
     70        public function offsetExists($offset) {
     71                return isset($this->cookies[$offset]);
    6572        }
    6673
     
    6875         * Get the value for the item
    6976         *
    70          * @param string $key Item key
     77         * @param string $offset Item key
    7178         * @return string|null Item value (null if offsetExists is false)
    7279         */
    73         public function offsetGet($key) {
    74                 if (!isset($this->cookies[$key])) {
     80        #[ReturnTypeWillChange]
     81        public function offsetGet($offset) {
     82                if (!isset($this->cookies[$offset])) {
    7583                        return null;
    7684                }
    7785
    78                 return $this->cookies[$key];
     86                return $this->cookies[$offset];
    7987        }
    8088
     
    8290         * Set the given item
    8391         *
    84          * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`)
     92         * @param string $offset Item name
     93         * @param string $value Item value
    8594         *
    86          * @param string $key Item name
    87          * @param string $value Item value
     95         * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`)
    8896         */
    89         public function offsetSet($key, $value) {
    90                 if ($key === null) {
    91                         throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset');
     97        #[ReturnTypeWillChange]
     98        public function offsetSet($offset, $value) {
     99                if ($offset === null) {
     100                        throw new Exception('Object is a dictionary, not a list', 'invalidset');
    92101                }
    93102
    94                 $this->cookies[$key] = $value;
     103                $this->cookies[$offset] = $value;
    95104        }
    96105
     
    98107         * Unset the given header
    99108         *
    100          * @param string $key
     109         * @param string $offset
    101110         */
    102         public function offsetUnset($key) {
    103                 unset($this->cookies[$key]);
     111        #[ReturnTypeWillChange]
     112        public function offsetUnset($offset) {
     113                unset($this->cookies[$offset]);
    104114        }
    105115
     
    107117         * Get an iterator for the data
    108118         *
    109          * @return ArrayIterator
     119         * @return \ArrayIterator
    110120         */
     121        #[ReturnTypeWillChange]
    111122        public function getIterator() {
    112123                return new ArrayIterator($this->cookies);
     
    116127         * Register the cookie handler with the request's hooking system
    117128         *
    118          * @param Requests_Hooker $hooks Hooking system
     129         * @param \WpOrg\Requests\HookManager $hooks Hooking system
    119130         */
    120         public function register(Requests_Hooker $hooks) {
    121                 $hooks->register('requests.before_request', array($this, 'before_request'));
    122                 $hooks->register('requests.before_redirect_check', array($this, 'before_redirect_check'));
     131        public function register(HookManager $hooks) {
     132                $hooks->register('requests.before_request', [$this, 'before_request']);
     133                $hooks->register('requests.before_redirect_check', [$this, 'before_redirect_check']);
    123134        }
    124135
     
    135146         */
    136147        public function before_request($url, &$headers, &$data, &$type, &$options) {
    137                 if (!$url instanceof Requests_IRI) {
    138                         $url = new Requests_IRI($url);
     148                if (!$url instanceof Iri) {
     149                        $url = new Iri($url);
    139150                }
    140151
    141152                if (!empty($this->cookies)) {
    142                         $cookies = array();
     153                        $cookies = [];
    143154                        foreach ($this->cookies as $key => $cookie) {
    144155                                $cookie = $this->normalize_cookie($cookie, $key);
     
    161172         * Parse all cookies from a response and attach them to the response
    162173         *
    163          * @var Requests_Response $response
     174         * @param \WpOrg\Requests\Response $response
    164175         */
    165         public function before_redirect_check(Requests_Response $return) {
    166                 $url = $return->url;
    167                 if (!$url instanceof Requests_IRI) {
    168                         $url = new Requests_IRI($url);
     176        public function before_redirect_check(Response $response) {
     177                $url = $response->url;
     178                if (!$url instanceof Iri) {
     179                        $url = new Iri($url);
    169180                }
    170181
    171                 $cookies         = Requests_Cookie::parse_from_headers($return->headers, $url);
    172                 $this->cookies   = array_merge($this->cookies, $cookies);
    173                 $return->cookies = $this;
     182                $cookies           = Cookie::parse_from_headers($response->headers, $url);
     183                $this->cookies     = array_merge($this->cookies, $cookies);
     184                $response->cookies = $this;
    174185        }
    175186}
  • trunk/src/wp-includes/Requests/Exception.php

    r50842 r52244  
    33 * Exception for HTTP requests
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests;
     9
     10use Exception as PHPException;
    711
    812/**
    913 * Exception for HTTP requests
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception extends Exception {
     17class Exception extends PHPException {
    1418        /**
    1519         * Type of exception
     
    4246
    4347        /**
    44          * Like {@see getCode()}, but a string code.
     48         * Like {@see \Exception::getCode()}, but a string code.
    4549         *
    4650         * @codeCoverageIgnore
  • trunk/src/wp-includes/Requests/Exception/Http.php

    r52243 r52244  
    33 * Exception based on HTTP response
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception;
     9
     10use WpOrg\Requests\Exception;
     11use WpOrg\Requests\Exception\Http\StatusUnknown;
    712
    813/**
    914 * Exception based on HTTP response
    1015 *
    11  * @package Requests
     16 * @package Requests\Exceptions
    1217 */
    13 class Requests_Exception_HTTP extends Requests_Exception {
     18class Http extends Exception {
    1419        /**
    1520         * HTTP status code
     
    4550
    4651        /**
    47          * Get the status message
     52         * Get the status message.
     53         *
     54         * @return string
    4855         */
    4956        public function getReason() {
     
    5966        public static function get_class($code) {
    6067                if (!$code) {
    61                         return 'Requests_Exception_HTTP_Unknown';
     68                        return StatusUnknown::class;
    6269                }
    6370
    64                 $class = sprintf('Requests_Exception_HTTP_%d', $code);
     71                $class = sprintf('\WpOrg\Requests\Exception\Http\Status%d', $code);
    6572                if (class_exists($class)) {
    6673                        return $class;
    6774                }
    6875
    69                 return 'Requests_Exception_HTTP_Unknown';
     76                return StatusUnknown::class;
    7077        }
    7178}
  • trunk/src/wp-includes/Requests/Exception/Http/Status304.php

    r52243 r52244  
    33 * Exception for 304 Not Modified responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 304 Not Modified responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_304 extends Requests_Exception_HTTP {
     17final class Status304 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status305.php

    r52243 r52244  
    33 * Exception for 305 Use Proxy responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 305 Use Proxy responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_305 extends Requests_Exception_HTTP {
     17final class Status305 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status306.php

    r52243 r52244  
    33 * Exception for 306 Switch Proxy responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 306 Switch Proxy responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_306 extends Requests_Exception_HTTP {
     17final class Status306 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status400.php

    r52243 r52244  
    33 * Exception for 400 Bad Request responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 400 Bad Request responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_400 extends Requests_Exception_HTTP {
     17final class Status400 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status401.php

    r52243 r52244  
    33 * Exception for 401 Unauthorized responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 401 Unauthorized responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_401 extends Requests_Exception_HTTP {
     17final class Status401 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status402.php

    r52243 r52244  
    33 * Exception for 402 Payment Required responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 402 Payment Required responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_402 extends Requests_Exception_HTTP {
     17final class Status402 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status403.php

    r52243 r52244  
    33 * Exception for 403 Forbidden responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 403 Forbidden responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_403 extends Requests_Exception_HTTP {
     17final class Status403 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status404.php

    r52243 r52244  
    33 * Exception for 404 Not Found responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 404 Not Found responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_404 extends Requests_Exception_HTTP {
     17final class Status404 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status405.php

    r52243 r52244  
    33 * Exception for 405 Method Not Allowed responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 405 Method Not Allowed responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_405 extends Requests_Exception_HTTP {
     17final class Status405 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status406.php

    r52243 r52244  
    33 * Exception for 406 Not Acceptable responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 406 Not Acceptable responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_406 extends Requests_Exception_HTTP {
     17final class Status406 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status407.php

    r52243 r52244  
    33 * Exception for 407 Proxy Authentication Required responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 407 Proxy Authentication Required responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_407 extends Requests_Exception_HTTP {
     17final class Status407 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status408.php

    r52243 r52244  
    33 * Exception for 408 Request Timeout responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 408 Request Timeout responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_408 extends Requests_Exception_HTTP {
     17final class Status408 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status409.php

    r52243 r52244  
    33 * Exception for 409 Conflict responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 409 Conflict responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_409 extends Requests_Exception_HTTP {
     17final class Status409 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status410.php

    r52243 r52244  
    33 * Exception for 410 Gone responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 410 Gone responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_410 extends Requests_Exception_HTTP {
     17final class Status410 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status411.php

    r52243 r52244  
    33 * Exception for 411 Length Required responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 411 Length Required responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_411 extends Requests_Exception_HTTP {
     17final class Status411 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status412.php

    r52243 r52244  
    33 * Exception for 412 Precondition Failed responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 412 Precondition Failed responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_412 extends Requests_Exception_HTTP {
     17final class Status412 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status413.php

    r52243 r52244  
    33 * Exception for 413 Request Entity Too Large responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 413 Request Entity Too Large responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_413 extends Requests_Exception_HTTP {
     17final class Status413 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status414.php

    r52243 r52244  
    33 * Exception for 414 Request-URI Too Large responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 414 Request-URI Too Large responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_414 extends Requests_Exception_HTTP {
     17final class Status414 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status415.php

    r52243 r52244  
    33 * Exception for 415 Unsupported Media Type responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 415 Unsupported Media Type responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_415 extends Requests_Exception_HTTP {
     17final class Status415 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status416.php

    r52243 r52244  
    33 * Exception for 416 Requested Range Not Satisfiable responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 416 Requested Range Not Satisfiable responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_416 extends Requests_Exception_HTTP {
     17final class Status416 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status417.php

    r52243 r52244  
    33 * Exception for 417 Expectation Failed responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 417 Expectation Failed responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_417 extends Requests_Exception_HTTP {
     17final class Status417 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status418.php

    r52243 r52244  
    33 * Exception for 418 I'm A Teapot responses
    44 *
    5  * @see https://tools.ietf.org/html/rfc2324
    6  * @package Requests
     5 * @link https://tools.ietf.org/html/rfc2324
     6 *
     7 * @package Requests\Exceptions
    78 */
     9
     10namespace WpOrg\Requests\Exception\Http;
     11
     12use WpOrg\Requests\Exception\Http;
    813
    914/**
    1015 * Exception for 418 I'm A Teapot responses
    1116 *
    12  * @see https://tools.ietf.org/html/rfc2324
    13  * @package Requests
     17 * @link https://tools.ietf.org/html/rfc2324
     18 *
     19 * @package Requests\Exceptions
    1420 */
    15 class Requests_Exception_HTTP_418 extends Requests_Exception_HTTP {
     21final class Status418 extends Http {
    1622        /**
    1723         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status428.php

    r52243 r52244  
    33 * Exception for 428 Precondition Required responses
    44 *
    5  * @see https://tools.ietf.org/html/rfc6585
    6  * @package Requests
     5 * @link https://tools.ietf.org/html/rfc6585
     6 *
     7 * @package Requests\Exceptions
    78 */
     9
     10namespace WpOrg\Requests\Exception\Http;
     11
     12use WpOrg\Requests\Exception\Http;
    813
    914/**
    1015 * Exception for 428 Precondition Required responses
    1116 *
    12  * @see https://tools.ietf.org/html/rfc6585
    13  * @package Requests
     17 * @link https://tools.ietf.org/html/rfc6585
     18 *
     19 * @package Requests\Exceptions
    1420 */
    15 class Requests_Exception_HTTP_428 extends Requests_Exception_HTTP {
     21final class Status428 extends Http {
    1622        /**
    1723         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status429.php

    r52243 r52244  
    33 * Exception for 429 Too Many Requests responses
    44 *
    5  * @see https://tools.ietf.org/html/draft-nottingham-http-new-status-04
    6  * @package Requests
     5 * @link https://tools.ietf.org/html/draft-nottingham-http-new-status-04
     6 *
     7 * @package Requests\Exceptions
    78 */
     9
     10namespace WpOrg\Requests\Exception\Http;
     11
     12use WpOrg\Requests\Exception\Http;
    813
    914/**
    1015 * Exception for 429 Too Many Requests responses
    1116 *
    12  * @see https://tools.ietf.org/html/draft-nottingham-http-new-status-04
    13  * @package Requests
     17 * @link https://tools.ietf.org/html/draft-nottingham-http-new-status-04
     18 *
     19 * @package Requests\Exceptions
    1420 */
    15 class Requests_Exception_HTTP_429 extends Requests_Exception_HTTP {
     21final class Status429 extends Http {
    1622        /**
    1723         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status431.php

    r52243 r52244  
    33 * Exception for 431 Request Header Fields Too Large responses
    44 *
    5  * @see https://tools.ietf.org/html/rfc6585
    6  * @package Requests
     5 * @link https://tools.ietf.org/html/rfc6585
     6 *
     7 * @package Requests\Exceptions
    78 */
     9
     10namespace WpOrg\Requests\Exception\Http;
     11
     12use WpOrg\Requests\Exception\Http;
    813
    914/**
    1015 * Exception for 431 Request Header Fields Too Large responses
    1116 *
    12  * @see https://tools.ietf.org/html/rfc6585
    13  * @package Requests
     17 * @link https://tools.ietf.org/html/rfc6585
     18 *
     19 * @package Requests\Exceptions
    1420 */
    15 class Requests_Exception_HTTP_431 extends Requests_Exception_HTTP {
     21final class Status431 extends Http {
    1622        /**
    1723         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status500.php

    r52243 r52244  
    33 * Exception for 500 Internal Server Error responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 500 Internal Server Error responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_500 extends Requests_Exception_HTTP {
     17final class Status500 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status501.php

    r52243 r52244  
    33 * Exception for 501 Not Implemented responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 501 Not Implemented responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_501 extends Requests_Exception_HTTP {
     17final class Status501 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status502.php

    r52243 r52244  
    33 * Exception for 502 Bad Gateway responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 502 Bad Gateway responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_502 extends Requests_Exception_HTTP {
     17final class Status502 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status503.php

    r52243 r52244  
    33 * Exception for 503 Service Unavailable responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 503 Service Unavailable responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_503 extends Requests_Exception_HTTP {
     17final class Status503 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status504.php

    r52243 r52244  
    33 * Exception for 504 Gateway Timeout responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 504 Gateway Timeout responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_504 extends Requests_Exception_HTTP {
     17final class Status504 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status505.php

    r52243 r52244  
    33 * Exception for 505 HTTP Version Not Supported responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
    711
    812/**
    913 * Exception for 505 HTTP Version Not Supported responses
    1014 *
    11  * @package Requests
     15 * @package Requests\Exceptions
    1216 */
    13 class Requests_Exception_HTTP_505 extends Requests_Exception_HTTP {
     17final class Status505 extends Http {
    1418        /**
    1519         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/Status511.php

    r52243 r52244  
    33 * Exception for 511 Network Authentication Required responses
    44 *
    5  * @see https://tools.ietf.org/html/rfc6585
    6  * @package Requests
     5 * @link https://tools.ietf.org/html/rfc6585
     6 *
     7 * @package Requests\Exceptions
    78 */
     9
     10namespace WpOrg\Requests\Exception\Http;
     11
     12use WpOrg\Requests\Exception\Http;
    813
    914/**
    1015 * Exception for 511 Network Authentication Required responses
    1116 *
    12  * @see https://tools.ietf.org/html/rfc6585
    13  * @package Requests
     17 * @link https://tools.ietf.org/html/rfc6585
     18 *
     19 * @package Requests\Exceptions
    1420 */
    15 class Requests_Exception_HTTP_511 extends Requests_Exception_HTTP {
     21final class Status511 extends Http {
    1622        /**
    1723         * HTTP status code
  • trunk/src/wp-includes/Requests/Exception/Http/StatusUnknown.php

    r52243 r52244  
    33 * Exception for unknown status responses
    44 *
    5  * @package Requests
     5 * @package Requests\Exceptions
    66 */
     7
     8namespace WpOrg\Requests\Exception\Http;
     9
     10use WpOrg\Requests\Exception\Http;
     11use WpOrg\Requests\Response;
    712
    813/**
    914 * Exception for unknown status responses
    1015 *
    11  * @package Requests
     16 * @package Requests\Exceptions
    1217 */
    13 class Requests_Exception_HTTP_Unknown extends Requests_Exception_HTTP {
     18final class StatusUnknown extends Http {
    1419        /**
    1520         * HTTP status code
     
    2934         * Create a new exception
    3035         *
    31          * If `$data` is an instance of {@see Requests_Response}, uses the status
     36         * If `$data` is an instance of {@see \WpOrg\Requests\Response}, uses the status
    3237         * code from it. Otherwise, sets as 0
    3338         *
     
    3641         */
    3742        public function __construct($reason = null, $data = null) {
    38                 if ($data instanceof Requests_Response) {
    39                         $this->code = $data->status_code;
     43                if ($data instanceof Response) {
     44                        $this->code = (int) $data->status_code;
    4045                }
    4146
  • trunk/src/wp-includes/Requests/Exception/Transport.php

    r46586 r52244  
    11<?php
     2/**
     3 * Transport Exception
     4 *
     5 * @package Requests\Exceptions
     6 */
    27
    3 class Requests_Exception_Transport extends Requests_Exception {
     8namespace WpOrg\Requests\Exception;
    49
    5 }
     10use WpOrg\Requests\Exception;
     11
     12/**
     13 * Transport Exception
     14 *
     15 * @package Requests\Exceptions
     16 */
     17class Transport extends Exception {}
  • trunk/src/wp-includes/Requests/Exception/Transport/Curl.php

    r52243 r52244  
    11<?php
     2/**
     3 * CURL Transport Exception.
     4 *
     5 * @package Requests\Exceptions
     6 */
    27
    3 class Requests_Exception_Transport_cURL extends Requests_Exception_Transport {
     8namespace WpOrg\Requests\Exception\Transport;
     9
     10use WpOrg\Requests\Exception\Transport;
     11
     12/**
     13 * CURL Transport Exception.
     14 *
     15 * @package Requests\Exceptions
     16 */
     17final class Curl extends Transport {
    418
    519        const EASY  = 'cURLEasy';
     
    3044        protected $reason = 'Unknown';
    3145
     46        /**
     47         * Create a new exception.
     48         *
     49         * @param string $message Exception message.
     50         * @param string $type    Exception type.
     51         * @param mixed  $data    Associated data, if applicable.
     52         * @param int    $code    Exception numerical code, if applicable.
     53         */
    3254        public function __construct($message, $type, $data = null, $code = 0) {
    3355                if ($type !== null) {
     
    3658
    3759                if ($code !== null) {
    38                         $this->code = $code;
     60                        $this->code = (int) $code;
    3961                }
    4062
     
    4870
    4971        /**
    50          * Get the error message
     72         * Get the error message.
     73         *
     74         * @return string
    5175         */
    5276        public function getReason() {
  • trunk/src/wp-includes/Requests/HookManager.php

    r52243 r52244  
    33 * Event dispatcher
    44 *
    5  * @package Requests
    6  * @subpackage Utilities
     5 * @package Requests\EventDispatcher
    76 */
     7
     8namespace WpOrg\Requests;
    89
    910/**
    1011 * Event dispatcher
    1112 *
    12  * @package Requests
    13  * @subpackage Utilities
     13 * @package Requests\EventDispatcher
    1414 */
    15 interface Requests_Hooker {
     15interface HookManager {
    1616        /**
    1717         * Register a callback for a hook
    1818         *
    1919         * @param string $hook Hook name
    20          * @param callback $callback Function/method to call on event
     20         * @param callable $callback Function/method to call on event
    2121         * @param int $priority Priority number. <0 is executed earlier, >0 is executed later
    2222         */
     
    3030         * @return boolean Successfulness
    3131         */
    32         public function dispatch($hook, $parameters = array());
     32        public function dispatch($hook, $parameters = []);
    3333}
  • trunk/src/wp-includes/Requests/Hooks.php

    r50842 r52244  
    33 * Handles adding and dispatching events
    44 *
    5  * @package Requests
    6  * @subpackage Utilities
     5 * @package Requests\EventDispatcher
    76 */
     7
     8namespace WpOrg\Requests;
     9
     10use WpOrg\Requests\Exception\InvalidArgument;
     11use WpOrg\Requests\HookManager;
     12use WpOrg\Requests\Utility\InputValidator;
    813
    914/**
    1015 * Handles adding and dispatching events
    1116 *
    12  * @package Requests
    13  * @subpackage Utilities
     17 * @package Requests\EventDispatcher
    1418 */
    15 class Requests_Hooks implements Requests_Hooker {
     19class Hooks implements HookManager {
    1620        /**
    1721         * Registered callbacks for each hook
     
    1923         * @var array
    2024         */
    21         protected $hooks = array();
    22 
    23         /**
    24          * Constructor
    25          */
    26         public function __construct() {
    27                 // pass
    28         }
     25        protected $hooks = [];
    2926
    3027        /**
     
    3229         *
    3330         * @param string $hook Hook name
    34          * @param callback $callback Function/method to call on event
     31         * @param callable $callback Function/method to call on event
    3532         * @param int $priority Priority number. <0 is executed earlier, >0 is executed later
     33         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $hook argument is not a string.
     34         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $callback argument is not callable.
     35         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $priority argument is not an integer.
    3636         */
    3737        public function register($hook, $callback, $priority = 0) {
     38                if (is_string($hook) === false) {
     39                        throw InvalidArgument::create(1, '$hook', 'string', gettype($hook));
     40                }
     41
     42                if (is_callable($callback) === false) {
     43                        throw InvalidArgument::create(2, '$callback', 'callable', gettype($callback));
     44                }
     45
     46                if (InputValidator::is_numeric_array_key($priority) === false) {
     47                        throw InvalidArgument::create(3, '$priority', 'integer', gettype($priority));
     48                }
     49
    3850                if (!isset($this->hooks[$hook])) {
    39                         $this->hooks[$hook] = array();
    40                 }
    41                 if (!isset($this->hooks[$hook][$priority])) {
    42                         $this->hooks[$hook][$priority] = array();
     51                        $this->hooks[$hook] = [
     52                                $priority => [],
     53                        ];
     54                } elseif (!isset($this->hooks[$hook][$priority])) {
     55                        $this->hooks[$hook][$priority] = [];
    4356                }
    4457
     
    5265         * @param array $parameters Parameters to pass to callbacks
    5366         * @return boolean Successfulness
     67         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $hook argument is not a string.
     68         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $parameters argument is not an array.
    5469         */
    55         public function dispatch($hook, $parameters = array()) {
     70        public function dispatch($hook, $parameters = []) {
     71                if (is_string($hook) === false) {
     72                        throw InvalidArgument::create(1, '$hook', 'string', gettype($hook));
     73                }
     74
     75                // Check strictly against array, as Array* objects don't work in combination with `call_user_func_array()`.
     76                if (is_array($parameters) === false) {
     77                        throw InvalidArgument::create(2, '$parameters', 'array', gettype($parameters));
     78                }
     79
    5680                if (empty($this->hooks[$hook])) {
    5781                        return false;
    5882                }
    5983
     84                if (!empty($parameters)) {
     85                        // Strip potential keys from the array to prevent them being interpreted as parameter names in PHP 8.0.
     86                        $parameters = array_values($parameters);
     87                }
     88
    6089                foreach ($this->hooks[$hook] as $priority => $hooked) {
    6190                        foreach ($hooked as $callback) {
    62                                 call_user_func_array($callback, $parameters);
     91                                $callback(...$parameters);
    6392                        }
    6493                }
  • trunk/src/wp-includes/Requests/IdnaEncoder.php

    r52243 r52244  
    11<?php
     2
     3namespace WpOrg\Requests;
     4
     5use WpOrg\Requests\Exception;
     6use WpOrg\Requests\Exception\InvalidArgument;
     7use WpOrg\Requests\Utility\InputValidator;
    28
    39/**
     
    612 * Note: Not fully compliant, as nameprep does nothing yet.
    713 *
    8  * @package Requests
    9  * @subpackage Utilities
    10  * @see https://tools.ietf.org/html/rfc3490 IDNA specification
    11  * @see https://tools.ietf.org/html/rfc3492 Punycode/Bootstrap specification
     14 * @package Requests\Utilities
     15 *
     16 * @link https://tools.ietf.org/html/rfc3490 IDNA specification
     17 * @link https://tools.ietf.org/html/rfc3492 Punycode/Bootstrap specification
    1218 */
    13 class Requests_IDNAEncoder {
     19class IdnaEncoder {
    1420        /**
    1521         * ACE prefix used for IDNA
    1622         *
    17          * @see https://tools.ietf.org/html/rfc3490#section-5
     23         * @link https://tools.ietf.org/html/rfc3490#section-5
    1824         * @var string
    1925         */
    2026        const ACE_PREFIX = 'xn--';
     27
     28        /**
     29         * Maximum length of a IDNA URL in ASCII.
     30         *
     31         * @see \WpOrg\Requests\IdnaEncoder::to_ascii()
     32         *
     33         * @since 2.0.0
     34         *
     35         * @var int
     36         */
     37        const MAX_LENGTH = 64;
    2138
    2239        /**#@+
    2340         * Bootstrap constant for Punycode
    2441         *
    25          * @see https://tools.ietf.org/html/rfc3492#section-5
     42         * @link https://tools.ietf.org/html/rfc3492#section-5
    2643         * @var int
    2744         */
     
    3855         * Encode a hostname using Punycode
    3956         *
    40          * @param string $string Hostname
     57         * @param string|Stringable $hostname Hostname
    4158         * @return string Punycode-encoded hostname
    42          */
    43         public static function encode($string) {
    44                 $parts = explode('.', $string);
     59         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or a stringable object.
     60         */
     61        public static function encode($hostname) {
     62                if (InputValidator::is_string_or_stringable($hostname) === false) {
     63                        throw InvalidArgument::create(1, '$hostname', 'string|Stringable', gettype($hostname));
     64                }
     65
     66                $parts = explode('.', $hostname);
    4567                foreach ($parts as &$part) {
    4668                        $part = self::to_ascii($part);
     
    5072
    5173        /**
    52          * Convert a UTF-8 string to an ASCII string using Punycode
    53          *
    54          * @throws Requests_Exception Provided string longer than 64 ASCII characters (`idna.provided_too_long`)
    55          * @throws Requests_Exception Prepared string longer than 64 ASCII characters (`idna.prepared_too_long`)
    56          * @throws Requests_Exception Provided string already begins with xn-- (`idna.provided_is_prefixed`)
    57          * @throws Requests_Exception Encoded string longer than 64 ASCII characters (`idna.encoded_too_long`)
    58          *
    59          * @param string $string ASCII or UTF-8 string (max length 64 characters)
     74         * Convert a UTF-8 text string to an ASCII string using Punycode
     75         *
     76         * @param string $text ASCII or UTF-8 string (max length 64 characters)
    6077         * @return string ASCII string
    61          */
    62         public static function to_ascii($string) {
    63                 // Step 1: Check if the string is already ASCII
    64                 if (self::is_ascii($string)) {
     78         *
     79         * @throws \WpOrg\Requests\Exception Provided string longer than 64 ASCII characters (`idna.provided_too_long`)
     80         * @throws \WpOrg\Requests\Exception Prepared string longer than 64 ASCII characters (`idna.prepared_too_long`)
     81         * @throws \WpOrg\Requests\Exception Provided string already begins with xn-- (`idna.provided_is_prefixed`)
     82         * @throws \WpOrg\Requests\Exception Encoded string longer than 64 ASCII characters (`idna.encoded_too_long`)
     83         */
     84        public static function to_ascii($text) {
     85                // Step 1: Check if the text is already ASCII
     86                if (self::is_ascii($text)) {
    6587                        // Skip to step 7
    66                         if (strlen($string) < 64) {
    67                                 return $string;
    68                         }
    69 
    70                         throw new Requests_Exception('Provided string is too long', 'idna.provided_too_long', $string);
     88                        if (strlen($text) < self::MAX_LENGTH) {
     89                                return $text;
     90                        }
     91
     92                        throw new Exception('Provided string is too long', 'idna.provided_too_long', $text);
    7193                }
    7294
    7395                // Step 2: nameprep
    74                 $string = self::nameprep($string);
     96                $text = self::nameprep($text);
    7597
    7698                // Step 3: UseSTD3ASCIIRules is false, continue
    7799                // Step 4: Check if it's ASCII now
    78                 if (self::is_ascii($string)) {
     100                if (self::is_ascii($text)) {
    79101                        // Skip to step 7
    80                         if (strlen($string) < 64) {
    81                                 return $string;
    82                         }
    83 
    84                         throw new Requests_Exception('Prepared string is too long', 'idna.prepared_too_long', $string);
     102                        /*
     103                         * As the `nameprep()` method returns the original string, this code will never be reached until
     104                         * that method is properly implemented.
     105                         */
     106                        // @codeCoverageIgnoreStart
     107                        if (strlen($text) < self::MAX_LENGTH) {
     108                                return $text;
     109                        }
     110
     111                        throw new Exception('Prepared string is too long', 'idna.prepared_too_long', $text);
     112                        // @codeCoverageIgnoreEnd
    85113                }
    86114
    87115                // Step 5: Check ACE prefix
    88                 if (strpos($string, self::ACE_PREFIX) === 0) {
    89                         throw new Requests_Exception('Provided string begins with ACE prefix', 'idna.provided_is_prefixed', $string);
     116                if (strpos($text, self::ACE_PREFIX) === 0) {
     117                        throw new Exception('Provided string begins with ACE prefix', 'idna.provided_is_prefixed', $text);
    90118                }
    91119
    92120                // Step 6: Encode with Punycode
    93                 $string = self::punycode_encode($string);
     121                $text = self::punycode_encode($text);
    94122
    95123                // Step 7: Prepend ACE prefix
    96                 $string = self::ACE_PREFIX . $string;
     124                $text = self::ACE_PREFIX . $text;
    97125
    98126                // Step 8: Check size
    99                 if (strlen($string) < 64) {
    100                         return $string;
    101                 }
    102 
    103                 throw new Requests_Exception('Encoded string is too long', 'idna.encoded_too_long', $string);
    104         }
    105 
    106         /**
    107          * Check whether a given string contains only ASCII characters
     127                if (strlen($text) < self::MAX_LENGTH) {
     128                        return $text;
     129                }
     130
     131                throw new Exception('Encoded string is too long', 'idna.encoded_too_long', $text);
     132        }
     133
     134        /**
     135         * Check whether a given text string contains only ASCII characters
    108136         *
    109137         * @internal (Testing found regex was the fastest implementation)
    110138         *
    111          * @param string $string
    112          * @return bool Is the string ASCII-only?
    113          */
    114         protected static function is_ascii($string) {
    115                 return (preg_match('/(?:[^\x00-\x7F])/', $string) !== 1);
    116         }
    117 
    118         /**
    119          * Prepare a string for use as an IDNA name
     139         * @param string $text
     140         * @return bool Is the text string ASCII-only?
     141         */
     142        protected static function is_ascii($text) {
     143                return (preg_match('/(?:[^\x00-\x7F])/', $text) !== 1);
     144        }
     145
     146        /**
     147         * Prepare a text string for use as an IDNA name
    120148         *
    121149         * @todo Implement this based on RFC 3491 and the newer 5891
    122          * @param string $string
     150         * @param string $text
    123151         * @return string Prepared string
    124152         */
    125         protected static function nameprep($string) {
    126                 return $string;
     153        protected static function nameprep($text) {
     154                return $text;
    127155        }
    128156
     
    130158         * Convert a UTF-8 string to a UCS-4 codepoint array
    131159         *
    132          * Based on Requests_IRI::replace_invalid_with_pct_encoding()
    133          *
    134          * @throws Requests_Exception Invalid UTF-8 codepoint (`idna.invalidcodepoint`)
     160         * Based on \WpOrg\Requests\Iri::replace_invalid_with_pct_encoding()
     161         *
    135162         * @param string $input
    136163         * @return array Unicode code points
     164         *
     165         * @throws \WpOrg\Requests\Exception Invalid UTF-8 codepoint (`idna.invalidcodepoint`)
    137166         */
    138167        protected static function utf8_to_codepoints($input) {
    139                 $codepoints = array();
     168                $codepoints = [];
    140169
    141170                // Get number of bytes
     
    172201                        // Invalid byte:
    173202                        else {
    174                                 throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $value);
     203                                throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $value);
    175204                        }
    176205
    177206                        if ($remaining > 0) {
    178207                                if ($position + $length > $strlen) {
    179                                         throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
     208                                        throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
    180209                                }
    181210                                for ($position++; $remaining > 0; $position++) {
     
    184213                                        // If it is invalid, count the sequence as invalid and reprocess the current byte:
    185214                                        if (($value & 0xC0) !== 0x80) {
    186                                                 throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
     215                                                throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
    187216                                        }
    188217
     
    209238                                )
    210239                        ) {
    211                                 throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
     240                                throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
    212241                        }
    213242
     
    222251         *
    223252         * @internal Pseudo-code from Section 6.3 is commented with "#" next to relevant code
    224          * @throws Requests_Exception On character outside of the domain (never happens with Punycode) (`idna.character_outside_domain`)
    225253         *
    226254         * @param string $input UTF-8 encoded string to encode
    227255         * @return string Punycode-encoded string
     256         *
     257         * @throws \WpOrg\Requests\Exception On character outside of the domain (never happens with Punycode) (`idna.character_outside_domain`)
    228258         */
    229259        public static function punycode_encode($input) {
     
    240270                // copy them to the output in order
    241271                $codepoints = self::utf8_to_codepoints($input);
    242                 $extended   = array();
     272                $extended   = [];
    243273
    244274                foreach ($codepoints as $char) {
     
    253283                        // @codeCoverageIgnoreStart
    254284                        elseif ($char < $n) {
    255                                 throw new Requests_Exception('Invalid character', 'idna.character_outside_domain', $char);
     285                                throw new Exception('Invalid character', 'idna.character_outside_domain', $char);
    256286                        }
    257287                        // @codeCoverageIgnoreEnd
     
    333363         * Convert a digit to its respective character
    334364         *
    335          * @see https://tools.ietf.org/html/rfc3492#section-5
    336          * @throws Requests_Exception On invalid digit (`idna.invalid_digit`)
     365         * @link https://tools.ietf.org/html/rfc3492#section-5
    337366         *
    338367         * @param int $digit Digit in the range 0-35
    339368         * @return string Single character corresponding to digit
     369         *
     370         * @throws \WpOrg\Requests\Exception On invalid digit (`idna.invalid_digit`)
    340371         */
    341372        protected static function digit_to_char($digit) {
     
    343374                // As far as I know, this never happens, but still good to be sure.
    344375                if ($digit < 0 || $digit > 35) {
    345                         throw new Requests_Exception(sprintf('Invalid digit %d', $digit), 'idna.invalid_digit', $digit);
     376                        throw new Exception(sprintf('Invalid digit %d', $digit), 'idna.invalid_digit', $digit);
    346377                }
    347378                // @codeCoverageIgnoreEnd
     
    353384         * Adapt the bias
    354385         *
    355          * @see https://tools.ietf.org/html/rfc3492#section-6.1
     386         * @link https://tools.ietf.org/html/rfc3492#section-6.1
    356387         * @param int $delta
    357388         * @param int $numpoints
  • trunk/src/wp-includes/Requests/Ipv6.php

    r52243 r52244  
    33 * Class to validate and to work with IPv6 addresses
    44 *
    5  * @package Requests
    6  * @subpackage Utilities
     5 * @package Requests\Utilities
    76 */
     7
     8namespace WpOrg\Requests;
     9
     10use WpOrg\Requests\Exception\InvalidArgument;
     11use WpOrg\Requests\Utility\InputValidator;
    812
    913/**
     
    1317 * entirely rewritten.
    1418 *
    15  * @package Requests
    16  * @subpackage Utilities
     19 * @package Requests\Utilities
    1720 */
    18 class Requests_IPv6 {
     21final class Ipv6 {
    1922        /**
    2023         * Uncompresses an IPv6 address
     
    3134         * @author Josh Peck <jmp at joshpeck dot org>
    3235         * @copyright 2003-2005 The PHP Group
    33          * @license http://www.opensource.org/licenses/bsd-license.php
    34          * @param string $ip An IPv6 address
     36         * @license https://opensource.org/licenses/bsd-license.php
     37         *
     38         * @param string|Stringable $ip An IPv6 address
    3539         * @return string The uncompressed IPv6 address
     40         *
     41         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or a stringable object.
    3642         */
    3743        public static function uncompress($ip) {
     44                if (InputValidator::is_string_or_stringable($ip) === false) {
     45                        throw InvalidArgument::create(1, '$ip', 'string|Stringable', gettype($ip));
     46                }
     47
     48                $ip = (string) $ip;
     49
    3850                if (substr_count($ip, '::') !== 1) {
    3951                        return $ip;
     
    7991         *           0:0:0:0:0:0:0:1        ->  ::1
    8092         *
    81          * @see uncompress()
     93         * @see \WpOrg\Requests\IPv6::uncompress()
     94         *
    8295         * @param string $ip An IPv6 address
    8396         * @return string The compressed IPv6 address
    8497         */
    8598        public static function compress($ip) {
    86                 // Prepare the IP to be compressed
     99                // Prepare the IP to be compressed.
     100                // Note: Input validation is handled in the `uncompress()` method, which is the first call made in this method.
    87101                $ip       = self::uncompress($ip);
    88102                $ip_parts = self::split_v6_v4($ip);
     
    125139         * @return string[] [0] contains the IPv6 represented part, and [1] the IPv4 represented part
    126140         */
    127         protected static function split_v6_v4($ip) {
     141        private static function split_v6_v4($ip) {
    128142                if (strpos($ip, '.') !== false) {
    129143                        $pos       = strrpos($ip, ':');
    130144                        $ipv6_part = substr($ip, 0, $pos);
    131145                        $ipv4_part = substr($ip, $pos + 1);
    132                         return array($ipv6_part, $ipv4_part);
    133                 }
    134                 else {
    135                         return array($ip, '');
     146                        return [$ipv6_part, $ipv4_part];
     147                }
     148                else {
     149                        return [$ip, ''];
    136150                }
    137151        }
     
    146160         */
    147161        public static function check_ipv6($ip) {
     162                // Note: Input validation is handled in the `uncompress()` method, which is the first call made in this method.
    148163                $ip                = self::uncompress($ip);
    149164                list($ipv6, $ipv4) = self::split_v6_v4($ip);
  • trunk/src/wp-includes/Requests/Iri.php

    r52243 r52244  
    33 * IRI parser/serialiser/normaliser
    44 *
    5  * @package Requests
    6  * @subpackage Utilities
     5 * @package Requests\Utilities
    76 */
     7
     8namespace WpOrg\Requests;
     9
     10use WpOrg\Requests\Exception;
     11use WpOrg\Requests\Exception\InvalidArgument;
     12use WpOrg\Requests\Ipv6;
     13use WpOrg\Requests\Port;
     14use WpOrg\Requests\Utility\InputValidator;
    815
    916/**
     
    3946 * POSSIBILITY OF SUCH DAMAGE.
    4047 *
    41  * @package Requests
    42  * @subpackage Utilities
     48 * @package Requests\Utilities
    4349 * @author Geoffrey Sneddon
    4450 * @author Steve Minutillo
    4551 * @copyright 2007-2009 Geoffrey Sneddon and Steve Minutillo
    46  * @license http://www.opensource.org/licenses/bsd-license.php
     52 * @license https://opensource.org/licenses/bsd-license.php
    4753 * @link http://hg.gsnedders.com/iri/
    4854 *
    4955 * @property string $iri IRI we're working with
    50  * @property-read string $uri IRI in URI form, {@see to_uri}
     56 * @property-read string $uri IRI in URI form, {@see \WpOrg\Requests\IRI::to_uri()}
    5157 * @property string $scheme Scheme part of the IRI
    5258 * @property string $authority Authority part, formatted for a URI (userinfo + host + port)
     
    6470 * @property string $ifragment Fragment part of the IRI (after '#')
    6571 */
    66 class Requests_IRI {
     72class Iri {
    6773        /**
    6874         * Scheme
     
    124130        protected $normalization = array(
    125131                'acap' => array(
    126                         'port' => 674
     132                        'port' => Port::ACAP,
    127133                ),
    128134                'dict' => array(
    129                         'port' => 2628
     135                        'port' => Port::DICT,
    130136                ),
    131137                'file' => array(
    132                         'ihost' => 'localhost'
     138                        'ihost' => 'localhost',
    133139                ),
    134140                'http' => array(
    135                         'port' => 80,
     141                        'port' => Port::HTTP,
    136142                ),
    137143                'https' => array(
    138                         'port' => 443,
     144                        'port' => Port::HTTPS,
    139145                ),
    140146        );
     
    241247         * Create a new IRI object, from a specified string
    242248         *
    243          * @param string|null $iri
     249         * @param string|Stringable|null $iri
     250         *
     251         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $iri argument is not a string, Stringable or null.
    244252         */
    245253        public function __construct($iri = null) {
     254                if ($iri !== null && InputValidator::is_string_or_stringable($iri) === false) {
     255                        throw InvalidArgument::create(1, '$iri', 'string|Stringable|null', gettype($iri));
     256                }
     257
    246258                $this->set_iri($iri);
    247259        }
     
    252264         * Returns false if $base is not absolute, otherwise an IRI.
    253265         *
    254          * @param Requests_IRI|string $base (Absolute) Base IRI
    255          * @param Requests_IRI|string $relative Relative IRI
    256          * @return Requests_IRI|false
     266         * @param \WpOrg\Requests\Iri|string $base (Absolute) Base IRI
     267         * @param \WpOrg\Requests\Iri|string $relative Relative IRI
     268         * @return \WpOrg\Requests\Iri|false
    257269         */
    258270        public static function absolutize($base, $relative) {
    259                 if (!($relative instanceof Requests_IRI)) {
    260                         $relative = new Requests_IRI($relative);
     271                if (!($relative instanceof self)) {
     272                        $relative = new self($relative);
    261273                }
    262274                if (!$relative->is_valid()) {
     
    267279                }
    268280
    269                 if (!($base instanceof Requests_IRI)) {
    270                         $base = new Requests_IRI($base);
     281                if (!($base instanceof self)) {
     282                        $base = new self($base);
    271283                }
    272284                if ($base->scheme === null || !$base->is_valid()) {
     
    280292                        }
    281293                        else {
    282                                 $target = new Requests_IRI;
     294                                $target = new self;
    283295                                $target->scheme = $base->scheme;
    284296                                $target->iuserinfo = $base->iuserinfo;
     
    331343                $has_match = preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match);
    332344                if (!$has_match) {
    333                         throw new Requests_Exception('Cannot parse supplied IRI', 'iri.cannot_parse', $iri);
     345                        throw new Exception('Cannot parse supplied IRI', 'iri.cannot_parse', $iri);
    334346                }
    335347
     
    414426         * Replace invalid character with percent encoding
    415427         *
    416          * @param string $string Input string
     428         * @param string $text Input string
    417429         * @param string $extra_chars Valid characters not in iunreserved or
    418430         *                            iprivate (this is ASCII-only)
     
    420432         * @return string
    421433         */
    422         protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) {
     434        protected function replace_invalid_with_pct_encoding($text, $extra_chars, $iprivate = false) {
    423435                // Normalize as many pct-encoded sections as possible
    424                 $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $string);
     436                $text = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $text);
    425437
    426438                // Replace invalid percent characters
    427                 $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
     439                $text = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $text);
    428440
    429441                // Add unreserved and % to $extra_chars (the latter is safe because all
     
    433445                // Now replace any bytes that aren't allowed with their pct-encoded versions
    434446                $position = 0;
    435                 $strlen = strlen($string);
    436                 while (($position += strspn($string, $extra_chars, $position)) < $strlen) {
    437                         $value = ord($string[$position]);
     447                $strlen = strlen($text);
     448                while (($position += strspn($text, $extra_chars, $position)) < $strlen) {
     449                        $value = ord($text[$position]);
    438450
    439451                        // Start position
     
    472484                                if ($position + $length <= $strlen) {
    473485                                        for ($position++; $remaining; $position++) {
    474                                                 $value = ord($string[$position]);
     486                                                $value = ord($text[$position]);
    475487
    476488                                                // Check that the byte is valid, then add it to the character:
     
    523535
    524536                                for ($j = $start; $j <= $position; $j++) {
    525                                         $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
     537                                        $text = substr_replace($text, sprintf('%%%02X', ord($text[$j])), $j, 1);
    526538                                        $j += 2;
    527539                                        $position += 2;
     
    531543                }
    532544
    533                 return $string;
     545                return $text;
    534546        }
    535547
     
    540552         * encoded characters in iunreserved
    541553         *
    542          * @param array $match PCRE match
     554         * @param array $regex_match PCRE match
    543555         * @return string Replacement
    544556         */
    545         protected function remove_iunreserved_percent_encoded($match) {
     557        protected function remove_iunreserved_percent_encoded($regex_match) {
    546558                // As we just have valid percent encoded sequences we can just explode
    547559                // and ignore the first member of the returned array (an empty string).
    548                 $bytes = explode('%', $match[0]);
     560                $bytes = explode('%', $regex_match[0]);
    549561
    550562                // Initialize the new string (this is what will be returned) and that
     
    722734                        return true;
    723735                }
     736
     737                $iri = (string) $iri;
     738
    724739                if (isset($cache[$iri])) {
    725740                        list($this->scheme,
     
    734749                }
    735750
    736                 $parsed = $this->parse_iri((string) $iri);
     751                $parsed = $this->parse_iri($iri);
    737752
    738753                $return = $this->set_scheme($parsed['scheme'])
     
    864879                }
    865880                if (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') {
    866                         if (Requests_IPv6::check_ipv6(substr($ihost, 1, -1))) {
    867                                 $this->ihost = '[' . Requests_IPv6::compress(substr($ihost, 1, -1)) . ']';
     881                        if (Ipv6::check_ipv6(substr($ihost, 1, -1))) {
     882                                $this->ihost = '[' . Ipv6::compress(substr($ihost, 1, -1)) . ']';
    868883                        }
    869884                        else {
     
    9861001         * Convert an IRI to a URI (or parts thereof)
    9871002         *
    988          * @param string|bool IRI to convert (or false from {@see get_iri})
     1003         * @param string|bool $iri IRI to convert (or false from {@see \WpOrg\Requests\IRI::get_iri()})
    9891004         * @return string|false URI if IRI is valid, false otherwise.
    9901005         */
    991         protected function to_uri($string) {
    992                 if (!is_string($string)) {
     1006        protected function to_uri($iri) {
     1007                if (!is_string($iri)) {
    9931008                        return false;
    9941009                }
     
    10001015
    10011016                $position = 0;
    1002                 $strlen = strlen($string);
    1003                 while (($position += strcspn($string, $non_ascii, $position)) < $strlen) {
    1004                         $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1);
     1017                $strlen = strlen($iri);
     1018                while (($position += strcspn($iri, $non_ascii, $position)) < $strlen) {
     1019                        $iri = substr_replace($iri, sprintf('%%%02X', ord($iri[$position])), $position, 1);
    10051020                        $position += 3;
    10061021                        $strlen += 2;
    10071022                }
    10081023
    1009                 return $string;
     1024                return $iri;
    10101025        }
    10111026
  • trunk/src/wp-includes/Requests/Proxy.php

    r50842 r52244  
    33 * Proxy connection interface
    44 *
    5  * @package Requests
    6  * @subpackage Proxy
    7  * @since 1.6
     5 * @package Requests\Proxy
     6 * @since   1.6
    87 */
     8
     9namespace WpOrg\Requests;
     10
     11use WpOrg\Requests\Hooks;
    912
    1013/**
     
    1619 * makes it much easier for users to use your provider.
    1720 *
    18  * @see Requests_Hooks
    19  * @package Requests
    20  * @subpackage Proxy
    21  * @since 1.6
     21 * @see \WpOrg\Requests\Hooks
     22 *
     23 * @package Requests\Proxy
     24 * @since   1.6
    2225 */
    23 interface Requests_Proxy {
     26interface Proxy {
    2427        /**
    2528         * Register hooks as needed
    2629         *
    27          * This method is called in {@see Requests::request} when the user has set
    28          * an instance as the 'auth' option. Use this callback to register all the
     30         * This method is called in {@see \WpOrg\Requests\Requests::request()} when the user
     31         * has set an instance as the 'auth' option. Use this callback to register all the
    2932         * hooks you'll need.
    3033         *
    31          * @see Requests_Hooks::register
    32          * @param Requests_Hooks $hooks Hook system
     34         * @see \WpOrg\Requests\Hooks::register()
     35         * @param \WpOrg\Requests\Hooks $hooks Hook system
    3336         */
    34         public function register(Requests_Hooks $hooks);
     37        public function register(Hooks $hooks);
    3538}
  • trunk/src/wp-includes/Requests/Proxy/Http.php

    r52243 r52244  
    33 * HTTP Proxy connection interface
    44 *
    5  * @package Requests
    6  * @subpackage Proxy
    7  * @since 1.6
     5 * @package Requests\Proxy
     6 * @since   1.6
    87 */
     8
     9namespace WpOrg\Requests\Proxy;
     10
     11use WpOrg\Requests\Exception\ArgumentCount;
     12use WpOrg\Requests\Exception\InvalidArgument;
     13use WpOrg\Requests\Hooks;
     14use WpOrg\Requests\Proxy;
    915
    1016/**
     
    1319 * Provides a handler for connection via an HTTP proxy
    1420 *
    15  * @package Requests
    16  * @subpackage Proxy
    17  * @since 1.6
     21 * @package Requests\Proxy
     22 * @since   1.6
    1823 */
    19 class Requests_Proxy_HTTP implements Requests_Proxy {
     24final class Http implements Proxy {
    2025        /**
    2126         * Proxy host and port
     
    5257         *
    5358         * @since 1.6
    54          * @throws Requests_Exception On incorrect number of arguments (`authbasicbadargs`)
    55          * @param array|null $args Array of user and password. Must have exactly two elements
     59         *
     60         * @param array|string|null $args Proxy as a string or an array of proxy, user and password.
     61         *                                When passed as an array, must have exactly one (proxy)
     62         *                                or three elements (proxy, user, password).
     63         *
     64         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not an array, a string or null.
     65         * @throws \WpOrg\Requests\Exception\ArgumentCount On incorrect number of arguments (`proxyhttpbadargs`)
    5666         */
    5767        public function __construct($args = null) {
     
    6878                        }
    6979                        else {
    70                                 throw new Requests_Exception('Invalid number of arguments', 'proxyhttpbadargs');
     80                                throw ArgumentCount::create(
     81                                        'an array with exactly one element or exactly three elements',
     82                                        count($args),
     83                                        'proxyhttpbadargs'
     84                                );
    7185                        }
     86                } elseif ($args !== null) {
     87                        throw InvalidArgument::create(1, '$args', 'array|string|null', gettype($args));
    7288                }
    7389        }
     
    7793         *
    7894         * @since 1.6
    79          * @see curl_before_send
    80          * @see fsockopen_remote_socket
    81          * @see fsockopen_remote_host_path
    82          * @see fsockopen_header
    83          * @param Requests_Hooks $hooks Hook system
     95         * @see \WpOrg\Requests\Proxy\HTTP::curl_before_send()
     96         * @see \WpOrg\Requests\Proxy\HTTP::fsockopen_remote_socket()
     97         * @see \WpOrg\Requests\Proxy\HTTP::fsockopen_remote_host_path()
     98         * @see \WpOrg\Requests\Proxy\HTTP::fsockopen_header()
     99         * @param \WpOrg\Requests\Hooks $hooks Hook system
    84100         */
    85         public function register(Requests_Hooks $hooks) {
    86                 $hooks->register('curl.before_send', array($this, 'curl_before_send'));
     101        public function register(Hooks $hooks) {
     102                $hooks->register('curl.before_send', [$this, 'curl_before_send']);
    87103
    88                 $hooks->register('fsockopen.remote_socket', array($this, 'fsockopen_remote_socket'));
    89                 $hooks->register('fsockopen.remote_host_path', array($this, 'fsockopen_remote_host_path'));
     104                $hooks->register('fsockopen.remote_socket', [$this, 'fsockopen_remote_socket']);
     105                $hooks->register('fsockopen.remote_host_path', [$this, 'fsockopen_remote_host_path']);
    90106                if ($this->use_authentication) {
    91                         $hooks->register('fsockopen.after_headers', array($this, 'fsockopen_header'));
     107                        $hooks->register('fsockopen.after_headers', [$this, 'fsockopen_header']);
    92108                }
    93109        }
     
    97113         *
    98114         * @since 1.6
    99          * @param resource $handle cURL resource
     115         * @param resource|\CurlHandle $handle cURL handle
    100116         */
    101117        public function curl_before_send(&$handle) {
  • 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, Rubys 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}
  • trunk/src/wp-includes/Requests/Response.php

    r50842 r52244  
    33 * HTTP response class
    44 *
    5  * Contains a response from Requests::request()
     5 * Contains a response from \WpOrg\Requests\Requests::request()
     6 *
    67 * @package Requests
    78 */
     9
     10namespace WpOrg\Requests;
     11
     12use WpOrg\Requests\Cookie\Jar;
     13use WpOrg\Requests\Exception;
     14use WpOrg\Requests\Exception\Http;
     15use WpOrg\Requests\Response\Headers;
    816
    917/**
    1018 * HTTP response class
    1119 *
    12  * Contains a response from Requests::request()
     20 * Contains a response from \WpOrg\Requests\Requests::request()
     21 *
    1322 * @package Requests
    1423 */
    15 class Requests_Response {
    16         /**
    17          * Constructor
    18          */
    19         public function __construct() {
    20                 $this->headers = new Requests_Response_Headers();
    21                 $this->cookies = new Requests_Cookie_Jar();
    22         }
     24class Response {
    2325
    2426        /**
     
    3941         * Headers, as an associative array
    4042         *
    41          * @var Requests_Response_Headers Array-like object representing headers
     43         * @var \WpOrg\Requests\Response\Headers Array-like object representing headers
    4244         */
    43         public $headers = array();
     45        public $headers = [];
    4446
    4547        /**
     
    8183         * Previous requests (from redirects)
    8284         *
    83          * @var array Array of Requests_Response objects
     85         * @var array Array of \WpOrg\Requests\Response objects
    8486         */
    85         public $history = array();
     87        public $history = [];
    8688
    8789        /**
    8890         * Cookies from the request
    8991         *
    90          * @var Requests_Cookie_Jar Array-like object representing a cookie jar
     92         * @var \WpOrg\Requests\Cookie\Jar Array-like object representing a cookie jar
    9193         */
    92         public $cookies = array();
     94        public $cookies = [];
     95
     96        /**
     97         * Constructor
     98         */
     99        public function __construct() {
     100                $this->headers = new Headers();
     101                $this->cookies = new Jar();
     102        }
    93103
    94104        /**
     
    99109        public function is_redirect() {
    100110                $code = $this->status_code;
    101                 return in_array($code, array(300, 301, 302, 303, 307), true) || $code > 307 && $code < 400;
     111                return in_array($code, [300, 301, 302, 303, 307], true) || $code > 307 && $code < 400;
    102112        }
    103113
     
    105115         * Throws an exception if the request was not successful
    106116         *
    107          * @throws Requests_Exception If `$allow_redirects` is false, and code is 3xx (`response.no_redirects`)
    108          * @throws Requests_Exception_HTTP On non-successful status code. Exception class corresponds to code (e.g. {@see Requests_Exception_HTTP_404})
    109117         * @param boolean $allow_redirects Set to false to throw on a 3xx as well
     118         *
     119         * @throws \WpOrg\Requests\Exception If `$allow_redirects` is false, and code is 3xx (`response.no_redirects`)
     120         * @throws \WpOrg\Requests\Exception\Http On non-successful status code. Exception class corresponds to "Status" + code (e.g. {@see \WpOrg\Requests\Exception\Http\Status404})
    110121         */
    111122        public function throw_for_status($allow_redirects = true) {
    112123                if ($this->is_redirect()) {
    113                         if (!$allow_redirects) {
    114                                 throw new Requests_Exception('Redirection not allowed', 'response.no_redirects', $this);
     124                        if ($allow_redirects !== true) {
     125                                throw new Exception('Redirection not allowed', 'response.no_redirects', $this);
    115126                        }
    116127                }
    117128                elseif (!$this->success) {
    118                         $exception = Requests_Exception_HTTP::get_class($this->status_code);
     129                        $exception = Http::get_class($this->status_code);
    119130                        throw new $exception(null, $this);
    120131                }
    121132        }
     133
     134        /**
     135         * JSON decode the response body.
     136         *
     137         * The method parameters are the same as those for the PHP native `json_decode()` function.
     138         *
     139         * @link https://php.net/json-decode
     140         *
     141         * @param ?bool $associative Optional. When `true`, JSON objects will be returned as associative arrays;
     142         *                           When `false`, JSON objects will be returned as objects.
     143         *                           When `null`, JSON objects will be returned as associative arrays
     144         *                           or objects depending on whether `JSON_OBJECT_AS_ARRAY` is set in the flags.
     145         *                           Defaults to `true` (in contrast to the PHP native default of `null`).
     146         * @param int   $depth       Optional. Maximum nesting depth of the structure being decoded.
     147         *                           Defaults to `512`.
     148         * @param int   $options     Optional. Bitmask of JSON_BIGINT_AS_STRING, JSON_INVALID_UTF8_IGNORE,
     149         *                           JSON_INVALID_UTF8_SUBSTITUTE, JSON_OBJECT_AS_ARRAY, JSON_THROW_ON_ERROR.
     150         *                           Defaults to `0` (no options set).
     151         *
     152         * @return array
     153         *
     154         * @throws \WpOrg\Requests\Exception If `$this->body` is not valid json.
     155         */
     156        public function decode_body($associative = true, $depth = 512, $options = 0) {
     157                $data = json_decode($this->body, $associative, $depth, $options);
     158
     159                if (json_last_error() !== JSON_ERROR_NONE) {
     160                        $last_error = json_last_error_msg();
     161                        throw new Exception('Unable to parse JSON data: ' . $last_error, 'response.invalid', $this);
     162                }
     163
     164                return $data;
     165        }
    122166}
  • trunk/src/wp-includes/Requests/Response/Headers.php

    r50842 r52244  
    66 */
    77
     8namespace WpOrg\Requests\Response;
     9
     10use WpOrg\Requests\Exception;
     11use WpOrg\Requests\Exception\InvalidArgument;
     12use WpOrg\Requests\Utility\CaseInsensitiveDictionary;
     13use WpOrg\Requests\Utility\FilteredIterator;
     14
    815/**
    916 * Case-insensitive dictionary, suitable for HTTP headers
     
    1118 * @package Requests
    1219 */
    13 class Requests_Response_Headers extends Requests_Utility_CaseInsensitiveDictionary {
     20class Headers extends CaseInsensitiveDictionary {
    1421        /**
    1522         * Get the given header
    1623         *
    17          * Unlike {@see self::getValues()}, this returns a string. If there are
     24         * Unlike {@see \WpOrg\Requests\Response\Headers::getValues()}, this returns a string. If there are
    1825         * multiple values, it concatenates them with a comma as per RFC2616.
    1926         *
     
    2128         * Set-Cookie headers.
    2229         *
    23          * @param string $key
     30         * @param string $offset
    2431         * @return string|null Header value
    2532         */
    26         public function offsetGet($key) {
    27                 $key = strtolower($key);
    28                 if (!isset($this->data[$key])) {
     33        public function offsetGet($offset) {
     34                if (is_string($offset)) {
     35                        $offset = strtolower($offset);
     36                }
     37
     38                if (!isset($this->data[$offset])) {
    2939                        return null;
    3040                }
    3141
    32                 return $this->flatten($this->data[$key]);
     42                return $this->flatten($this->data[$offset]);
    3343        }
    3444
     
    3646         * Set the given item
    3747         *
    38          * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`)
     48         * @param string $offset Item name
     49         * @param string $value Item value
    3950         *
    40          * @param string $key Item name
    41          * @param string $value Item value
     51         * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`)
    4252         */
    43         public function offsetSet($key, $value) {
    44                 if ($key === null) {
    45                         throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset');
     53        public function offsetSet($offset, $value) {
     54                if ($offset === null) {
     55                        throw new Exception('Object is a dictionary, not a list', 'invalidset');
    4656                }
    4757
    48                 $key = strtolower($key);
    49 
    50                 if (!isset($this->data[$key])) {
    51                         $this->data[$key] = array();
     58                if (is_string($offset)) {
     59                        $offset = strtolower($offset);
    5260                }
    5361
    54                 $this->data[$key][] = $value;
     62                if (!isset($this->data[$offset])) {
     63                        $this->data[$offset] = [];
     64                }
     65
     66                $this->data[$offset][] = $value;
    5567        }
    5668
     
    5870         * Get all values for a given header
    5971         *
    60          * @param string $key
     72         * @param string $offset
    6173         * @return array|null Header values
     74         *
     75         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not valid as an array key.
    6276         */
    63         public function getValues($key) {
    64                 $key = strtolower($key);
    65                 if (!isset($this->data[$key])) {
     77        public function getValues($offset) {
     78                if (!is_string($offset) && !is_int($offset)) {
     79                        throw InvalidArgument::create(1, '$offset', 'string|int', gettype($offset));
     80                }
     81
     82                $offset = strtolower($offset);
     83                if (!isset($this->data[$offset])) {
    6684                        return null;
    6785                }
    6886
    69                 return $this->data[$key];
     87                return $this->data[$offset];
    7088        }
    7189
     
    7896         * @param string|array $value Value to flatten
    7997         * @return string Flattened value
     98         *
     99         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or an array.
    80100         */
    81101        public function flatten($value) {
    82                 if (is_array($value)) {
    83                         $value = implode(',', $value);
     102                if (is_string($value)) {
     103                        return $value;
    84104                }
    85105
    86                 return $value;
     106                if (is_array($value)) {
     107                        return implode(',', $value);
     108                }
     109
     110                throw InvalidArgument::create(1, '$value', 'string|array', gettype($value));
    87111        }
    88112
     
    90114         * Get an iterator for the data
    91115         *
    92          * Converts the internal
    93          * @return ArrayIterator
     116         * Converts the internally stored values to a comma-separated string if there is more
     117         * than one value for a key.
     118         *
     119         * @return \ArrayIterator
    94120         */
    95121        public function getIterator() {
    96                 return new Requests_Utility_FilteredIterator($this->data, array($this, 'flatten'));
     122                return new FilteredIterator($this->data, [$this, 'flatten']);
    97123        }
    98124}
  • trunk/src/wp-includes/Requests/Session.php

    r50842 r52244  
    33 * Session handler for persistent requests and default parameters
    44 *
    5  * @package Requests
    6  * @subpackage Session Handler
     5 * @package Requests\SessionHandler
    76 */
     7
     8namespace WpOrg\Requests;
     9
     10use WpOrg\Requests\Cookie\Jar;
     11use WpOrg\Requests\Exception\InvalidArgument;
     12use WpOrg\Requests\Iri;
     13use WpOrg\Requests\Requests;
     14use WpOrg\Requests\Utility\InputValidator;
    815
    916/**
     
    1522 * a shared cookie jar), then overridden for individual requests.
    1623 *
    17  * @package Requests
    18  * @subpackage Session Handler
     24 * @package Requests\SessionHandler
    1925 */
    20 class Requests_Session {
     26class Session {
    2127        /**
    2228         * Base URL for requests
     
    3339         * @var array
    3440         */
    35         public $headers = array();
     41        public $headers = [];
    3642
    3743        /**
     
    4349         * @var array
    4450         */
    45         public $data = array();
     51        public $data = [];
    4652
    4753        /**
     
    5662         * @var array
    5763         */
    58         public $options = array();
     64        public $options = [];
    5965
    6066        /**
    6167         * Create a new session
    6268         *
    63          * @param string|null $url Base URL for requests
     69         * @param string|Stringable|null $url Base URL for requests
    6470         * @param array $headers Default headers for requests
    6571         * @param array $data Default data for requests
    6672         * @param array $options Default options for requests
    67          */
    68         public function __construct($url = null, $headers = array(), $data = array(), $options = array()) {
     73         *
     74         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string, Stringable or null.
     75         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $headers argument is not an array.
     76         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data argument is not an array.
     77         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array.
     78         */
     79        public function __construct($url = null, $headers = [], $data = [], $options = []) {
     80                if ($url !== null && InputValidator::is_string_or_stringable($url) === false) {
     81                        throw InvalidArgument::create(1, '$url', 'string|Stringable|null', gettype($url));
     82                }
     83
     84                if (is_array($headers) === false) {
     85                        throw InvalidArgument::create(2, '$headers', 'array', gettype($headers));
     86                }
     87
     88                if (is_array($data) === false) {
     89                        throw InvalidArgument::create(3, '$data', 'array', gettype($data));
     90                }
     91
     92                if (is_array($options) === false) {
     93                        throw InvalidArgument::create(4, '$options', 'array', gettype($options));
     94                }
     95
    6996                $this->url     = $url;
    7097                $this->headers = $headers;
     
    73100
    74101                if (empty($this->options['cookies'])) {
    75                         $this->options['cookies'] = new Requests_Cookie_Jar();
     102                        $this->options['cookies'] = new Jar();
    76103                }
    77104        }
     
    80107         * Get a property's value
    81108         *
    82          * @param string $key Property key
     109         * @param string $name Property name.
    83110         * @return mixed|null Property value, null if none found
    84111         */
    85         public function __get($key) {
    86                 if (isset($this->options[$key])) {
    87                         return $this->options[$key];
     112        public function __get($name) {
     113                if (isset($this->options[$name])) {
     114                        return $this->options[$name];
    88115                }
    89116
     
    94121         * Set a property's value
    95122         *
    96          * @param string $key Property key
     123         * @param string $name Property name.
    97124         * @param mixed $value Property value
    98125         */
    99         public function __set($key, $value) {
    100                 $this->options[$key] = $value;
     126        public function __set($name, $value) {
     127                $this->options[$name] = $value;
    101128        }
    102129
     
    104131         * Remove a property's value
    105132         *
    106          * @param string $key Property key
    107          */
    108         public function __isset($key) {
    109                 return isset($this->options[$key]);
     133         * @param string $name Property name.
     134         */
     135        public function __isset($name) {
     136                return isset($this->options[$name]);
    110137        }
    111138
     
    113140         * Remove a property's value
    114141         *
    115          * @param string $key Property key
    116          */
    117         public function __unset($key) {
    118                 if (isset($this->options[$key])) {
    119                         unset($this->options[$key]);
    120                 }
     142         * @param string $name Property name.
     143         */
     144        public function __unset($name) {
     145                unset($this->options[$name]);
    121146        }
    122147
    123148        /**#@+
    124          * @see request()
     149         * @see \WpOrg\Requests\Session::request()
    125150         * @param string $url
    126151         * @param array $headers
    127152         * @param array $options
    128          * @return Requests_Response
     153         * @return \WpOrg\Requests\Response
    129154         */
    130155        /**
    131156         * Send a GET request
    132157         */
    133         public function get($url, $headers = array(), $options = array()) {
     158        public function get($url, $headers = [], $options = []) {
    134159                return $this->request($url, $headers, null, Requests::GET, $options);
    135160        }
     
    138163         * Send a HEAD request
    139164         */
    140         public function head($url, $headers = array(), $options = array()) {
     165        public function head($url, $headers = [], $options = []) {
    141166                return $this->request($url, $headers, null, Requests::HEAD, $options);
    142167        }
     
    145170         * Send a DELETE request
    146171         */
    147         public function delete($url, $headers = array(), $options = array()) {
     172        public function delete($url, $headers = [], $options = []) {
    148173                return $this->request($url, $headers, null, Requests::DELETE, $options);
    149174        }
     
    151176
    152177        /**#@+
    153          * @see request()
     178         * @see \WpOrg\Requests\Session::request()
    154179         * @param string $url
    155180         * @param array $headers
    156181         * @param array $data
    157182         * @param array $options
    158          * @return Requests_Response
     183         * @return \WpOrg\Requests\Response
    159184         */
    160185        /**
    161186         * Send a POST request
    162187         */
    163         public function post($url, $headers = array(), $data = array(), $options = array()) {
     188        public function post($url, $headers = [], $data = [], $options = []) {
    164189                return $this->request($url, $headers, $data, Requests::POST, $options);
    165190        }
     
    168193         * Send a PUT request
    169194         */
    170         public function put($url, $headers = array(), $data = array(), $options = array()) {
     195        public function put($url, $headers = [], $data = [], $options = []) {
    171196                return $this->request($url, $headers, $data, Requests::PUT, $options);
    172197        }
     
    175200         * Send a PATCH request
    176201         *
    177          * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the
    178          * specification recommends that should send an ETag
     202         * Note: Unlike {@see \WpOrg\Requests\Session::post()} and {@see \WpOrg\Requests\Session::put()},
     203         * `$headers` is required, as the specification recommends that should send an ETag
    179204         *
    180205         * @link https://tools.ietf.org/html/rfc5789
    181206         */
    182         public function patch($url, $headers, $data = array(), $options = array()) {
     207        public function patch($url, $headers, $data = [], $options = []) {
    183208                return $this->request($url, $headers, $data, Requests::PATCH, $options);
    184209        }
     
    191216         * parsing.
    192217         *
    193          * @see Requests::request()
    194          *
    195          * @throws Requests_Exception On invalid URLs (`nonhttp`)
     218         * @see \WpOrg\Requests\Requests::request()
    196219         *
    197220         * @param string $url URL to request
    198221         * @param array $headers Extra headers to send with the request
    199222         * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests
    200          * @param string $type HTTP request type (use Requests constants)
    201          * @param array $options Options for the request (see {@see Requests::request})
    202          * @return Requests_Response
    203          */
    204         public function request($url, $headers = array(), $data = array(), $type = Requests::GET, $options = array()) {
     223         * @param string $type HTTP request type (use \WpOrg\Requests\Requests constants)
     224         * @param array $options Options for the request (see {@see \WpOrg\Requests\Requests::request()})
     225         * @return \WpOrg\Requests\Response
     226         *
     227         * @throws \WpOrg\Requests\Exception On invalid URLs (`nonhttp`)
     228         */
     229        public function request($url, $headers = [], $data = [], $type = Requests::GET, $options = []) {
    205230                $request = $this->merge_request(compact('url', 'headers', 'data', 'options'));
    206231
     
    211236         * Send multiple HTTP requests simultaneously
    212237         *
    213          * @see Requests::request_multiple()
    214          *
    215          * @param array $requests Requests data (see {@see Requests::request_multiple})
    216          * @param array $options Global and default options (see {@see Requests::request})
    217          * @return array Responses (either Requests_Response or a Requests_Exception object)
    218          */
    219         public function request_multiple($requests, $options = array()) {
     238         * @see \WpOrg\Requests\Requests::request_multiple()
     239         *
     240         * @param array $requests Requests data (see {@see \WpOrg\Requests\Requests::request_multiple()})
     241         * @param array $options Global and default options (see {@see \WpOrg\Requests\Requests::request()})
     242         * @return array Responses (either \WpOrg\Requests\Response or a \WpOrg\Requests\Exception object)
     243         *
     244         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access.
     245         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array.
     246         */
     247        public function request_multiple($requests, $options = []) {
     248                if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) {
     249                        throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests));
     250                }
     251
     252                if (is_array($options) === false) {
     253                        throw InvalidArgument::create(2, '$options', 'array', gettype($options));
     254                }
     255
    220256                foreach ($requests as $key => $request) {
    221257                        $requests[$key] = $this->merge_request($request, false);
     
    233269         * Merge a request's data with the default data
    234270         *
    235          * @param array $request Request data (same form as {@see request_multiple})
     271         * @param array $request Request data (same form as {@see \WpOrg\Requests\Session::request_multiple()})
    236272         * @param boolean $merge_options Should we merge options as well?
    237273         * @return array Request data
     
    239275        protected function merge_request($request, $merge_options = true) {
    240276                if ($this->url !== null) {
    241                         $request['url'] = Requests_IRI::absolutize($this->url, $request['url']);
     277                        $request['url'] = Iri::absolutize($this->url, $request['url']);
    242278                        $request['url'] = $request['url']->uri;
    243279                }
    244280
    245281                if (empty($request['headers'])) {
    246                         $request['headers'] = array();
     282                        $request['headers'] = [];
    247283                }
    248284                $request['headers'] = array_merge($this->headers, $request['headers']);
     
    257293                }
    258294
    259                 if ($merge_options !== false) {
     295                if ($merge_options === true) {
    260296                        $request['options'] = array_merge($this->options, $request['options']);
    261297
  • trunk/src/wp-includes/Requests/Ssl.php

    r52243 r52244  
    33 * SSL utilities for Requests
    44 *
    5  * @package Requests
    6  * @subpackage Utilities
     5 * @package Requests\Utilities
    76 */
     7
     8namespace WpOrg\Requests;
     9
     10use WpOrg\Requests\Exception\InvalidArgument;
     11use WpOrg\Requests\Utility\InputValidator;
    812
    913/**
     
    1216 * Collection of utilities for working with and verifying SSL certificates.
    1317 *
    14  * @package Requests
    15  * @subpackage Utilities
     18 * @package Requests\Utilities
    1619 */
    17 class Requests_SSL {
     20final class Ssl {
    1821        /**
    1922         * Verify the certificate against common name and subject alternative names
     
    2225         * names, leading things like 'https://www.github.com/' to be invalid.
    2326         *
    24          * @see https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1
     27         * @link https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1
    2528         *
    26          * @throws Requests_Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`)
    27          * @param string $host Host name to verify against
     29         * @param string|Stringable $host Host name to verify against
    2830         * @param array $cert Certificate data from openssl_x509_parse()
    2931         * @return bool
     32         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $host argument is not a string or a stringable object.
     33         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $cert argument is not an array or array accessible.
    3034         */
    3135        public static function verify_certificate($host, $cert) {
     36                if (InputValidator::is_string_or_stringable($host) === false) {
     37                        throw InvalidArgument::create(1, '$host', 'string|Stringable', gettype($host));
     38                }
     39
     40                if (InputValidator::has_array_access($cert) === false) {
     41                        throw InvalidArgument::create(2, '$cert', 'array|ArrayAccess', gettype($cert));
     42                }
     43
    3244                $has_dns_alt = false;
    3345
    3446                // Check the subjectAltName
    35                 if (!empty($cert['extensions']) && !empty($cert['extensions']['subjectAltName'])) {
     47                if (!empty($cert['extensions']['subjectAltName'])) {
    3648                        $altnames = explode(',', $cert['extensions']['subjectAltName']);
    3749                        foreach ($altnames as $altname) {
     
    5163                                }
    5264                        }
     65
     66                        if ($has_dns_alt === true) {
     67                                return false;
     68                        }
    5369                }
    5470
    5571                // Fall back to checking the common name if we didn't get any dNSName
    5672                // alt names, as per RFC2818
    57                 if (!$has_dns_alt && !empty($cert['subject']['CN'])) {
     73                if (!empty($cert['subject']['CN'])) {
    5874                        // Check for a match
    59                         if (self::match_domain($host, $cert['subject']['CN']) === true) {
    60                                 return true;
    61                         }
     75                        return (self::match_domain($host, $cert['subject']['CN']) === true);
    6276                }
    6377
     
    7892         * the third rule.
    7993         *
    80          * @param string $reference Reference dNSName
     94         * @param string|Stringable $reference Reference dNSName
    8195         * @return boolean Is the name valid?
     96         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or a stringable object.
    8297         */
    8398        public static function verify_reference_name($reference) {
     99                if (InputValidator::is_string_or_stringable($reference) === false) {
     100                        throw InvalidArgument::create(1, '$reference', 'string|Stringable', gettype($reference));
     101                }
     102
     103                if ($reference === '') {
     104                        return false;
     105                }
     106
     107                if (preg_match('`\s`', $reference) > 0) {
     108                        // Whitespace detected. This can never be a dNSName.
     109                        return false;
     110                }
     111
    84112                $parts = explode('.', $reference);
     113                if ($parts !== array_filter($parts)) {
     114                        // DNSName cannot contain two dots next to each other.
     115                        return false;
     116                }
    85117
    86118                // Check the first part of the name
     
    113145         * Match a hostname against a dNSName reference
    114146         *
    115          * @param string $host Requested host
    116          * @param string $reference dNSName to match against
     147         * @param string|Stringable $host Requested host
     148         * @param string|Stringable $reference dNSName to match against
    117149         * @return boolean Does the domain match?
     150         * @throws \WpOrg\Requests\Exception\InvalidArgument When either of the passed arguments is not a string or a stringable object.
    118151         */
    119152        public static function match_domain($host, $reference) {
     153                if (InputValidator::is_string_or_stringable($host) === false) {
     154                        throw InvalidArgument::create(1, '$host', 'string|Stringable', gettype($host));
     155                }
     156
    120157                // Check if the reference is blocklisted first
    121158                if (self::verify_reference_name($reference) !== true) {
     
    124161
    125162                // Check for a direct match
    126                 if ($host === $reference) {
     163                if ((string) $host === (string) $reference) {
    127164                        return true;
    128165                }
    129166
    130167                // Calculate the valid wildcard match if the host is not an IP address
    131                 // Also validates that the host has 3 parts or more, as per Firefox's
    132                 // ruleset.
     168                // Also validates that the host has 3 parts or more, as per Firefox's ruleset,
     169                // as a wildcard reference is only allowed with 3 parts or more, so the
     170                // comparison will never match if host doesn't contain 3 parts or more as well.
    133171                if (ip2long($host) === false) {
    134172                        $parts    = explode('.', $host);
    135173                        $parts[0] = '*';
    136174                        $wildcard = implode('.', $parts);
    137                         if ($wildcard === $reference) {
     175                        if ($wildcard === (string) $reference) {
    138176                                return true;
    139177                        }
  • trunk/src/wp-includes/Requests/Transport.php

    r50842 r52244  
    33 * Base HTTP transport
    44 *
    5  * @package Requests
    6  * @subpackage Transport
     5 * @package Requests\Transport
    76 */
     7
     8namespace WpOrg\Requests;
    89
    910/**
    1011 * Base HTTP transport
    1112 *
    12  * @package Requests
    13  * @subpackage Transport
     13 * @package Requests\Transport
    1414 */
    15 interface Requests_Transport {
     15interface Transport {
    1616        /**
    1717         * Perform a request
     
    2020         * @param array $headers Associative array of request headers
    2121         * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
    22          * @param array $options Request options, see {@see Requests::response()} for documentation
     22         * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation
    2323         * @return string Raw HTTP result
    2424         */
    25         public function request($url, $headers = array(), $data = array(), $options = array());
     25        public function request($url, $headers = [], $data = [], $options = []);
    2626
    2727        /**
    2828         * Send multiple requests simultaneously
    2929         *
    30          * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see Requests_Transport::request}
    31          * @param array $options Global options, see {@see Requests::response()} for documentation
    32          * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well)
     30         * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see \WpOrg\Requests\Transport::request()}
     31         * @param array $options Global options, see {@see \WpOrg\Requests\Requests::response()} for documentation
     32         * @return array Array of \WpOrg\Requests\Response objects (may contain \WpOrg\Requests\Exception or string responses as well)
    3333         */
    3434        public function request_multiple($requests, $options);
    3535
    3636        /**
    37          * Self-test whether the transport can be used
    38          * @return bool
     37         * Self-test whether the transport can be used.
     38         *
     39         * The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}.
     40         *
     41         * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`.
     42         * @return bool Whether the transport can be used.
    3943         */
    40         public static function test();
     44        public static function test($capabilities = []);
    4145}
  • trunk/src/wp-includes/Requests/Transport/Curl.php

    r52243 r52244  
    33 * cURL HTTP transport
    44 *
    5  * @package Requests
    6  * @subpackage Transport
     5 * @package Requests\Transport
    76 */
     7
     8namespace WpOrg\Requests\Transport;
     9
     10use RecursiveArrayIterator;
     11use RecursiveIteratorIterator;
     12use WpOrg\Requests\Capability;
     13use WpOrg\Requests\Exception;
     14use WpOrg\Requests\Exception\InvalidArgument;
     15use WpOrg\Requests\Exception\Transport\Curl as CurlException;
     16use WpOrg\Requests\Requests;
     17use WpOrg\Requests\Transport;
     18use WpOrg\Requests\Utility\InputValidator;
    819
    920/**
    1021 * cURL HTTP transport
    1122 *
    12  * @package Requests
    13  * @subpackage Transport
     23 * @package Requests\Transport
    1424 */
    15 class Requests_Transport_cURL implements Requests_Transport {
     25final class Curl implements Transport {
    1626        const CURL_7_10_5 = 0x070A05;
    1727        const CURL_7_16_2 = 0x071002;
     
    3444         * Information on the current request
    3545         *
    36          * @var array cURL information array, see {@see https://secure.php.net/curl_getinfo}
     46         * @var array cURL information array, see {@link https://www.php.net/curl_getinfo}
    3747         */
    3848        public $info;
     
    4858         * cURL handle
    4959         *
     60         * @var resource|\CurlHandle Resource in PHP < 8.0, Instance of CurlHandle in PHP >= 8.0.
     61         */
     62        private $handle;
     63
     64        /**
     65         * Hook dispatcher instance
     66         *
     67         * @var \WpOrg\Requests\Hooks
     68         */
     69        private $hooks;
     70
     71        /**
     72         * Have we finished the headers yet?
     73         *
     74         * @var boolean
     75         */
     76        private $done_headers = false;
     77
     78        /**
     79         * If streaming to a file, keep the file pointer
     80         *
    5081         * @var resource
    5182         */
    52         protected $handle;
    53 
    54         /**
    55          * Hook dispatcher instance
    56          *
    57          * @var Requests_Hooks
    58          */
    59         protected $hooks;
    60 
    61         /**
    62          * Have we finished the headers yet?
    63          *
    64          * @var boolean
    65          */
    66         protected $done_headers = false;
    67 
    68         /**
    69          * If streaming to a file, keep the file pointer
    70          *
    71          * @var resource
    72          */
    73         protected $stream_handle;
     83        private $stream_handle;
    7484
    7585        /**
     
    7888         * @var int
    7989         */
    80         protected $response_bytes;
     90        private $response_bytes;
    8191
    8292        /**
     
    8595         * @var int|bool Byte count, or false if no limit.
    8696         */
    87         protected $response_byte_limit;
     97        private $response_byte_limit;
    8898
    8999        /**
     
    122132         * Perform a request
    123133         *
    124          * @throws Requests_Exception On a cURL error (`curlerror`)
    125          *
    126          * @param string $url URL to request
     134         * @param string|Stringable $url URL to request
    127135         * @param array $headers Associative array of request headers
    128136         * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
    129          * @param array $options Request options, see {@see Requests::response()} for documentation
     137         * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation
    130138         * @return string Raw HTTP result
    131          */
    132         public function request($url, $headers = array(), $data = array(), $options = array()) {
     139         *
     140         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string or Stringable.
     141         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $headers argument is not an array.
     142         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data parameter is not an array or string.
     143         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array.
     144         * @throws \WpOrg\Requests\Exception       On a cURL error (`curlerror`)
     145         */
     146        public function request($url, $headers = [], $data = [], $options = []) {
     147                if (InputValidator::is_string_or_stringable($url) === false) {
     148                        throw InvalidArgument::create(1, '$url', 'string|Stringable', gettype($url));
     149                }
     150
     151                if (is_array($headers) === false) {
     152                        throw InvalidArgument::create(2, '$headers', 'array', gettype($headers));
     153                }
     154
     155                if (!is_array($data) && !is_string($data)) {
     156                        if ($data === null) {
     157                                $data = '';
     158                        } else {
     159                                throw InvalidArgument::create(3, '$data', 'array|string', gettype($data));
     160                        }
     161                }
     162
     163                if (is_array($options) === false) {
     164                        throw InvalidArgument::create(4, '$options', 'array', gettype($options));
     165                }
     166
    133167                $this->hooks = $options['hooks'];
    134168
    135169                $this->setup_handle($url, $headers, $data, $options);
    136170
    137                 $options['hooks']->dispatch('curl.before_send', array(&$this->handle));
     171                $options['hooks']->dispatch('curl.before_send', [&$this->handle]);
    138172
    139173                if ($options['filename'] !== false) {
    140                         $this->stream_handle = fopen($options['filename'], 'wb');
     174                        // phpcs:ignore WordPress.PHP.NoSilencedErrors -- Silenced the PHP native warning in favour of throwing an exception.
     175                        $this->stream_handle = @fopen($options['filename'], 'wb');
     176                        if ($this->stream_handle === false) {
     177                                $error = error_get_last();
     178                                throw new Exception($error['message'], 'fopen');
     179                        }
    141180                }
    142181
     
    165204                $response = $this->response_data;
    166205
    167                 $options['hooks']->dispatch('curl.after_send', array());
    168 
    169                 if (curl_errno($this->handle) === 23 || curl_errno($this->handle) === 61) {
     206                $options['hooks']->dispatch('curl.after_send', []);
     207
     208                if (curl_errno($this->handle) === CURLE_WRITE_ERROR || curl_errno($this->handle) === CURLE_BAD_CONTENT_ENCODING) {
    170209                        // Reset encoding and try again
    171210                        curl_setopt($this->handle, CURLOPT_ENCODING, 'none');
     
    180219
    181220                // Need to remove the $this reference from the curl handle.
    182                 // Otherwise Requests_Transport_cURL wont be garbage collected and the curl_close() will never be called.
     221                // Otherwise \WpOrg\Requests\Transport\Curl won't be garbage collected and the curl_close() will never be called.
    183222                curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, null);
    184223                curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, null);
     
    192231         * @param array $requests Request data
    193232         * @param array $options Global options
    194          * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well)
     233         * @return array Array of \WpOrg\Requests\Response objects (may contain \WpOrg\Requests\Exception or string responses as well)
     234         *
     235         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access.
     236         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array.
    195237         */
    196238        public function request_multiple($requests, $options) {
    197239                // If you're not requesting, we can't get any responses ¯\_(ツ)_/¯
    198240                if (empty($requests)) {
    199                         return array();
     241                        return [];
     242                }
     243
     244                if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) {
     245                        throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests));
     246                }
     247
     248                if (is_array($options) === false) {
     249                        throw InvalidArgument::create(2, '$options', 'array', gettype($options));
    200250                }
    201251
    202252                $multihandle = curl_multi_init();
    203                 $subrequests = array();
    204                 $subhandles  = array();
     253                $subrequests = [];
     254                $subhandles  = [];
    205255
    206256                $class = get_class($this);
     
    208258                        $subrequests[$id] = new $class();
    209259                        $subhandles[$id]  = $subrequests[$id]->get_subrequest_handle($request['url'], $request['headers'], $request['data'], $request['options']);
    210                         $request['options']['hooks']->dispatch('curl.before_multi_add', array(&$subhandles[$id]));
     260                        $request['options']['hooks']->dispatch('curl.before_multi_add', [&$subhandles[$id]]);
    211261                        curl_multi_add_handle($multihandle, $subhandles[$id]);
    212262                }
    213263
    214264                $completed       = 0;
    215                 $responses       = array();
     265                $responses       = [];
    216266                $subrequestcount = count($subrequests);
    217267
    218                 $request['options']['hooks']->dispatch('curl.before_multi_exec', array(&$multihandle));
     268                $request['options']['hooks']->dispatch('curl.before_multi_exec', [&$multihandle]);
    219269
    220270                do {
     
    226276                        while ($status === CURLM_CALL_MULTI_PERFORM);
    227277
    228                         $to_process = array();
     278                        $to_process = [];
    229279
    230280                        // Read the information as needed
     
    242292                                        //get error string for handle.
    243293                                        $reason          = curl_error($done['handle']);
    244                                         $exception       = new Requests_Exception_Transport_cURL(
     294                                        $exception       = new CurlException(
    245295                                                $reason,
    246                                                 Requests_Exception_Transport_cURL::EASY,
     296                                                CurlException::EASY,
    247297                                                $done['handle'],
    248298                                                $done['result']
    249299                                        );
    250300                                        $responses[$key] = $exception;
    251                                         $options['hooks']->dispatch('transport.internal.parse_error', array(&$responses[$key], $requests[$key]));
     301                                        $options['hooks']->dispatch('transport.internal.parse_error', [&$responses[$key], $requests[$key]]);
    252302                                }
    253303                                else {
    254304                                        $responses[$key] = $subrequests[$key]->process_response($subrequests[$key]->response_data, $options);
    255305
    256                                         $options['hooks']->dispatch('transport.internal.parse_response', array(&$responses[$key], $requests[$key]));
     306                                        $options['hooks']->dispatch('transport.internal.parse_response', [&$responses[$key], $requests[$key]]);
    257307                                }
    258308
     
    261311
    262312                                if (!is_string($responses[$key])) {
    263                                         $options['hooks']->dispatch('multiple.request.complete', array(&$responses[$key], $key));
     313                                        $options['hooks']->dispatch('multiple.request.complete', [&$responses[$key], $key]);
    264314                                }
    265315                                $completed++;
     
    268318                while ($active || $completed < $subrequestcount);
    269319
    270                 $request['options']['hooks']->dispatch('curl.after_multi_exec', array(&$multihandle));
     320                $request['options']['hooks']->dispatch('curl.after_multi_exec', [&$multihandle]);
    271321
    272322                curl_multi_close($multihandle);
     
    281331         * @param array $headers Associative array of request headers
    282332         * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
    283          * @param array $options Request options, see {@see Requests::response()} for documentation
    284          * @return resource Subrequest's cURL handle
     333         * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation
     334         * @return resource|\CurlHandle Subrequest's cURL handle
    285335         */
    286336        public function &get_subrequest_handle($url, $headers, $data, $options) {
     
    308358         * @param array $headers Associative array of request headers
    309359         * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
    310          * @param array $options Request options, see {@see Requests::response()} for documentation
    311          */
    312         protected function setup_handle($url, $headers, $data, $options) {
    313                 $options['hooks']->dispatch('curl.before_request', array(&$this->handle));
     360         * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation
     361         */
     362        private function setup_handle($url, $headers, $data, $options) {
     363                $options['hooks']->dispatch('curl.before_request', [&$this->handle]);
    314364
    315365                // Force closing the connection for old versions of cURL (<7.22).
     
    343393                        }
    344394                        elseif (!is_string($data)) {
    345                                 $data = http_build_query($data, null, '&');
     395                                $data = http_build_query($data, '', '&');
    346396                        }
    347397                }
     
    394444                }
    395445                curl_setopt($this->handle, CURLOPT_URL, $url);
    396                 curl_setopt($this->handle, CURLOPT_REFERER, $url);
    397446                curl_setopt($this->handle, CURLOPT_USERAGENT, $options['useragent']);
    398447                if (!empty($headers)) {
     
    407456
    408457                if ($options['blocking'] === true) {
    409                         curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, array($this, 'stream_headers'));
    410                         curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, array($this, 'stream_body'));
     458                        curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, [$this, 'stream_headers']);
     459                        curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, [$this, 'stream_body']);
    411460                        curl_setopt($this->handle, CURLOPT_BUFFERSIZE, Requests::BUFFER_SIZE);
    412461                }
     
    419468         * @param array $options Request options
    420469         * @return string|false HTTP response data including headers. False if non-blocking.
    421          * @throws Requests_Exception
     470         * @throws \WpOrg\Requests\Exception
    422471         */
    423472        public function process_response($response, $options) {
    424473                if ($options['blocking'] === false) {
    425474                        $fake_headers = '';
    426                         $options['hooks']->dispatch('curl.after_request', array(&$fake_headers));
     475                        $options['hooks']->dispatch('curl.after_request', [&$fake_headers]);
    427476                        return false;
    428477                }
     
    441490                                curl_error($this->handle)
    442491                        );
    443                         throw new Requests_Exception($error, 'curlerror', $this->handle);
     492                        throw new Exception($error, 'curlerror', $this->handle);
    444493                }
    445494                $this->info = curl_getinfo($this->handle);
    446495
    447                 $options['hooks']->dispatch('curl.after_request', array(&$this->headers, &$this->info));
     496                $options['hooks']->dispatch('curl.after_request', [&$this->headers, &$this->info]);
    448497                return $this->headers;
    449498        }
     
    452501         * Collect the headers as they are received
    453502         *
    454          * @param resource $handle cURL resource
     503         * @param resource|\CurlHandle $handle cURL handle
    455504         * @param string $headers Header string
    456505         * @return integer Length of provided header
     
    477526         * @since 1.6.1
    478527         *
    479          * @param resource $handle cURL resource
     528         * @param resource|\CurlHandle $handle cURL handle
    480529         * @param string $data Body data
    481530         * @return integer Length of provided data
    482531         */
    483532        public function stream_body($handle, $data) {
    484                 $this->hooks->dispatch('request.progress', array($data, $this->response_bytes, $this->response_byte_limit));
     533                $this->hooks->dispatch('request.progress', [$data, $this->response_bytes, $this->response_byte_limit]);
    485534                $data_length = strlen($data);
    486535
     
    514563         *
    515564         * @param string $url
    516          * @param array|object $data Data to build query using, see {@see https://secure.php.net/http_build_query}
     565         * @param array|object $data Data to build query using, see {@link https://www.php.net/http_build_query}
    517566         * @return string URL with data
    518567         */
    519         protected static function format_get($url, $data) {
     568        private static function format_get($url, $data) {
    520569                if (!empty($data)) {
    521570                        $query     = '';
     
    528577                        }
    529578
    530                         $query .= '&' . http_build_query($data, null, '&');
     579                        $query .= '&' . http_build_query($data, '', '&');
    531580                        $query  = trim($query, '&');
    532581
     
    542591
    543592        /**
    544          * Whether this transport is valid
     593         * Self-test whether the transport can be used.
     594         *
     595         * The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}.
    545596         *
    546597         * @codeCoverageIgnore
    547          * @return boolean True if the transport is valid, false otherwise.
    548          */
    549         public static function test($capabilities = array()) {
     598         * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`.
     599         * @return bool Whether the transport can be used.
     600         */
     601        public static function test($capabilities = []) {
    550602                if (!function_exists('curl_init') || !function_exists('curl_exec')) {
    551603                        return false;
     
    553605
    554606                // If needed, check that our installed curl version supports SSL
    555                 if (isset($capabilities['ssl']) && $capabilities['ssl']) {
     607                if (isset($capabilities[Capability::SSL]) && $capabilities[Capability::SSL]) {
    556608                        $curl_version = curl_version();
    557609                        if (!(CURL_VERSION_SSL & $curl_version['features'])) {
     
    569621         * @return string The "Expect" header.
    570622         */
    571         protected function get_expect_header($data) {
     623        private function get_expect_header($data) {
    572624                if (!is_array($data)) {
    573625                        return strlen((string) $data) >= 1048576 ? '100-Continue' : '';
  • trunk/src/wp-includes/Requests/Transport/Fsockopen.php

    r52243 r52244  
    33 * fsockopen HTTP transport
    44 *
    5  * @package Requests
    6  * @subpackage Transport
     5 * @package Requests\Transport
    76 */
     7
     8namespace WpOrg\Requests\Transport;
     9
     10use WpOrg\Requests\Capability;
     11use WpOrg\Requests\Exception;
     12use WpOrg\Requests\Exception\InvalidArgument;
     13use WpOrg\Requests\Port;
     14use WpOrg\Requests\Requests;
     15use WpOrg\Requests\Ssl;
     16use WpOrg\Requests\Transport;
     17use WpOrg\Requests\Utility\CaseInsensitiveDictionary;
     18use WpOrg\Requests\Utility\InputValidator;
    819
    920/**
    1021 * fsockopen HTTP transport
    1122 *
    12  * @package Requests
    13  * @subpackage Transport
     23 * @package Requests\Transport
    1424 */
    15 class Requests_Transport_fsockopen implements Requests_Transport {
     25final class Fsockopen implements Transport {
    1626        /**
    1727         * Second to microsecond conversion
     
    3141         * Stream metadata
    3242         *
    33          * @var array Associative array of properties, see {@see https://secure.php.net/stream_get_meta_data}
     43         * @var array Associative array of properties, see {@link https://www.php.net/stream_get_meta_data}
    3444         */
    3545        public $info;
     
    4050         * @var int|bool Byte count, or false if no limit.
    4151         */
    42         protected $max_bytes = false;
    43 
    44         protected $connect_error = '';
     52        private $max_bytes = false;
     53
     54        private $connect_error = '';
    4555
    4656        /**
    4757         * Perform a request
    4858         *
    49          * @throws Requests_Exception On failure to connect to socket (`fsockopenerror`)
    50          * @throws Requests_Exception On socket timeout (`timeout`)
    51          *
    52          * @param string $url URL to request
     59         * @param string|Stringable $url URL to request
    5360         * @param array $headers Associative array of request headers
    5461         * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
    55          * @param array $options Request options, see {@see Requests::response()} for documentation
     62         * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation
    5663         * @return string Raw HTTP result
    57          */
    58         public function request($url, $headers = array(), $data = array(), $options = array()) {
     64         *
     65         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string or Stringable.
     66         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $headers argument is not an array.
     67         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data parameter is not an array or string.
     68         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array.
     69         * @throws \WpOrg\Requests\Exception       On failure to connect to socket (`fsockopenerror`)
     70         * @throws \WpOrg\Requests\Exception       On socket timeout (`timeout`)
     71         */
     72        public function request($url, $headers = [], $data = [], $options = []) {
     73                if (InputValidator::is_string_or_stringable($url) === false) {
     74                        throw InvalidArgument::create(1, '$url', 'string|Stringable', gettype($url));
     75                }
     76
     77                if (is_array($headers) === false) {
     78                        throw InvalidArgument::create(2, '$headers', 'array', gettype($headers));
     79                }
     80
     81                if (!is_array($data) && !is_string($data)) {
     82                        if ($data === null) {
     83                                $data = '';
     84                        } else {
     85                                throw InvalidArgument::create(3, '$data', 'array|string', gettype($data));
     86                        }
     87                }
     88
     89                if (is_array($options) === false) {
     90                        throw InvalidArgument::create(4, '$options', 'array', gettype($options));
     91                }
     92
    5993                $options['hooks']->dispatch('fsockopen.before_request');
    6094
    6195                $url_parts = parse_url($url);
    6296                if (empty($url_parts)) {
    63                         throw new Requests_Exception('Invalid URL.', 'invalidurl', $url);
     97                        throw new Exception('Invalid URL.', 'invalidurl', $url);
    6498                }
    6599                $host                     = $url_parts['host'];
    66100                $context                  = stream_context_create();
    67101                $verifyname               = false;
    68                 $case_insensitive_headers = new Requests_Utility_CaseInsensitiveDictionary($headers);
     102                $case_insensitive_headers = new CaseInsensitiveDictionary($headers);
    69103
    70104                // HTTPS support
     
    72106                        $remote_socket = 'ssl://' . $host;
    73107                        if (!isset($url_parts['port'])) {
    74                                 $url_parts['port'] = 443;
    75                         }
    76 
    77                         $context_options = array(
     108                                $url_parts['port'] = Port::HTTPS;
     109                        }
     110
     111                        $context_options = [
    78112                                'verify_peer'       => true,
    79113                                'capture_peer_cert' => true,
    80                         );
     114                        ];
    81115                        $verifyname      = true;
    82116
     
    106140                        }
    107141
    108                         stream_context_set_option($context, array('ssl' => $context_options));
     142                        stream_context_set_option($context, ['ssl' => $context_options]);
    109143                }
    110144                else {
     
    115149
    116150                if (!isset($url_parts['port'])) {
    117                         $url_parts['port'] = 80;
     151                        $url_parts['port'] = Port::HTTP;
    118152                }
    119153                $remote_socket .= ':' . $url_parts['port'];
    120154
    121155                // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler
    122                 set_error_handler(array($this, 'connect_error_handler'), E_WARNING | E_NOTICE);
    123 
    124                 $options['hooks']->dispatch('fsockopen.remote_socket', array(&$remote_socket));
     156                set_error_handler([$this, 'connect_error_handler'], E_WARNING | E_NOTICE);
     157
     158                $options['hooks']->dispatch('fsockopen.remote_socket', [&$remote_socket]);
    125159
    126160                $socket = stream_socket_client($remote_socket, $errno, $errstr, ceil($options['connect_timeout']), STREAM_CLIENT_CONNECT, $context);
     
    129163
    130164                if ($verifyname && !$this->verify_certificate_from_context($host, $context)) {
    131                         throw new Requests_Exception('SSL certificate did not match the requested domain name', 'ssl.no_match');
     165                        throw new Exception('SSL certificate did not match the requested domain name', 'ssl.no_match');
    132166                }
    133167
     
    135169                        if ($errno === 0) {
    136170                                // Connection issue
    137                                 throw new Requests_Exception(rtrim($this->connect_error), 'fsockopen.connect_error');
    138                         }
    139 
    140                         throw new Requests_Exception($errstr, 'fsockopenerror', null, $errno);
     171                                throw new Exception(rtrim($this->connect_error), 'fsockopen.connect_error');
     172                        }
     173
     174                        throw new Exception($errstr, 'fsockopenerror', null, $errno);
    141175                }
    142176
     
    148182                }
    149183                else {
    150                         $path = self::format_get($url_parts, array());
    151                 }
    152 
    153                 $options['hooks']->dispatch('fsockopen.remote_host_path', array(&$path, $url));
     184                        $path = self::format_get($url_parts, []);
     185                }
     186
     187                $options['hooks']->dispatch('fsockopen.remote_host_path', [&$path, $url]);
    154188
    155189                $request_body = '';
     
    178212
    179213                if (!isset($case_insensitive_headers['Host'])) {
    180                         $out .= sprintf('Host: %s', $url_parts['host']);
    181 
    182                         if ((strtolower($url_parts['scheme']) === 'http' && $url_parts['port'] !== 80) || (strtolower($url_parts['scheme']) === 'https' && $url_parts['port'] !== 443)) {
     214                        $out         .= sprintf('Host: %s', $url_parts['host']);
     215                        $scheme_lower = strtolower($url_parts['scheme']);
     216
     217                        if (($scheme_lower === 'http' && $url_parts['port'] !== Port::HTTP) || ($scheme_lower === 'https' && $url_parts['port'] !== Port::HTTPS)) {
    183218                                $out .= ':' . $url_parts['port'];
    184219                        }
     
    201236                }
    202237
    203                 $options['hooks']->dispatch('fsockopen.after_headers', array(&$out));
     238                $options['hooks']->dispatch('fsockopen.after_headers', [&$out]);
    204239
    205240                if (substr($out, -2) !== "\r\n") {
     
    213248                $out .= "\r\n" . $request_body;
    214249
    215                 $options['hooks']->dispatch('fsockopen.before_send', array(&$out));
     250                $options['hooks']->dispatch('fsockopen.before_send', [&$out]);
    216251
    217252                fwrite($socket, $out);
    218                 $options['hooks']->dispatch('fsockopen.after_send', array($out));
     253                $options['hooks']->dispatch('fsockopen.after_send', [$out]);
    219254
    220255                if (!$options['blocking']) {
    221256                        fclose($socket);
    222257                        $fake_headers = '';
    223                         $options['hooks']->dispatch('fsockopen.after_request', array(&$fake_headers));
     258                        $options['hooks']->dispatch('fsockopen.after_request', [&$fake_headers]);
    224259                        return '';
    225260                }
     
    242277                $download   = false;
    243278                if ($options['filename']) {
    244                         $download = fopen($options['filename'], 'wb');
     279                        // phpcs:ignore WordPress.PHP.NoSilencedErrors -- Silenced the PHP native warning in favour of throwing an exception.
     280                        $download = @fopen($options['filename'], 'wb');
     281                        if ($download === false) {
     282                                $error = error_get_last();
     283                                throw new Exception($error['message'], 'fopen');
     284                        }
    245285                }
    246286
     
    248288                        $this->info = stream_get_meta_data($socket);
    249289                        if ($this->info['timed_out']) {
    250                                 throw new Requests_Exception('fsocket timed out', 'timeout');
     290                                throw new Exception('fsocket timed out', 'timeout');
    251291                        }
    252292
     
    262302                        // Are we in body mode now?
    263303                        if ($doingbody) {
    264                                 $options['hooks']->dispatch('request.progress', array($block, $size, $this->max_bytes));
     304                                $options['hooks']->dispatch('request.progress', [$block, $size, $this->max_bytes]);
    265305                                $data_length = strlen($block);
    266306                                if ($this->max_bytes) {
     
    295335                fclose($socket);
    296336
    297                 $options['hooks']->dispatch('fsockopen.after_request', array(&$this->headers, &$this->info));
     337                $options['hooks']->dispatch('fsockopen.after_request', [&$this->headers, &$this->info]);
    298338                return $this->headers;
    299339        }
     
    302342         * Send multiple requests simultaneously
    303343         *
    304          * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see Requests_Transport::request}
    305          * @param array $options Global options, see {@see Requests::response()} for documentation
    306          * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well)
     344         * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see \WpOrg\Requests\Transport::request()}
     345         * @param array $options Global options, see {@see \WpOrg\Requests\Requests::response()} for documentation
     346         * @return array Array of \WpOrg\Requests\Response objects (may contain \WpOrg\Requests\Exception or string responses as well)
     347         *
     348         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access.
     349         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array.
    307350         */
    308351        public function request_multiple($requests, $options) {
    309                 $responses = array();
     352                // If you're not requesting, we can't get any responses ¯\_(ツ)_/¯
     353                if (empty($requests)) {
     354                        return [];
     355                }
     356
     357                if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) {
     358                        throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests));
     359                }
     360
     361                if (is_array($options) === false) {
     362                        throw InvalidArgument::create(2, '$options', 'array', gettype($options));
     363                }
     364
     365                $responses = [];
    310366                $class     = get_class($this);
    311367                foreach ($requests as $id => $request) {
     
    314370                                $responses[$id] = $handler->request($request['url'], $request['headers'], $request['data'], $request['options']);
    315371
    316                                 $request['options']['hooks']->dispatch('transport.internal.parse_response', array(&$responses[$id], $request));
    317                         }
    318                         catch (Requests_Exception $e) {
     372                                $request['options']['hooks']->dispatch('transport.internal.parse_response', [&$responses[$id], $request]);
     373                        }
     374                        catch (Exception $e) {
    319375                                $responses[$id] = $e;
    320376                        }
    321377
    322378                        if (!is_string($responses[$id])) {
    323                                 $request['options']['hooks']->dispatch('multiple.request.complete', array(&$responses[$id], $id));
     379                                $request['options']['hooks']->dispatch('multiple.request.complete', [&$responses[$id], $id]);
    324380                        }
    325381                }
     
    333389         * @return string Accept-Encoding header value
    334390         */
    335         protected static function accept_encoding() {
    336                 $type = array();
     391        private static function accept_encoding() {
     392                $type = [];
    337393                if (function_exists('gzinflate')) {
    338394                        $type[] = 'deflate;q=1.0';
     
    352408         *
    353409         * @param array $url_parts
    354          * @param array|object $data Data to build query using, see {@see https://secure.php.net/http_build_query}
     410         * @param array|object $data Data to build query using, see {@link https://www.php.net/http_build_query}
    355411         * @return string URL with data
    356412         */
    357         protected static function format_get($url_parts, $data) {
     413        private static function format_get($url_parts, $data) {
    358414                if (!empty($data)) {
    359415                        if (empty($url_parts['query'])) {
     
    402458         * Instead
    403459         *
    404          * @see https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1
    405          *
    406          * @throws Requests_Exception On failure to connect via TLS (`fsockopen.ssl.connect_error`)
    407          * @throws Requests_Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`)
     460         * @link https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1
     461         *
    408462         * @param string $host Host name to verify against
    409463         * @param resource $context Stream context
    410464         * @return bool
     465         *
     466         * @throws \WpOrg\Requests\Exception On failure to connect via TLS (`fsockopen.ssl.connect_error`)
     467         * @throws \WpOrg\Requests\Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`)
    411468         */
    412469        public function verify_certificate_from_context($host, $context) {
     
    416473                // all
    417474                if (empty($meta) || empty($meta['ssl']) || empty($meta['ssl']['peer_certificate'])) {
    418                         throw new Requests_Exception(rtrim($this->connect_error), 'ssl.connect_error');
     475                        throw new Exception(rtrim($this->connect_error), 'ssl.connect_error');
    419476                }
    420477
    421478                $cert = openssl_x509_parse($meta['ssl']['peer_certificate']);
    422479
    423                 return Requests_SSL::verify_certificate($host, $cert);
    424         }
    425 
    426         /**
    427          * Whether this transport is valid
     480                return Ssl::verify_certificate($host, $cert);
     481        }
     482
     483        /**
     484         * Self-test whether the transport can be used.
     485         *
     486         * The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}.
    428487         *
    429488         * @codeCoverageIgnore
    430          * @return boolean True if the transport is valid, false otherwise.
    431          */
    432         public static function test($capabilities = array()) {
     489         * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`.
     490         * @return bool Whether the transport can be used.
     491         */
     492        public static function test($capabilities = []) {
    433493                if (!function_exists('fsockopen')) {
    434494                        return false;
     
    436496
    437497                // If needed, check that streams support SSL
    438                 if (isset($capabilities['ssl']) && $capabilities['ssl']) {
     498                if (isset($capabilities[Capability::SSL]) && $capabilities[Capability::SSL]) {
    439499                        if (!extension_loaded('openssl') || !function_exists('openssl_x509_parse')) {
    440500                                return false;
    441501                        }
    442 
    443                         // Currently broken, thanks to https://github.com/facebook/hhvm/issues/2156
    444                         if (defined('HHVM_VERSION')) {
    445                                 return false;
    446                         }
    447502                }
    448503
  • trunk/src/wp-includes/Requests/Utility/CaseInsensitiveDictionary.php

    r50842 r52244  
    33 * Case-insensitive dictionary, suitable for HTTP headers
    44 *
    5  * @package Requests
    6  * @subpackage Utilities
     5 * @package Requests\Utilities
    76 */
     7
     8namespace WpOrg\Requests\Utility;
     9
     10use ArrayAccess;
     11use ArrayIterator;
     12use IteratorAggregate;
     13use ReturnTypeWillChange;
     14use WpOrg\Requests\Exception;
    815
    916/**
    1017 * Case-insensitive dictionary, suitable for HTTP headers
    1118 *
    12  * @package Requests
    13  * @subpackage Utilities
     19 * @package Requests\Utilities
    1420 */
    15 class Requests_Utility_CaseInsensitiveDictionary implements ArrayAccess, IteratorAggregate {
     21class CaseInsensitiveDictionary implements ArrayAccess, IteratorAggregate {
    1622        /**
    1723         * Actual item data
     
    1925         * @var array
    2026         */
    21         protected $data = array();
     27        protected $data = [];
    2228
    2329        /**
     
    2632         * @param array $data Dictionary/map to convert to case-insensitive
    2733         */
    28         public function __construct(array $data = array()) {
    29                 foreach ($data as $key => $value) {
    30                         $this->offsetSet($key, $value);
     34        public function __construct(array $data = []) {
     35                foreach ($data as $offset => $value) {
     36                        $this->offsetSet($offset, $value);
    3137                }
    3238        }
     
    3541         * Check if the given item exists
    3642         *
    37          * @param string $key Item key
     43         * @param string $offset Item key
    3844         * @return boolean Does the item exist?
    3945         */
    40         public function offsetExists($key) {
    41                 $key = strtolower($key);
    42                 return isset($this->data[$key]);
     46        #[ReturnTypeWillChange]
     47        public function offsetExists($offset) {
     48                if (is_string($offset)) {
     49                        $offset = strtolower($offset);
     50                }
     51
     52                return isset($this->data[$offset]);
    4353        }
    4454
     
    4656         * Get the value for the item
    4757         *
    48          * @param string $key Item key
    49          * @return string|null Item value (null if offsetExists is false)
     58         * @param string $offset Item key
     59         * @return string|null Item value (null if the item key doesn't exist)
    5060         */
    51         public function offsetGet($key) {
    52                 $key = strtolower($key);
    53                 if (!isset($this->data[$key])) {
     61        #[ReturnTypeWillChange]
     62        public function offsetGet($offset) {
     63                if (is_string($offset)) {
     64                        $offset = strtolower($offset);
     65                }
     66
     67                if (!isset($this->data[$offset])) {
    5468                        return null;
    5569                }
    5670
    57                 return $this->data[$key];
     71                return $this->data[$offset];
    5872        }
    5973
     
    6175         * Set the given item
    6276         *
    63          * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`)
     77         * @param string $offset Item name
     78         * @param string $value Item value
    6479         *
    65          * @param string $key Item name
    66          * @param string $value Item value
     80         * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`)
    6781         */
    68         public function offsetSet($key, $value) {
    69                 if ($key === null) {
    70                         throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset');
     82        #[ReturnTypeWillChange]
     83        public function offsetSet($offset, $value) {
     84                if ($offset === null) {
     85                        throw new Exception('Object is a dictionary, not a list', 'invalidset');
    7186                }
    7287
    73                 $key              = strtolower($key);
    74                 $this->data[$key] = $value;
     88                if (is_string($offset)) {
     89                        $offset = strtolower($offset);
     90                }
     91
     92                $this->data[$offset] = $value;
    7593        }
    7694
     
    7896         * Unset the given header
    7997         *
    80          * @param string $key
     98         * @param string $offset
    8199         */
    82         public function offsetUnset($key) {
    83                 unset($this->data[strtolower($key)]);
     100        #[ReturnTypeWillChange]
     101        public function offsetUnset($offset) {
     102                if (is_string($offset)) {
     103                        $offset = strtolower($offset);
     104                }
     105
     106                unset($this->data[$offset]);
    84107        }
    85108
     
    87110         * Get an iterator for the data
    88111         *
    89          * @return ArrayIterator
     112         * @return \ArrayIterator
    90113         */
     114        #[ReturnTypeWillChange]
    91115        public function getIterator() {
    92116                return new ArrayIterator($this->data);
  • trunk/src/wp-includes/Requests/Utility/FilteredIterator.php

    r50842 r52244  
    33 * Iterator for arrays requiring filtered values
    44 *
    5  * @package Requests
    6  * @subpackage Utilities
     5 * @package Requests\Utilities
    76 */
     7
     8namespace WpOrg\Requests\Utility;
     9
     10use ArrayIterator;
     11use ReturnTypeWillChange;
     12use WpOrg\Requests\Exception\InvalidArgument;
     13use WpOrg\Requests\Utility\InputValidator;
    814
    915/**
    1016 * Iterator for arrays requiring filtered values
    1117 *
    12  * @package Requests
    13  * @subpackage Utilities
     18 * @package Requests\Utilities
    1419 */
    15 class Requests_Utility_FilteredIterator extends ArrayIterator {
     20final class FilteredIterator extends ArrayIterator {
    1621        /**
    1722         * Callback to run as a filter
     
    1924         * @var callable
    2025         */
    21         protected $callback;
     26        private $callback;
    2227
    2328        /**
     
    2631         * @param array $data
    2732         * @param callable $callback Callback to be called on each value
     33         *
     34         * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data argument is not iterable.
    2835         */
    2936        public function __construct($data, $callback) {
     37                if (InputValidator::is_iterable($data) === false) {
     38                        throw InvalidArgument::create(1, '$data', 'iterable', gettype($data));
     39                }
     40
    3041                parent::__construct($data);
    3142
    32                 $this->callback = $callback;
     43                if (is_callable($callback)) {
     44                        $this->callback = $callback;
     45                }
     46        }
     47
     48        /**
     49         * @inheritdoc
     50         *
     51         * @phpcs:disable PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound
     52         */
     53        #[ReturnTypeWillChange]
     54        public function __unserialize($data) {}
     55        // phpcs:enable
     56
     57        public function __wakeup() {
     58                unset($this->callback);
    3359        }
    3460
     
    3864         * @return string
    3965         */
     66        #[ReturnTypeWillChange]
    4067        public function current() {
    4168                $value = parent::current();
     
    5178         * @inheritdoc
    5279         */
    53         public function unserialize($serialized) {}
    54 
    55         /**
    56          * @inheritdoc
    57          *
    58          * @phpcs:disable PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.MethodDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound
    59          */
    60         public function __unserialize($serialized) {}
    61 
    62         public function __wakeup() {
    63                 unset($this->callback);
    64         }
     80        #[ReturnTypeWillChange]
     81        public function unserialize($data) {}
    6582}
  • trunk/src/wp-includes/class-wp-http-requests-hooks.php

    r51300 r52244  
    1313 * @since 4.7.0
    1414 *
    15  * @see Requests_Hooks
     15 * @see WpOrg\Requests\Hooks
    1616 */
    17 class WP_HTTP_Requests_Hooks extends Requests_Hooks {
     17class WP_HTTP_Requests_Hooks extends WpOrg\Requests\Hooks {
    1818        /**
    1919         * Requested URL.
  • trunk/src/wp-includes/class-wp-http-requests-response.php

    r46586 r52244  
    99
    1010/**
    11  * Core wrapper object for a Requests_Response for standardisation.
     11 * Core wrapper object for a WpOrg\Requests\Response for standardisation.
    1212 *
    1313 * @since 4.6.0
     
    2020         *
    2121         * @since 4.6.0
    22          * @var Requests_Response
     22         * @var \WpOrg\Requests\Response
    2323         */
    2424        protected $response;
     
    3737         * @since 4.6.0
    3838         *
    39          * @param Requests_Response $response HTTP response.
    40          * @param string            $filename Optional. File name. Default empty.
     39         * @param \WpOrg\Requests\Response $response HTTP response.
     40         * @param string                   $filename Optional. File name. Default empty.
    4141         */
    42         public function __construct( Requests_Response $response, $filename = '' ) {
     42        public function __construct( WpOrg\Requests\Response $response, $filename = '' ) {
    4343                $this->response = $response;
    4444                $this->filename = $filename;
     
    5050         * @since 4.6.0
    5151         *
    52          * @return Requests_Response HTTP response.
     52         * @return WpOrg\Requests\Response HTTP response.
    5353         */
    5454        public function get_response_object() {
     
    6161         * @since 4.6.0
    6262         *
    63          * @return \Requests_Utility_CaseInsensitiveDictionary Map of header name to header value.
     63         * @return \WpOrg\Requests\Utility\CaseInsensitiveDictionary Map of header name to header value.
    6464         */
    6565        public function get_headers() {
    6666                // Ensure headers remain case-insensitive.
    67                 $converted = new Requests_Utility_CaseInsensitiveDictionary();
     67                $converted = new WpOrg\Requests\Utility\CaseInsensitiveDictionary();
    6868
    6969                foreach ( $this->response->headers->getAll() as $key => $value ) {
     
    8686         */
    8787        public function set_headers( $headers ) {
    88                 $this->response->headers = new Requests_Response_Headers( $headers );
     88                $this->response->headers = new WpOrg\Requests\Response\Headers( $headers );
    8989        }
    9090
  • trunk/src/wp-includes/class-wp-http.php

    r52026 r52244  
    88 */
    99
    10 if ( ! class_exists( 'Requests' ) ) {
    11         require ABSPATH . WPINC . '/class-requests.php';
    12 
    13         Requests::register_autoloader();
    14         Requests::set_certificate_path( ABSPATH . WPINC . '/certificates/ca-bundle.crt' );
     10if ( ! class_exists( 'WpOrg\Requests\Autoload' ) ) {
     11        require ABSPATH . WPINC . '/Requests/Autoload.php';
     12
     13        WpOrg\Requests\Autoload::register();
     14        WpOrg\Requests\Requests::set_certificate_path( ABSPATH . WPINC . '/certificates/ca-bundle.crt' );
    1515}
    1616
     
    275275                        $response = new WP_Error( 'http_request_failed', __( 'A valid URL was not provided.' ) );
    276276                        /** This action is documented in wp-includes/class-wp-http.php */
    277                         do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url );
     277                        do_action( 'http_api_debug', $response, 'response', 'WpOrg\Requests\Requests', $parsed_args, $url );
    278278                        return $response;
    279279                }
     
    282282                        $response = new WP_Error( 'http_request_not_executed', __( 'User has blocked requests through HTTP.' ) );
    283283                        /** This action is documented in wp-includes/class-wp-http.php */
    284                         do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url );
     284                        do_action( 'http_api_debug', $response, 'response', 'WpOrg\Requests\Requests', $parsed_args, $url );
    285285                        return $response;
    286286                }
     
    299299                                $response = new WP_Error( 'http_request_failed', __( 'Destination directory for file streaming does not exist or is not writable.' ) );
    300300                                /** This action is documented in wp-includes/class-wp-http.php */
    301                                 do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url );
     301                                do_action( 'http_api_debug', $response, 'response', 'WpOrg\Requests\Requests', $parsed_args, $url );
    302302                                return $response;
    303303                        }
     
    347347                }
    348348
    349                 // If we've got cookies, use and convert them to Requests_Cookie.
     349                // If we've got cookies, use and convert them to WpOrg\Requests\Cookie.
    350350                if ( ! empty( $parsed_args['cookies'] ) ) {
    351351                        $options['cookies'] = WP_Http::normalize_cookies( $parsed_args['cookies'] );
     
    379379                $proxy = new WP_HTTP_Proxy();
    380380                if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {
    381                         $options['proxy'] = new Requests_Proxy_HTTP( $proxy->host() . ':' . $proxy->port() );
     381                        $options['proxy'] = new WpOrg\Requests\Proxy\HTTP( $proxy->host() . ':' . $proxy->port() );
    382382
    383383                        if ( $proxy->use_authentication() ) {
     
    392392
    393393                try {
    394                         $requests_response = Requests::request( $url, $headers, $data, $type, $options );
     394                        $requests_response = WpOrg\Requests\Requests::request( $url, $headers, $data, $type, $options );
    395395
    396396                        // Convert the response into an array.
     
    400400                        // Add the original object to the array.
    401401                        $response['http_response'] = $http_response;
    402                 } catch ( Requests_Exception $e ) {
     402                } catch ( WpOrg\Requests\Exception $e ) {
    403403                        $response = new WP_Error( 'http_request_failed', $e->getMessage() );
    404404                }
     
    417417                 * @param string         $url         The request URL.
    418418                 */
    419                 do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url );
     419                do_action( 'http_api_debug', $response, 'response', 'WpOrg\Requests\Requests', $parsed_args, $url );
    420420                if ( is_wp_error( $response ) ) {
    421421                        return $response;
     
    453453         *
    454454         * @param array $cookies Array of cookies to send with the request.
    455          * @return Requests_Cookie_Jar Cookie holder object.
     455         * @return WpOrg\Requests\Cookie\Jar Cookie holder object.
    456456         */
    457457        public static function normalize_cookies( $cookies ) {
    458                 $cookie_jar = new Requests_Cookie_Jar();
     458                $cookie_jar = new WpOrg\Requests\Cookie\Jar();
    459459
    460460                foreach ( $cookies as $name => $value ) {
     
    466466                                        }
    467467                                );
    468                                 $cookie_jar[ $value->name ] = new Requests_Cookie( $value->name, $value->value, $attributes, array( 'host-only' => $value->host_only ) );
     468                                $cookie_jar[ $value->name ] = new WpOrg\Requests\Cookie( $value->name, $value->value, $attributes, array( 'host-only' => $value->host_only ) );
    469469                        } elseif ( is_scalar( $value ) ) {
    470                                 $cookie_jar[ $name ] = new Requests_Cookie( $name, $value );
     470                                $cookie_jar[ $name ] = new WpOrg\Requests\Cookie( $name, (string) $value );
    471471                        }
    472472                }
     
    484484         * @since 4.6.0
    485485         *
    486          * @param string            $location URL to redirect to.
    487          * @param array             $headers  Headers for the redirect.
    488          * @param string|array      $data     Body to send with the request.
    489          * @param array             $options  Redirect request options.
    490          * @param Requests_Response $original Response object.
     486         * @param string                  $location URL to redirect to.
     487         * @param array                   $headers  Headers for the redirect.
     488         * @param string|array            $data     Body to send with the request.
     489         * @param array                   $options  Redirect request options.
     490         * @param WpOrg\Requests\Response $original Response object.
    491491         */
    492492        public static function browser_redirect_compatibility( $location, $headers, $data, &$options, $original ) {
    493493                // Browser compatibility.
    494494                if ( 302 === $original->status_code ) {
    495                         $options['type'] = Requests::GET;
     495                        $options['type'] = WpOrg\Requests\Requests::GET;
    496496                }
    497497        }
     
    502502         * @since 4.7.5
    503503         *
    504          * @throws Requests_Exception On unsuccessful URL validation.
     504         * @throws WpOrg\Requests\Exception On unsuccessful URL validation.
    505505         * @param string $location URL to redirect to.
    506506         */
    507507        public static function validate_redirects( $location ) {
    508508                if ( ! wp_http_validate_url( $location ) ) {
    509                         throw new Requests_Exception( __( 'A valid URL was not provided.' ), 'wp_http.redirect_failed_validation' );
     509                        throw new WpOrg\Requests\Exception( __( 'A valid URL was not provided.' ), 'wp_http.redirect_failed_validation' );
    510510                }
    511511        }
  • trunk/src/wp-includes/http.php

    r52085 r52244  
    201201 *
    202202 * @since 2.7.0
    203  * @since 4.6.0 Return value changed from an array to an Requests_Utility_CaseInsensitiveDictionary instance.
    204  *
    205  * @see \Requests_Utility_CaseInsensitiveDictionary
     203 * @since 4.6.0 Return value changed from an array to an WpOrg\Requests\Utility\CaseInsensitiveDictionary instance.
     204 *
     205 * @see \WpOrg\Requests\Utility\CaseInsensitiveDictionary
    206206 *
    207207 * @param array|WP_Error $response HTTP response.
    208  * @return array|\Requests_Utility_CaseInsensitiveDictionary The headers of the response. Empty array if incorrect parameter given.
     208 * @return array|\WpOrg\Requests\Utility\CaseInsensitiveDictionary The headers of the response. Empty array if incorrect parameter given.
    209209 */
    210210function wp_remote_retrieve_headers( $response ) {
  • trunk/src/wp-includes/rest-api.php

    r52242 r52244  
    13911391        $ipv4_pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/';
    13921392
    1393         if ( ! preg_match( $ipv4_pattern, $ip ) && ! Requests_IPv6::check_ipv6( $ip ) ) {
     1393        if ( ! preg_match( $ipv4_pattern, $ip ) && ! WpOrg\Requests\Ipv6::check_ipv6( $ip ) ) {
    13941394                return false;
    13951395        }
  • trunk/tests/phpunit/tests/feed/wpSimplePieFile.php

    r51651 r52244  
    8686
    8787                return array(
    88                         'headers'  => new Requests_Utility_CaseInsensitiveDictionary( $single_value_headers ),
     88                        'headers'  => new WpOrg\Requests\Utility\CaseInsensitiveDictionary( $single_value_headers ),
    8989                        'body'     => file_get_contents( DIR_TESTDATA . '/feed/wordpress-org-news.xml' ),
    9090                        'response' => array(
     
    115115                );
    116116
    117                 $response['headers'] = new Requests_Utility_CaseInsensitiveDictionary( $multiple_value_headers );
     117                $response['headers'] = new WpOrg\Requests\Utility\CaseInsensitiveDictionary( $multiple_value_headers );
    118118
    119119                return $response;
  • trunk/tests/phpunit/tests/functions.php

    r52187 r52244  
    365365        public function test_deserialize_request_utility_filtered_iterator_objects( $value ) {
    366366                $serialized = maybe_serialize( $value );
    367                 if ( get_class( $value ) === 'Requests_Utility_FilteredIterator' ) {
     367                if ( get_class( $value ) === 'WpOrg\Requests\Utility\FilteredIterator' ) {
    368368                        $new_value = unserialize( $serialized );
    369                         $property  = ( new ReflectionClass( 'Requests_Utility_FilteredIterator' ) )->getProperty( 'callback' );
     369                        $property  = ( new ReflectionClass( 'WpOrg\Requests\Utility\FilteredIterator' ) )->getProperty( 'callback' );
    370370                        $property->setAccessible( true );
    371371                        $callback_value = $property->getValue( $new_value );
     
    378378        public function data_serialize_deserialize_objects() {
    379379                return array(
    380                         array( new Requests_Utility_FilteredIterator( array( 1 ), 'md5' ) ),
    381                         array( new Requests_Utility_FilteredIterator( array( 1, 2 ), 'sha1' ) ),
     380                        array( new WpOrg\Requests\Utility\FilteredIterator( array( 1 ), 'md5' ) ),
     381                        array( new WpOrg\Requests\Utility\FilteredIterator( array( 1, 2 ), 'sha1' ) ),
    382382                        array( new ArrayIterator( array( 1, 2, 3 ) ) ),
    383383                );
  • trunk/tests/phpunit/tests/http/functions.php

    r52010 r52244  
    217217        public function test_get_cookie_host_only() {
    218218                // Emulate WP_Http::request() internals.
    219                 $requests_response = new Requests_Response();
    220 
    221                 $requests_response->cookies['test'] = Requests_Cookie::parse( 'test=foo; domain=.wordpress.org' );
     219                $requests_response = new WpOrg\Requests\Response();
     220
     221                $requests_response->cookies['test'] = WpOrg\Requests\Cookie::parse( 'test=foo; domain=.wordpress.org' );
    222222
    223223                $requests_response->cookies['test']->flags['host-only'] = false; // https://github.com/WordPress/Requests/issues/306
     
    232232                $this->assertFalse( $cookie->host_only, 'host-only flag not set' );
    233233
    234                 // Regurgitate (Requests_Cookie -> WP_Http_Cookie -> Requests_Cookie).
     234                // Regurgitate (WpOrg\Requests\Cookie -> WP_Http_Cookie -> WpOrg\Requests\Cookie).
    235235                $cookies = WP_Http::normalize_cookies( wp_remote_retrieve_cookies( $response ) );
    236236                $this->assertFalse( $cookies['test']->flags['host-only'], 'host-only flag data lost' );
  • trunk/tests/phpunit/tests/http/http.php

    r52084 r52244  
    310310                );
    311311
    312                 $this->assertInstanceOf( 'Requests_Cookie_Jar', $cookie_jar );
     312                $this->assertInstanceOf( 'WpOrg\Requests\Cookie\Jar', $cookie_jar );
    313313
    314314                foreach ( array_keys( $cookies ) as $cookie ) {
     
    316316                                $this->assertArrayNotHasKey( $cookie, $cookie_jar );
    317317                        } else {
    318                                 $this->assertInstanceOf( 'Requests_Cookie', $cookie_jar[ $cookie ] );
     318                                $this->assertInstanceOf( 'WpOrg\Requests\Cookie', $cookie_jar[ $cookie ] );
    319319                        }
    320320                }
  • trunk/tests/phpunit/tests/rest-api/rest-widgets-controller.php

    r52068 r52244  
    417417
    418418                return array(
    419                         'headers'  => new Requests_Utility_CaseInsensitiveDictionary( $single_value_headers ),
     419                        'headers'  => new WpOrg\Requests\Utility\CaseInsensitiveDictionary( $single_value_headers ),
    420420                        'body'     => file_get_contents( DIR_TESTDATA . '/feed/wordpress-org-news.xml' ),
    421421                        'response' => array(
  • trunk/tests/phpunit/tests/rest-api/wpRestBlockNavigationAreasController.php

    r52161 r52244  
    6666        public function test_context_param() {
    6767                wp_set_current_user( static::$admin_id );
    68                 $request  = new WP_REST_Request( Requests::OPTIONS, '/wp/v2/block-navigation-areas' );
     68                $request  = new WP_REST_Request( WpOrg\Requests\Requests::OPTIONS, '/wp/v2/block-navigation-areas' );
    6969                $response = rest_get_server()->dispatch( $request );
    7070                $this->assertSame( 200, $response->get_status() );
     
    102102                $navigation_area = array_rand( get_navigation_areas(), 1 );
    103103                $route           = sprintf( '/wp/v2/block-navigation-areas/%s', urlencode( $navigation_area ) );
    104                 $request         = new WP_REST_Request( Requests::POST, $route );
     104                $request         = new WP_REST_Request( WpOrg\Requests\Requests::POST, $route );
    105105
    106106                $updated_navigation_area = array(
  • trunk/tests/phpunit/tests/widgets/wpWidgetRss.php

    r52031 r52244  
    107107
    108108                return array(
    109                         'headers'  => new Requests_Utility_CaseInsensitiveDictionary( $single_value_headers ),
     109                        'headers'  => new WpOrg\Requests\Utility\CaseInsensitiveDictionary( $single_value_headers ),
    110110                        'body'     => file_get_contents( DIR_TESTDATA . '/feed/wordpress-org-news.xml' ),
    111111                        'response' => array(
Note: See TracChangeset for help on using the changeset viewer.