diff --git a/wp-includes/Requests/Auth.php b/wp-includes/Requests/Auth.php index 63ebb08333..914c7449ca 100644 --- a/wp-includes/Requests/Auth.php +++ b/wp-includes/Requests/Auth.php @@ -2,13 +2,10 @@ /** * Authentication provider interface * - * @package Requests\Authentication + * @package Requests + * @subpackage Authentication */ -namespace WpOrg\Requests; - -use WpOrg\Requests\Hooks; - /** * Authentication provider interface * @@ -17,20 +14,20 @@ use WpOrg\Requests\Hooks; * Parameters should be passed via the constructor where possible, as this * makes it much easier for users to use your provider. * - * @see \WpOrg\Requests\Hooks - * - * @package Requests\Authentication + * @see Requests_Hooks + * @package Requests + * @subpackage Authentication */ -interface Auth { +interface Requests_Auth { /** * Register hooks as needed * - * This method is called in {@see \WpOrg\Requests\Requests::request()} when the user - * has set an instance as the 'auth' option. Use this callback to register all the + * This method is called in {@see Requests::request} when the user has set + * an instance as the 'auth' option. Use this callback to register all the * hooks you'll need. * - * @see \WpOrg\Requests\Hooks::register() - * @param \WpOrg\Requests\Hooks $hooks Hook system + * @see Requests_Hooks::register + * @param Requests_Hooks $hooks Hook system */ - public function register(Hooks $hooks); + public function register(Requests_Hooks $hooks); } diff --git a/wp-includes/Requests/Auth/Basic.php b/wp-includes/Requests/Auth/Basic.php index 8ea0eb5538..68d15bd5db 100644 --- a/wp-includes/Requests/Auth/Basic.php +++ b/wp-includes/Requests/Auth/Basic.php @@ -2,25 +2,20 @@ /** * Basic Authentication provider * - * @package Requests\Authentication + * @package Requests + * @subpackage Authentication */ -namespace WpOrg\Requests\Auth; - -use WpOrg\Requests\Auth; -use WpOrg\Requests\Exception\ArgumentCount; -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\Hooks; - /** * Basic Authentication provider * * Provides a handler for Basic HTTP authentication via the Authorization * header. * - * @package Requests\Authentication + * @package Requests + * @subpackage Authentication */ -class Basic implements Auth { +class Requests_Auth_Basic implements Requests_Auth { /** * Username * @@ -38,45 +33,35 @@ class Basic implements Auth { /** * Constructor * - * @since 2.0 Throws an `InvalidArgument` exception. - * @since 2.0 Throws an `ArgumentCount` exception instead of the Requests base `Exception. - * + * @throws Requests_Exception On incorrect number of arguments (`authbasicbadargs`) * @param array|null $args Array of user and password. Must have exactly two elements - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not an array or null. - * @throws \WpOrg\Requests\Exception\ArgumentCount On incorrect number of array elements (`authbasicbadargs`). */ public function __construct($args = null) { if (is_array($args)) { if (count($args) !== 2) { - throw ArgumentCount::create('an array with exactly two elements', count($args), 'authbasicbadargs'); + throw new Requests_Exception('Invalid number of arguments', 'authbasicbadargs'); } list($this->user, $this->pass) = $args; - return; - } - - if ($args !== null) { - throw InvalidArgument::create(1, '$args', 'array|null', gettype($args)); } } /** * Register the necessary callbacks * - * @see \WpOrg\Requests\Auth\Basic::curl_before_send() - * @see \WpOrg\Requests\Auth\Basic::fsockopen_header() - * @param \WpOrg\Requests\Hooks $hooks Hook system + * @see curl_before_send + * @see fsockopen_header + * @param Requests_Hooks $hooks Hook system */ - public function register(Hooks $hooks) { - $hooks->register('curl.before_send', [$this, 'curl_before_send']); - $hooks->register('fsockopen.after_headers', [$this, 'fsockopen_header']); + public function register(Requests_Hooks $hooks) { + $hooks->register('curl.before_send', array($this, 'curl_before_send')); + $hooks->register('fsockopen.after_headers', array($this, 'fsockopen_header')); } /** * Set cURL parameters before the data is sent * - * @param resource|\CurlHandle $handle cURL handle + * @param resource $handle cURL resource */ public function curl_before_send(&$handle) { curl_setopt($handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); diff --git a/wp-includes/Requests/Autoload.php b/wp-includes/Requests/Autoload.php deleted file mode 100644 index 26dd280ee8..0000000000 --- a/wp-includes/Requests/Autoload.php +++ /dev/null @@ -1,187 +0,0 @@ - '\WpOrg\Requests\Auth', - 'requests_hooker' => '\WpOrg\Requests\HookManager', - 'requests_proxy' => '\WpOrg\Requests\Proxy', - 'requests_transport' => '\WpOrg\Requests\Transport', - - // Classes. - 'requests_cookie' => '\WpOrg\Requests\Cookie', - 'requests_exception' => '\WpOrg\Requests\Exception', - 'requests_hooks' => '\WpOrg\Requests\Hooks', - 'requests_idnaencoder' => '\WpOrg\Requests\IdnaEncoder', - 'requests_ipv6' => '\WpOrg\Requests\Ipv6', - 'requests_iri' => '\WpOrg\Requests\Iri', - 'requests_response' => '\WpOrg\Requests\Response', - 'requests_session' => '\WpOrg\Requests\Session', - 'requests_ssl' => '\WpOrg\Requests\Ssl', - 'requests_auth_basic' => '\WpOrg\Requests\Auth\Basic', - 'requests_cookie_jar' => '\WpOrg\Requests\Cookie\Jar', - 'requests_proxy_http' => '\WpOrg\Requests\Proxy\Http', - 'requests_response_headers' => '\WpOrg\Requests\Response\Headers', - 'requests_transport_curl' => '\WpOrg\Requests\Transport\Curl', - 'requests_transport_fsockopen' => '\WpOrg\Requests\Transport\Fsockopen', - 'requests_utility_caseinsensitivedictionary' => '\WpOrg\Requests\Utility\CaseInsensitiveDictionary', - 'requests_utility_filterediterator' => '\WpOrg\Requests\Utility\FilteredIterator', - 'requests_exception_http' => '\WpOrg\Requests\Exception\Http', - 'requests_exception_transport' => '\WpOrg\Requests\Exception\Transport', - 'requests_exception_transport_curl' => '\WpOrg\Requests\Exception\Transport\Curl', - 'requests_exception_http_304' => '\WpOrg\Requests\Exception\Http\Status304', - 'requests_exception_http_305' => '\WpOrg\Requests\Exception\Http\Status305', - 'requests_exception_http_306' => '\WpOrg\Requests\Exception\Http\Status306', - 'requests_exception_http_400' => '\WpOrg\Requests\Exception\Http\Status400', - 'requests_exception_http_401' => '\WpOrg\Requests\Exception\Http\Status401', - 'requests_exception_http_402' => '\WpOrg\Requests\Exception\Http\Status402', - 'requests_exception_http_403' => '\WpOrg\Requests\Exception\Http\Status403', - 'requests_exception_http_404' => '\WpOrg\Requests\Exception\Http\Status404', - 'requests_exception_http_405' => '\WpOrg\Requests\Exception\Http\Status405', - 'requests_exception_http_406' => '\WpOrg\Requests\Exception\Http\Status406', - 'requests_exception_http_407' => '\WpOrg\Requests\Exception\Http\Status407', - 'requests_exception_http_408' => '\WpOrg\Requests\Exception\Http\Status408', - 'requests_exception_http_409' => '\WpOrg\Requests\Exception\Http\Status409', - 'requests_exception_http_410' => '\WpOrg\Requests\Exception\Http\Status410', - 'requests_exception_http_411' => '\WpOrg\Requests\Exception\Http\Status411', - 'requests_exception_http_412' => '\WpOrg\Requests\Exception\Http\Status412', - 'requests_exception_http_413' => '\WpOrg\Requests\Exception\Http\Status413', - 'requests_exception_http_414' => '\WpOrg\Requests\Exception\Http\Status414', - 'requests_exception_http_415' => '\WpOrg\Requests\Exception\Http\Status415', - 'requests_exception_http_416' => '\WpOrg\Requests\Exception\Http\Status416', - 'requests_exception_http_417' => '\WpOrg\Requests\Exception\Http\Status417', - 'requests_exception_http_418' => '\WpOrg\Requests\Exception\Http\Status418', - 'requests_exception_http_428' => '\WpOrg\Requests\Exception\Http\Status428', - 'requests_exception_http_429' => '\WpOrg\Requests\Exception\Http\Status429', - 'requests_exception_http_431' => '\WpOrg\Requests\Exception\Http\Status431', - 'requests_exception_http_500' => '\WpOrg\Requests\Exception\Http\Status500', - 'requests_exception_http_501' => '\WpOrg\Requests\Exception\Http\Status501', - 'requests_exception_http_502' => '\WpOrg\Requests\Exception\Http\Status502', - 'requests_exception_http_503' => '\WpOrg\Requests\Exception\Http\Status503', - 'requests_exception_http_504' => '\WpOrg\Requests\Exception\Http\Status504', - 'requests_exception_http_505' => '\WpOrg\Requests\Exception\Http\Status505', - 'requests_exception_http_511' => '\WpOrg\Requests\Exception\Http\Status511', - 'requests_exception_http_unknown' => '\WpOrg\Requests\Exception\Http\StatusUnknown', - ]; - - /** - * Register the autoloader. - * - * Note: the autoloader is *prepended* in the autoload queue. - * This is done to ensure that the Requests 2.0 autoloader takes precedence - * over a potentially (dependency-registered) Requests 1.x autoloader. - * - * @internal This method contains a safeguard against the autoloader being - * registered multiple times. This safeguard uses a global constant to - * (hopefully/in most cases) still function correctly, even if the - * class would be renamed. - * - * @return void - */ - public static function register() { - if (defined('REQUESTS_AUTOLOAD_REGISTERED') === false) { - spl_autoload_register([self::class, 'load'], true); - define('REQUESTS_AUTOLOAD_REGISTERED', true); - } - } - - /** - * Autoloader. - * - * @param string $class_name Name of the class name to load. - * - * @return bool Whether a class was loaded or not. - */ - public static function load($class_name) { - // Check that the class starts with "Requests" (PSR-0) or "WpOrg\Requests" (PSR-4). - $psr_4_prefix_pos = strpos($class_name, 'WpOrg\\Requests\\'); - - if (stripos($class_name, 'Requests') !== 0 && $psr_4_prefix_pos !== 0) { - return false; - } - - $class_lower = strtolower($class_name); - - if ($class_lower === 'requests') { - // Reference to the original PSR-0 Requests class. - $file = dirname(__DIR__) . '/library/Requests.php'; - } elseif ($psr_4_prefix_pos === 0) { - // PSR-4 classname. - $file = __DIR__ . '/' . strtr(substr($class_name, 15), '\\', '/') . '.php'; - } - - if (isset($file) && file_exists($file)) { - include $file; - return true; - } - - /* - * Okay, so the class starts with "Requests", but we couldn't find the file. - * If this is one of the deprecated/renamed PSR-0 classes being requested, - * let's alias it to the new name and throw a deprecation notice. - */ - if (isset(self::$deprecated_classes[$class_lower])) { - /* - * Integrators who cannot yet upgrade to the PSR-4 class names can silence deprecations - * by defining a `REQUESTS_SILENCE_PSR0_DEPRECATIONS` constant and setting it to `true`. - * The constant needs to be defined before the first deprecated class is requested - * via this autoloader. - */ - if (!defined('REQUESTS_SILENCE_PSR0_DEPRECATIONS') || REQUESTS_SILENCE_PSR0_DEPRECATIONS !== true) { - // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error - trigger_error( - 'The PSR-0 `Requests_...` class names in the Request library are deprecated.' - . ' Switch to the PSR-4 `WpOrg\Requests\...` class names at your earliest convenience.', - E_USER_DEPRECATED - ); - - // Prevent the deprecation notice from being thrown twice. - if (!defined('REQUESTS_SILENCE_PSR0_DEPRECATIONS')) { - define('REQUESTS_SILENCE_PSR0_DEPRECATIONS', true); - } - } - - // Create an alias and let the autoloader recursively kick in to load the PSR-4 class. - return class_alias(self::$deprecated_classes[$class_lower], $class_name, true); - } - - return false; - } - } -} diff --git a/wp-includes/Requests/Capability.php b/wp-includes/Requests/Capability.php deleted file mode 100644 index 87b8340a34..0000000000 --- a/wp-includes/Requests/Capability.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ - const ALL = [ - self::SSL, - ]; -} diff --git a/wp-includes/Requests/Cookie.php b/wp-includes/Requests/Cookie.php index 1a33ec075f..7dd5b6822d 100644 --- a/wp-includes/Requests/Cookie.php +++ b/wp-includes/Requests/Cookie.php @@ -2,23 +2,17 @@ /** * Cookie storage object * - * @package Requests\Cookies + * @package Requests + * @subpackage Cookies */ -namespace WpOrg\Requests; - -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\Iri; -use WpOrg\Requests\Response\Headers; -use WpOrg\Requests\Utility\CaseInsensitiveDictionary; -use WpOrg\Requests\Utility\InputValidator; - /** * Cookie storage object * - * @package Requests\Cookies + * @package Requests + * @subpackage Cookies */ -class Cookie { +class Requests_Cookie { /** * Cookie name. * @@ -39,9 +33,9 @@ class Cookie { * Valid keys are (currently) path, domain, expires, max-age, secure and * httponly. * - * @var \WpOrg\Requests\Utility\CaseInsensitiveDictionary|array Array-like object + * @var Requests_Utility_CaseInsensitiveDictionary|array Array-like object */ - public $attributes = []; + public $attributes = array(); /** * Cookie flags @@ -51,7 +45,7 @@ class Cookie { * * @var array */ - public $flags = []; + public $flags = array(); /** * Reference time for relative calculations @@ -68,46 +62,18 @@ class Cookie { * * @param string $name * @param string $value - * @param array|\WpOrg\Requests\Utility\CaseInsensitiveDictionary $attributes Associative array of attribute data - * @param array $flags - * @param int|null $reference_time - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $name argument is not a string. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $value argument is not a string. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $attributes argument is not an array or iterable object with array access. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $flags argument is not an array. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $reference_time argument is not an integer or null. + * @param array|Requests_Utility_CaseInsensitiveDictionary $attributes Associative array of attribute data */ - public function __construct($name, $value, $attributes = [], $flags = [], $reference_time = null) { - if (is_string($name) === false) { - throw InvalidArgument::create(1, '$name', 'string', gettype($name)); - } - - if (is_string($value) === false) { - throw InvalidArgument::create(2, '$value', 'string', gettype($value)); - } - - if (InputValidator::has_array_access($attributes) === false || InputValidator::is_iterable($attributes) === false) { - throw InvalidArgument::create(3, '$attributes', 'array|ArrayAccess&Traversable', gettype($attributes)); - } - - if (is_array($flags) === false) { - throw InvalidArgument::create(4, '$flags', 'array', gettype($flags)); - } - - if ($reference_time !== null && is_int($reference_time) === false) { - throw InvalidArgument::create(5, '$reference_time', 'integer|null', gettype($reference_time)); - } - + public function __construct($name, $value, $attributes = array(), $flags = array(), $reference_time = null) { $this->name = $name; $this->value = $value; $this->attributes = $attributes; - $default_flags = [ + $default_flags = array( 'creation' => time(), 'last-access' => time(), 'persistent' => false, 'host-only' => true, - ]; + ); $this->flags = array_merge($default_flags, $flags); $this->reference_time = time(); @@ -118,15 +84,6 @@ class Cookie { $this->normalize(); } - /** - * Get the cookie value - * - * Attributes and other data can be accessed via methods. - */ - public function __toString() { - return $this->value; - } - /** * Check if a cookie is expired. * @@ -156,10 +113,10 @@ class Cookie { /** * Check if a cookie is valid for a given URI * - * @param \WpOrg\Requests\Iri $uri URI to check + * @param Requests_IRI $uri URI to check * @return boolean Whether the cookie is valid for the given URI */ - public function uri_matches(Iri $uri) { + public function uri_matches(Requests_IRI $uri) { if (!$this->domain_matches($uri->host)) { return false; } @@ -174,23 +131,19 @@ class Cookie { /** * Check if a cookie is valid for a given domain * - * @param string $domain Domain to check + * @param string $string Domain to check * @return boolean Whether the cookie is valid for the given domain */ - public function domain_matches($domain) { - if (is_string($domain) === false) { - return false; - } - + public function domain_matches($string) { if (!isset($this->attributes['domain'])) { // Cookies created manually; cookies created by Requests will set // the domain to the requested domain return true; } - $cookie_domain = $this->attributes['domain']; - if ($cookie_domain === $domain) { - // The cookie domain and the passed domain are identical. + $domain_string = $this->attributes['domain']; + if ($domain_string === $string) { + // The domain string and the string are identical. return true; } @@ -200,26 +153,26 @@ class Cookie { return false; } - if (strlen($domain) <= strlen($cookie_domain)) { - // For obvious reasons, the cookie domain cannot be a suffix if the passed domain - // is shorter than the cookie domain + if (strlen($string) <= strlen($domain_string)) { + // For obvious reasons, the string cannot be a suffix if the domain + // is shorter than the domain string return false; } - if (substr($domain, -1 * strlen($cookie_domain)) !== $cookie_domain) { - // The cookie domain should be a suffix of the passed domain. + if (substr($string, -1 * strlen($domain_string)) !== $domain_string) { + // The domain string should be a suffix of the string. return false; } - $prefix = substr($domain, 0, strlen($domain) - strlen($cookie_domain)); + $prefix = substr($string, 0, strlen($string) - strlen($domain_string)); if (substr($prefix, -1) !== '.') { - // The last character of the passed domain that is not included in the + // The last character of the string that is not included in the // domain string should be a %x2E (".") character. return false; } - // The passed domain should be a host name (i.e., not an IP address). - return !preg_match('#^(.+\.)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $domain); + // The string should be a host name (i.e., not an IP address). + return !preg_match('#^(.+\.)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $string); } /** @@ -242,10 +195,6 @@ class Cookie { return true; } - if (is_scalar($request_path) === false) { - return false; - } - $cookie_path = $this->attributes['path']; if ($cookie_path === $request_path) { @@ -367,6 +316,17 @@ class Cookie { return sprintf('%s=%s', $this->name, $this->value); } + /** + * Format a cookie for a Cookie header + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie::format_for_header} + * @return string + */ + public function formatForHeader() { + return $this->format_for_header(); + } + /** * Format a cookie for a Set-Cookie header * @@ -378,7 +338,7 @@ class Cookie { public function format_for_set_cookie() { $header_value = $this->format_for_header(); if (!empty($this->attributes)) { - $parts = []; + $parts = array(); foreach ($this->attributes as $key => $value) { // Ignore non-associative attributes if (is_numeric($key)) { @@ -394,6 +354,26 @@ class Cookie { return $header_value; } + /** + * Format a cookie for a Set-Cookie header + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie::format_for_set_cookie} + * @return string + */ + public function formatForSetCookie() { + return $this->format_for_set_cookie(); + } + + /** + * Get the cookie value + * + * Attributes and other data can be accessed via methods. + */ + public function __toString() { + return $this->value; + } + /** * Parse a cookie string into a cookie object * @@ -401,28 +381,15 @@ class Cookie { * is an intentional deviation from RFC 2109 and RFC 2616. RFC 6265 * specifies some of this handling, but not in a thorough manner. * - * @param string $cookie_header Cookie header value (from a Set-Cookie header) - * @param string $name - * @param int|null $reference_time - * @return \WpOrg\Requests\Cookie Parsed cookie object - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $cookie_header argument is not a string. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $name argument is not a string. + * @param string Cookie header value (from a Set-Cookie header) + * @return Requests_Cookie Parsed cookie object */ - public static function parse($cookie_header, $name = '', $reference_time = null) { - if (is_string($cookie_header) === false) { - throw InvalidArgument::create(1, '$cookie_header', 'string', gettype($cookie_header)); - } - - if (is_string($name) === false) { - throw InvalidArgument::create(2, '$name', 'string', gettype($name)); - } - - $parts = explode(';', $cookie_header); + public static function parse($string, $name = '', $reference_time = null) { + $parts = explode(';', $string); $kvparts = array_shift($parts); if (!empty($name)) { - $value = $cookie_header; + $value = $string; } elseif (strpos($kvparts, '=') === false) { // Some sites might only have a value without the equals separator. @@ -439,8 +406,8 @@ class Cookie { $name = trim($name); $value = trim($value); - // Attribute keys are handled case-insensitively - $attributes = new CaseInsensitiveDictionary(); + // Attribute key are handled case-insensitively + $attributes = new Requests_Utility_CaseInsensitiveDictionary(); if (!empty($parts)) { foreach ($parts as $part) { @@ -458,24 +425,24 @@ class Cookie { } } - return new static($name, $value, $attributes, [], $reference_time); + return new Requests_Cookie($name, $value, $attributes, array(), $reference_time); } /** * Parse all Set-Cookie headers from request headers * - * @param \WpOrg\Requests\Response\Headers $headers Headers to parse from - * @param \WpOrg\Requests\Iri|null $origin URI for comparing cookie origins + * @param Requests_Response_Headers $headers Headers to parse from + * @param Requests_IRI|null $origin URI for comparing cookie origins * @param int|null $time Reference time for expiration calculation * @return array */ - public static function parse_from_headers(Headers $headers, Iri $origin = null, $time = null) { + public static function parse_from_headers(Requests_Response_Headers $headers, Requests_IRI $origin = null, $time = null) { $cookie_headers = $headers->getValues('Set-Cookie'); if (empty($cookie_headers)) { - return []; + return array(); } - $cookies = []; + $cookies = array(); foreach ($cookie_headers as $header) { $parsed = self::parse($header, '', $time); @@ -524,4 +491,15 @@ class Cookie { return $cookies; } + + /** + * Parse all Set-Cookie headers from request headers + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie::parse_from_headers} + * @return array + */ + public static function parseFromHeaders(Requests_Response_Headers $headers) { + return self::parse_from_headers($headers); + } } diff --git a/wp-includes/Requests/Cookie/Jar.php b/wp-includes/Requests/Cookie/Jar.php index dfbb8b739b..a816f90a0a 100644 --- a/wp-includes/Requests/Cookie/Jar.php +++ b/wp-includes/Requests/Cookie/Jar.php @@ -2,123 +2,112 @@ /** * Cookie holder object * - * @package Requests\Cookies + * @package Requests + * @subpackage Cookies */ -namespace WpOrg\Requests\Cookie; - -use ArrayAccess; -use ArrayIterator; -use IteratorAggregate; -use ReturnTypeWillChange; -use WpOrg\Requests\Cookie; -use WpOrg\Requests\Exception; -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\HookManager; -use WpOrg\Requests\Iri; -use WpOrg\Requests\Response; - /** * Cookie holder object * - * @package Requests\Cookies + * @package Requests + * @subpackage Cookies */ -class Jar implements ArrayAccess, IteratorAggregate { +class Requests_Cookie_Jar implements ArrayAccess, IteratorAggregate { /** * Actual item data * * @var array */ - protected $cookies = []; + protected $cookies = array(); /** * Create a new jar * * @param array $cookies Existing cookie values - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not an array. */ - public function __construct($cookies = []) { - if (is_array($cookies) === false) { - throw InvalidArgument::create(1, '$cookies', 'array', gettype($cookies)); - } - + public function __construct($cookies = array()) { $this->cookies = $cookies; } /** - * Normalise cookie data into a \WpOrg\Requests\Cookie + * Normalise cookie data into a Requests_Cookie * - * @param string|\WpOrg\Requests\Cookie $cookie - * @return \WpOrg\Requests\Cookie + * @param string|Requests_Cookie $cookie + * @return Requests_Cookie */ - public function normalize_cookie($cookie, $key = '') { - if ($cookie instanceof Cookie) { + public function normalize_cookie($cookie, $key = null) { + if ($cookie instanceof Requests_Cookie) { return $cookie; } - return Cookie::parse($cookie, $key); + return Requests_Cookie::parse($cookie, $key); + } + + /** + * Normalise cookie data into a Requests_Cookie + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie_Jar::normalize_cookie} + * @return Requests_Cookie + */ + public function normalizeCookie($cookie, $key = null) { + return $this->normalize_cookie($cookie, $key); } /** * Check if the given item exists * - * @param string $offset Item key + * @param string $key Item key * @return boolean Does the item exist? */ - #[ReturnTypeWillChange] - public function offsetExists($offset) { - return isset($this->cookies[$offset]); + public function offsetExists($key) { + return isset($this->cookies[$key]); } /** * Get the value for the item * - * @param string $offset Item key + * @param string $key Item key * @return string|null Item value (null if offsetExists is false) */ - #[ReturnTypeWillChange] - public function offsetGet($offset) { - if (!isset($this->cookies[$offset])) { + public function offsetGet($key) { + if (!isset($this->cookies[$key])) { return null; } - return $this->cookies[$offset]; + return $this->cookies[$key]; } /** * Set the given item * - * @param string $offset Item name - * @param string $value Item value + * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`) * - * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`) + * @param string $key Item name + * @param string $value Item value */ - #[ReturnTypeWillChange] - public function offsetSet($offset, $value) { - if ($offset === null) { - throw new Exception('Object is a dictionary, not a list', 'invalidset'); + public function offsetSet($key, $value) { + if ($key === null) { + throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset'); } - $this->cookies[$offset] = $value; + $this->cookies[$key] = $value; } /** * Unset the given header * - * @param string $offset + * @param string $key */ - #[ReturnTypeWillChange] - public function offsetUnset($offset) { - unset($this->cookies[$offset]); + public function offsetUnset($key) { + unset($this->cookies[$key]); } /** * Get an iterator for the data * - * @return \ArrayIterator + * @return ArrayIterator */ - #[ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->cookies); } @@ -126,11 +115,11 @@ class Jar implements ArrayAccess, IteratorAggregate { /** * Register the cookie handler with the request's hooking system * - * @param \WpOrg\Requests\HookManager $hooks Hooking system + * @param Requests_Hooker $hooks Hooking system */ - public function register(HookManager $hooks) { - $hooks->register('requests.before_request', [$this, 'before_request']); - $hooks->register('requests.before_redirect_check', [$this, 'before_redirect_check']); + public function register(Requests_Hooker $hooks) { + $hooks->register('requests.before_request', array($this, 'before_request')); + $hooks->register('requests.before_redirect_check', array($this, 'before_redirect_check')); } /** @@ -145,12 +134,12 @@ class Jar implements ArrayAccess, IteratorAggregate { * @param array $options */ public function before_request($url, &$headers, &$data, &$type, &$options) { - if (!$url instanceof Iri) { - $url = new Iri($url); + if (!$url instanceof Requests_IRI) { + $url = new Requests_IRI($url); } if (!empty($this->cookies)) { - $cookies = []; + $cookies = array(); foreach ($this->cookies as $key => $cookie) { $cookie = $this->normalize_cookie($cookie, $key); @@ -171,16 +160,16 @@ class Jar implements ArrayAccess, IteratorAggregate { /** * Parse all cookies from a response and attach them to the response * - * @param \WpOrg\Requests\Response $response + * @var Requests_Response $response */ - public function before_redirect_check(Response $response) { - $url = $response->url; - if (!$url instanceof Iri) { - $url = new Iri($url); + public function before_redirect_check(Requests_Response $return) { + $url = $return->url; + if (!$url instanceof Requests_IRI) { + $url = new Requests_IRI($url); } - $cookies = Cookie::parse_from_headers($response->headers, $url); - $this->cookies = array_merge($this->cookies, $cookies); - $response->cookies = $this; + $cookies = Requests_Cookie::parse_from_headers($return->headers, $url); + $this->cookies = array_merge($this->cookies, $cookies); + $return->cookies = $this; } } diff --git a/wp-includes/Requests/Exception.php b/wp-includes/Requests/Exception.php index b67d1b1a40..1080efd971 100644 --- a/wp-includes/Requests/Exception.php +++ b/wp-includes/Requests/Exception.php @@ -2,19 +2,15 @@ /** * Exception for HTTP requests * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests; - -use Exception as PHPException; - /** * Exception for HTTP requests * - * @package Requests\Exceptions + * @package Requests */ -class Exception extends PHPException { +class Requests_Exception extends Exception { /** * Type of exception * @@ -45,7 +41,7 @@ class Exception extends PHPException { } /** - * Like {@see \Exception::getCode()}, but a string code. + * Like {@see getCode()}, but a string code. * * @codeCoverageIgnore * @return string diff --git a/wp-includes/Requests/Exception/ArgumentCount.php b/wp-includes/Requests/Exception/ArgumentCount.php deleted file mode 100644 index b5773ddf33..0000000000 --- a/wp-includes/Requests/Exception/ArgumentCount.php +++ /dev/null @@ -1,47 +0,0 @@ -reason; @@ -65,14 +58,14 @@ class Http extends Exception { */ public static function get_class($code) { if (!$code) { - return StatusUnknown::class; + return 'Requests_Exception_HTTP_Unknown'; } - $class = sprintf('\WpOrg\Requests\Exception\Http\Status%d', $code); + $class = sprintf('Requests_Exception_HTTP_%d', $code); if (class_exists($class)) { return $class; } - return StatusUnknown::class; + return 'Requests_Exception_HTTP_Unknown'; } } diff --git a/wp-includes/Requests/Exception/Http/Status304.php b/wp-includes/Requests/Exception/HTTP/304.php similarity index 61% rename from wp-includes/Requests/Exception/Http/Status304.php rename to wp-includes/Requests/Exception/HTTP/304.php index d510ae7d4e..2636ba4517 100644 --- a/wp-includes/Requests/Exception/Http/Status304.php +++ b/wp-includes/Requests/Exception/HTTP/304.php @@ -2,19 +2,15 @@ /** * Exception for 304 Not Modified responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 304 Not Modified responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status304 extends Http { +class Requests_Exception_HTTP_304 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status305.php b/wp-includes/Requests/Exception/HTTP/305.php similarity index 60% rename from wp-includes/Requests/Exception/Http/Status305.php rename to wp-includes/Requests/Exception/HTTP/305.php index 8be63c3f21..37d115a81a 100644 --- a/wp-includes/Requests/Exception/Http/Status305.php +++ b/wp-includes/Requests/Exception/HTTP/305.php @@ -2,19 +2,15 @@ /** * Exception for 305 Use Proxy responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 305 Use Proxy responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status305 extends Http { +class Requests_Exception_HTTP_305 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status306.php b/wp-includes/Requests/Exception/HTTP/306.php similarity index 61% rename from wp-includes/Requests/Exception/Http/Status306.php rename to wp-includes/Requests/Exception/HTTP/306.php index 2f3534ab9d..743a4ed1d0 100644 --- a/wp-includes/Requests/Exception/Http/Status306.php +++ b/wp-includes/Requests/Exception/HTTP/306.php @@ -2,19 +2,15 @@ /** * Exception for 306 Switch Proxy responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 306 Switch Proxy responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status306 extends Http { +class Requests_Exception_HTTP_306 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status400.php b/wp-includes/Requests/Exception/HTTP/400.php similarity index 60% rename from wp-includes/Requests/Exception/Http/Status400.php rename to wp-includes/Requests/Exception/HTTP/400.php index 4e39623578..5bd5428c0f 100644 --- a/wp-includes/Requests/Exception/Http/Status400.php +++ b/wp-includes/Requests/Exception/HTTP/400.php @@ -2,19 +2,15 @@ /** * Exception for 400 Bad Request responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 400 Bad Request responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status400 extends Http { +class Requests_Exception_HTTP_400 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status401.php b/wp-includes/Requests/Exception/HTTP/401.php similarity index 61% rename from wp-includes/Requests/Exception/Http/Status401.php rename to wp-includes/Requests/Exception/HTTP/401.php index 2a76429ce7..62a283ab09 100644 --- a/wp-includes/Requests/Exception/Http/Status401.php +++ b/wp-includes/Requests/Exception/HTTP/401.php @@ -2,19 +2,15 @@ /** * Exception for 401 Unauthorized responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 401 Unauthorized responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status401 extends Http { +class Requests_Exception_HTTP_401 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status402.php b/wp-includes/Requests/Exception/HTTP/402.php similarity index 62% rename from wp-includes/Requests/Exception/Http/Status402.php rename to wp-includes/Requests/Exception/HTTP/402.php index 09d42879d5..f287fd4b22 100644 --- a/wp-includes/Requests/Exception/Http/Status402.php +++ b/wp-includes/Requests/Exception/HTTP/402.php @@ -2,19 +2,15 @@ /** * Exception for 402 Payment Required responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 402 Payment Required responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status402 extends Http { +class Requests_Exception_HTTP_402 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status403.php b/wp-includes/Requests/Exception/HTTP/403.php similarity index 60% rename from wp-includes/Requests/Exception/Http/Status403.php rename to wp-includes/Requests/Exception/HTTP/403.php index 0b1fc3963d..2ae1c44459 100644 --- a/wp-includes/Requests/Exception/Http/Status403.php +++ b/wp-includes/Requests/Exception/HTTP/403.php @@ -2,19 +2,15 @@ /** * Exception for 403 Forbidden responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 403 Forbidden responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status403 extends Http { +class Requests_Exception_HTTP_403 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status404.php b/wp-includes/Requests/Exception/HTTP/404.php similarity index 60% rename from wp-includes/Requests/Exception/Http/Status404.php rename to wp-includes/Requests/Exception/HTTP/404.php index ef39a853e3..e6e28672c3 100644 --- a/wp-includes/Requests/Exception/Http/Status404.php +++ b/wp-includes/Requests/Exception/HTTP/404.php @@ -2,19 +2,15 @@ /** * Exception for 404 Not Found responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 404 Not Found responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status404 extends Http { +class Requests_Exception_HTTP_404 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status405.php b/wp-includes/Requests/Exception/HTTP/405.php similarity index 62% rename from wp-includes/Requests/Exception/Http/Status405.php rename to wp-includes/Requests/Exception/HTTP/405.php index 666fbfe7c7..0461e6108c 100644 --- a/wp-includes/Requests/Exception/Http/Status405.php +++ b/wp-includes/Requests/Exception/HTTP/405.php @@ -2,19 +2,15 @@ /** * Exception for 405 Method Not Allowed responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 405 Method Not Allowed responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status405 extends Http { +class Requests_Exception_HTTP_405 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status406.php b/wp-includes/Requests/Exception/HTTP/406.php similarity index 61% rename from wp-includes/Requests/Exception/Http/Status406.php rename to wp-includes/Requests/Exception/HTTP/406.php index 37952f80a2..980ef0efc5 100644 --- a/wp-includes/Requests/Exception/Http/Status406.php +++ b/wp-includes/Requests/Exception/HTTP/406.php @@ -2,19 +2,15 @@ /** * Exception for 406 Not Acceptable responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 406 Not Acceptable responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status406 extends Http { +class Requests_Exception_HTTP_406 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status407.php b/wp-includes/Requests/Exception/HTTP/407.php similarity index 64% rename from wp-includes/Requests/Exception/Http/Status407.php rename to wp-includes/Requests/Exception/HTTP/407.php index d8796f9b54..d08c6af7cc 100644 --- a/wp-includes/Requests/Exception/Http/Status407.php +++ b/wp-includes/Requests/Exception/HTTP/407.php @@ -2,19 +2,15 @@ /** * Exception for 407 Proxy Authentication Required responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 407 Proxy Authentication Required responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status407 extends Http { +class Requests_Exception_HTTP_407 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status408.php b/wp-includes/Requests/Exception/HTTP/408.php similarity index 61% rename from wp-includes/Requests/Exception/Http/Status408.php rename to wp-includes/Requests/Exception/HTTP/408.php index 6718d064a1..db15bc2910 100644 --- a/wp-includes/Requests/Exception/Http/Status408.php +++ b/wp-includes/Requests/Exception/HTTP/408.php @@ -2,19 +2,15 @@ /** * Exception for 408 Request Timeout responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 408 Request Timeout responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status408 extends Http { +class Requests_Exception_HTTP_408 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status409.php b/wp-includes/Requests/Exception/HTTP/409.php similarity index 60% rename from wp-includes/Requests/Exception/Http/Status409.php rename to wp-includes/Requests/Exception/HTTP/409.php index 711a5c43f7..83002f9361 100644 --- a/wp-includes/Requests/Exception/Http/Status409.php +++ b/wp-includes/Requests/Exception/HTTP/409.php @@ -2,19 +2,15 @@ /** * Exception for 409 Conflict responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 409 Conflict responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status409 extends Http { +class Requests_Exception_HTTP_409 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status410.php b/wp-includes/Requests/Exception/HTTP/410.php similarity index 58% rename from wp-includes/Requests/Exception/Http/Status410.php rename to wp-includes/Requests/Exception/HTTP/410.php index 127443b781..5bf7aa6d46 100644 --- a/wp-includes/Requests/Exception/Http/Status410.php +++ b/wp-includes/Requests/Exception/HTTP/410.php @@ -2,19 +2,15 @@ /** * Exception for 410 Gone responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 410 Gone responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status410 extends Http { +class Requests_Exception_HTTP_410 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status411.php b/wp-includes/Requests/Exception/HTTP/411.php similarity index 61% rename from wp-includes/Requests/Exception/Http/Status411.php rename to wp-includes/Requests/Exception/HTTP/411.php index e70e63c649..25517b4f36 100644 --- a/wp-includes/Requests/Exception/Http/Status411.php +++ b/wp-includes/Requests/Exception/HTTP/411.php @@ -2,19 +2,15 @@ /** * Exception for 411 Length Required responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 411 Length Required responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status411 extends Http { +class Requests_Exception_HTTP_411 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status412.php b/wp-includes/Requests/Exception/HTTP/412.php similarity index 62% rename from wp-includes/Requests/Exception/Http/Status412.php rename to wp-includes/Requests/Exception/HTTP/412.php index 4a8b9185b2..e89533a7ef 100644 --- a/wp-includes/Requests/Exception/Http/Status412.php +++ b/wp-includes/Requests/Exception/HTTP/412.php @@ -2,19 +2,15 @@ /** * Exception for 412 Precondition Failed responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 412 Precondition Failed responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status412 extends Http { +class Requests_Exception_HTTP_412 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status413.php b/wp-includes/Requests/Exception/HTTP/413.php similarity index 63% rename from wp-includes/Requests/Exception/Http/Status413.php rename to wp-includes/Requests/Exception/HTTP/413.php index 96a96fb163..a7b38fce11 100644 --- a/wp-includes/Requests/Exception/Http/Status413.php +++ b/wp-includes/Requests/Exception/HTTP/413.php @@ -2,19 +2,15 @@ /** * Exception for 413 Request Entity Too Large responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 413 Request Entity Too Large responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status413 extends Http { +class Requests_Exception_HTTP_413 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status414.php b/wp-includes/Requests/Exception/HTTP/414.php similarity index 63% rename from wp-includes/Requests/Exception/Http/Status414.php rename to wp-includes/Requests/Exception/HTTP/414.php index b65ec937af..54c8b8c9ae 100644 --- a/wp-includes/Requests/Exception/Http/Status414.php +++ b/wp-includes/Requests/Exception/HTTP/414.php @@ -2,19 +2,15 @@ /** * Exception for 414 Request-URI Too Large responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 414 Request-URI Too Large responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status414 extends Http { +class Requests_Exception_HTTP_414 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status415.php b/wp-includes/Requests/Exception/HTTP/415.php similarity index 63% rename from wp-includes/Requests/Exception/Http/Status415.php rename to wp-includes/Requests/Exception/HTTP/415.php index cb45655e97..6b5f0785b8 100644 --- a/wp-includes/Requests/Exception/Http/Status415.php +++ b/wp-includes/Requests/Exception/HTTP/415.php @@ -2,19 +2,15 @@ /** * Exception for 415 Unsupported Media Type responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 415 Unsupported Media Type responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status415 extends Http { +class Requests_Exception_HTTP_415 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status416.php b/wp-includes/Requests/Exception/HTTP/416.php similarity index 65% rename from wp-includes/Requests/Exception/Http/Status416.php rename to wp-includes/Requests/Exception/HTTP/416.php index c3661a193c..48a4ecdb8f 100644 --- a/wp-includes/Requests/Exception/Http/Status416.php +++ b/wp-includes/Requests/Exception/HTTP/416.php @@ -2,19 +2,15 @@ /** * Exception for 416 Requested Range Not Satisfiable responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 416 Requested Range Not Satisfiable responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status416 extends Http { +class Requests_Exception_HTTP_416 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status417.php b/wp-includes/Requests/Exception/HTTP/417.php similarity index 62% rename from wp-includes/Requests/Exception/Http/Status417.php rename to wp-includes/Requests/Exception/HTTP/417.php index 4adba9a23e..81570330aa 100644 --- a/wp-includes/Requests/Exception/Http/Status417.php +++ b/wp-includes/Requests/Exception/HTTP/417.php @@ -2,19 +2,15 @@ /** * Exception for 417 Expectation Failed responses * - * @package Requests\Exceptions + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 417 Expectation Failed responses * - * @package Requests\Exceptions + * @package Requests */ -final class Status417 extends Http { +class Requests_Exception_HTTP_417 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status418.php b/wp-includes/Requests/Exception/HTTP/418.php similarity index 50% rename from wp-includes/Requests/Exception/Http/Status418.php rename to wp-includes/Requests/Exception/HTTP/418.php index 5bcb2b84a9..0fcc87d614 100644 --- a/wp-includes/Requests/Exception/Http/Status418.php +++ b/wp-includes/Requests/Exception/HTTP/418.php @@ -2,23 +2,17 @@ /** * Exception for 418 I'm A Teapot responses * - * @link https://tools.ietf.org/html/rfc2324 - * - * @package Requests\Exceptions + * @see https://tools.ietf.org/html/rfc2324 + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 418 I'm A Teapot responses * - * @link https://tools.ietf.org/html/rfc2324 - * - * @package Requests\Exceptions + * @see https://tools.ietf.org/html/rfc2324 + * @package Requests */ -final class Status418 extends Http { +class Requests_Exception_HTTP_418 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/Http/Status428.php b/wp-includes/Requests/Exception/HTTP/428.php similarity index 52% rename from wp-includes/Requests/Exception/Http/Status428.php rename to wp-includes/Requests/Exception/HTTP/428.php index 4d7ea51f5c..799ddffd54 100644 --- a/wp-includes/Requests/Exception/Http/Status428.php +++ b/wp-includes/Requests/Exception/HTTP/428.php @@ -2,23 +2,17 @@ /** * Exception for 428 Precondition Required responses * - * @link https://tools.ietf.org/html/rfc6585 - * - * @package Requests\Exceptions + * @see https://tools.ietf.org/html/rfc6585 + * @package Requests */ -namespace WpOrg\Requests\Exception\Http; - -use WpOrg\Requests\Exception\Http; - /** * Exception for 428 Precondition Required responses * - * @link https://tools.ietf.org/html/rfc6585 - * - * @package Requests\Exceptions + * @see https://tools.ietf.org/html/rfc6585 + * @package Requests */ -final class Status428 extends Http { +class Requests_Exception_HTTP_428 extends Requests_Exception_HTTP { /** * HTTP status code * diff --git a/wp-includes/Requests/Exception/HTTP/429.php b/wp-includes/Requests/Exception/HTTP/429.php new file mode 100644 index 0000000000..78a3148adf --- /dev/null +++ b/wp-includes/Requests/Exception/HTTP/429.php @@ -0,0 +1,29 @@ +code = (int) $data->status_code; + if ($data instanceof Requests_Response) { + $this->code = $data->status_code; } parent::__construct($reason, $data); diff --git a/wp-includes/Requests/Exception/Http/Status429.php b/wp-includes/Requests/Exception/Http/Status429.php deleted file mode 100644 index 2018196c7b..0000000000 --- a/wp-includes/Requests/Exception/Http/Status429.php +++ /dev/null @@ -1,35 +0,0 @@ -type = $type; } if ($code !== null) { - $this->code = (int) $code; + $this->code = $code; } if ($message !== null) { @@ -69,9 +47,7 @@ final class Curl extends Transport { } /** - * Get the error message. - * - * @return string + * Get the error message */ public function getReason() { return $this->reason; diff --git a/wp-includes/Requests/HookManager.php b/wp-includes/Requests/Hooker.php similarity index 66% rename from wp-includes/Requests/HookManager.php rename to wp-includes/Requests/Hooker.php index f2920170b9..c852931f1a 100644 --- a/wp-includes/Requests/HookManager.php +++ b/wp-includes/Requests/Hooker.php @@ -2,22 +2,22 @@ /** * Event dispatcher * - * @package Requests\EventDispatcher + * @package Requests + * @subpackage Utilities */ -namespace WpOrg\Requests; - /** * Event dispatcher * - * @package Requests\EventDispatcher + * @package Requests + * @subpackage Utilities */ -interface HookManager { +interface Requests_Hooker { /** * Register a callback for a hook * * @param string $hook Hook name - * @param callable $callback Function/method to call on event + * @param callback $callback Function/method to call on event * @param int $priority Priority number. <0 is executed earlier, >0 is executed later */ public function register($hook, $callback, $priority = 0); @@ -29,5 +29,5 @@ interface HookManager { * @param array $parameters Parameters to pass to callbacks * @return boolean Successfulness */ - public function dispatch($hook, $parameters = []); + public function dispatch($hook, $parameters = array()); } diff --git a/wp-includes/Requests/Hooks.php b/wp-includes/Requests/Hooks.php index eb8df6209d..f857902ced 100644 --- a/wp-includes/Requests/Hooks.php +++ b/wp-includes/Requests/Hooks.php @@ -2,57 +2,44 @@ /** * Handles adding and dispatching events * - * @package Requests\EventDispatcher + * @package Requests + * @subpackage Utilities */ -namespace WpOrg\Requests; - -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\HookManager; -use WpOrg\Requests\Utility\InputValidator; - /** * Handles adding and dispatching events * - * @package Requests\EventDispatcher + * @package Requests + * @subpackage Utilities */ -class Hooks implements HookManager { +class Requests_Hooks implements Requests_Hooker { /** * Registered callbacks for each hook * * @var array */ - protected $hooks = []; + protected $hooks = array(); + + /** + * Constructor + */ + public function __construct() { + // pass + } /** * Register a callback for a hook * * @param string $hook Hook name - * @param callable $callback Function/method to call on event + * @param callback $callback Function/method to call on event * @param int $priority Priority number. <0 is executed earlier, >0 is executed later - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $hook argument is not a string. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $callback argument is not callable. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $priority argument is not an integer. */ public function register($hook, $callback, $priority = 0) { - if (is_string($hook) === false) { - throw InvalidArgument::create(1, '$hook', 'string', gettype($hook)); - } - - if (is_callable($callback) === false) { - throw InvalidArgument::create(2, '$callback', 'callable', gettype($callback)); - } - - if (InputValidator::is_numeric_array_key($priority) === false) { - throw InvalidArgument::create(3, '$priority', 'integer', gettype($priority)); - } - if (!isset($this->hooks[$hook])) { - $this->hooks[$hook] = [ - $priority => [], - ]; - } elseif (!isset($this->hooks[$hook][$priority])) { - $this->hooks[$hook][$priority] = []; + $this->hooks[$hook] = array(); + } + if (!isset($this->hooks[$hook][$priority])) { + $this->hooks[$hook][$priority] = array(); } $this->hooks[$hook][$priority][] = $callback; @@ -64,31 +51,15 @@ class Hooks implements HookManager { * @param string $hook Hook name * @param array $parameters Parameters to pass to callbacks * @return boolean Successfulness - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $hook argument is not a string. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $parameters argument is not an array. */ - public function dispatch($hook, $parameters = []) { - if (is_string($hook) === false) { - throw InvalidArgument::create(1, '$hook', 'string', gettype($hook)); - } - - // Check strictly against array, as Array* objects don't work in combination with `call_user_func_array()`. - if (is_array($parameters) === false) { - throw InvalidArgument::create(2, '$parameters', 'array', gettype($parameters)); - } - + public function dispatch($hook, $parameters = array()) { if (empty($this->hooks[$hook])) { return false; } - if (!empty($parameters)) { - // Strip potential keys from the array to prevent them being interpreted as parameter names in PHP 8.0. - $parameters = array_values($parameters); - } - foreach ($this->hooks[$hook] as $priority => $hooked) { foreach ($hooked as $callback) { - $callback(...$parameters); + call_user_func_array($callback, $parameters); } } diff --git a/wp-includes/Requests/IdnaEncoder.php b/wp-includes/Requests/IDNAEncoder.php similarity index 66% rename from wp-includes/Requests/IdnaEncoder.php rename to wp-includes/Requests/IDNAEncoder.php index a0df5004a9..881142935b 100644 --- a/wp-includes/Requests/IdnaEncoder.php +++ b/wp-includes/Requests/IDNAEncoder.php @@ -1,45 +1,28 @@ 0) { if ($position + $length > $strlen) { - throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); + throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); } for ($position++; $remaining > 0; $position++) { $value = ord($input[$position]); // If it is invalid, count the sequence as invalid and reprocess the current byte: if (($value & 0xC0) !== 0x80) { - throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); + throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); } --$remaining; @@ -237,7 +208,7 @@ class IdnaEncoder { || $character > 0xEFFFD ) ) { - throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); + throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); } $codepoints[] = $character; @@ -250,11 +221,10 @@ class IdnaEncoder { * RFC3492-compliant encoder * * @internal Pseudo-code from Section 6.3 is commented with "#" next to relevant code + * @throws Requests_Exception On character outside of the domain (never happens with Punycode) (`idna.character_outside_domain`) * * @param string $input UTF-8 encoded string to encode * @return string Punycode-encoded string - * - * @throws \WpOrg\Requests\Exception On character outside of the domain (never happens with Punycode) (`idna.character_outside_domain`) */ public static function punycode_encode($input) { $output = ''; @@ -269,7 +239,7 @@ class IdnaEncoder { $b = 0; // see loop // copy them to the output in order $codepoints = self::utf8_to_codepoints($input); - $extended = []; + $extended = array(); foreach ($codepoints as $char) { if ($char < 128) { @@ -282,7 +252,7 @@ class IdnaEncoder { // This never occurs for Punycode, so ignore in coverage // @codeCoverageIgnoreStart elseif ($char < $n) { - throw new Exception('Invalid character', 'idna.character_outside_domain', $char); + throw new Requests_Exception('Invalid character', 'idna.character_outside_domain', $char); } // @codeCoverageIgnoreEnd else { @@ -362,18 +332,17 @@ class IdnaEncoder { /** * Convert a digit to its respective character * - * @link https://tools.ietf.org/html/rfc3492#section-5 + * @see https://tools.ietf.org/html/rfc3492#section-5 + * @throws Requests_Exception On invalid digit (`idna.invalid_digit`) * * @param int $digit Digit in the range 0-35 * @return string Single character corresponding to digit - * - * @throws \WpOrg\Requests\Exception On invalid digit (`idna.invalid_digit`) */ protected static function digit_to_char($digit) { // @codeCoverageIgnoreStart // As far as I know, this never happens, but still good to be sure. if ($digit < 0 || $digit > 35) { - throw new Exception(sprintf('Invalid digit %d', $digit), 'idna.invalid_digit', $digit); + throw new Requests_Exception(sprintf('Invalid digit %d', $digit), 'idna.invalid_digit', $digit); } // @codeCoverageIgnoreEnd $digits = 'abcdefghijklmnopqrstuvwxyz0123456789'; @@ -383,7 +352,7 @@ class IdnaEncoder { /** * Adapt the bias * - * @link https://tools.ietf.org/html/rfc3492#section-6.1 + * @see https://tools.ietf.org/html/rfc3492#section-6.1 * @param int $delta * @param int $numpoints * @param bool $firsttime diff --git a/wp-includes/Requests/Ipv6.php b/wp-includes/Requests/IPv6.php similarity index 81% rename from wp-includes/Requests/Ipv6.php rename to wp-includes/Requests/IPv6.php index a01b640e65..ba88786be6 100644 --- a/wp-includes/Requests/Ipv6.php +++ b/wp-includes/Requests/IPv6.php @@ -2,23 +2,20 @@ /** * Class to validate and to work with IPv6 addresses * - * @package Requests\Utilities + * @package Requests + * @subpackage Utilities */ -namespace WpOrg\Requests; - -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\Utility\InputValidator; - /** * Class to validate and to work with IPv6 addresses * * This was originally based on the PEAR class of the same name, but has been * entirely rewritten. * - * @package Requests\Utilities + * @package Requests + * @subpackage Utilities */ -final class Ipv6 { +class Requests_IPv6 { /** * Uncompresses an IPv6 address * @@ -33,20 +30,11 @@ final class Ipv6 { * @author elfrink at introweb dot nl * @author Josh Peck * @copyright 2003-2005 The PHP Group - * @license https://opensource.org/licenses/bsd-license.php - * - * @param string|Stringable $ip An IPv6 address + * @license http://www.opensource.org/licenses/bsd-license.php + * @param string $ip An IPv6 address * @return string The uncompressed IPv6 address - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or a stringable object. */ public static function uncompress($ip) { - if (InputValidator::is_string_or_stringable($ip) === false) { - throw InvalidArgument::create(1, '$ip', 'string|Stringable', gettype($ip)); - } - - $ip = (string) $ip; - if (substr_count($ip, '::') !== 1) { return $ip; } @@ -90,14 +78,12 @@ final class Ipv6 { * Example: FF01:0:0:0:0:0:0:101 -> FF01::101 * 0:0:0:0:0:0:0:1 -> ::1 * - * @see \WpOrg\Requests\IPv6::uncompress() - * + * @see uncompress() * @param string $ip An IPv6 address * @return string The compressed IPv6 address */ public static function compress($ip) { - // Prepare the IP to be compressed. - // Note: Input validation is handled in the `uncompress()` method, which is the first call made in this method. + // Prepare the IP to be compressed $ip = self::uncompress($ip); $ip_parts = self::split_v6_v4($ip); @@ -138,15 +124,15 @@ final class Ipv6 { * @param string $ip An IPv6 address * @return string[] [0] contains the IPv6 represented part, and [1] the IPv4 represented part */ - private static function split_v6_v4($ip) { + protected static function split_v6_v4($ip) { if (strpos($ip, '.') !== false) { $pos = strrpos($ip, ':'); $ipv6_part = substr($ip, 0, $pos); $ipv4_part = substr($ip, $pos + 1); - return [$ipv6_part, $ipv4_part]; + return array($ipv6_part, $ipv4_part); } else { - return [$ip, '']; + return array($ip, ''); } } @@ -159,7 +145,6 @@ final class Ipv6 { * @return bool true if $ip is a valid IPv6 address */ public static function check_ipv6($ip) { - // Note: Input validation is handled in the `uncompress()` method, which is the first call made in this method. $ip = self::uncompress($ip); list($ipv6, $ipv4) = self::split_v6_v4($ip); $ipv6 = explode(':', $ipv6); diff --git a/wp-includes/Requests/Iri.php b/wp-includes/Requests/IRI.php similarity index 91% rename from wp-includes/Requests/Iri.php rename to wp-includes/Requests/IRI.php index 21f5e9045d..5d80e49572 100644 --- a/wp-includes/Requests/Iri.php +++ b/wp-includes/Requests/IRI.php @@ -2,17 +2,10 @@ /** * IRI parser/serialiser/normaliser * - * @package Requests\Utilities + * @package Requests + * @subpackage Utilities */ -namespace WpOrg\Requests; - -use WpOrg\Requests\Exception; -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\Ipv6; -use WpOrg\Requests\Port; -use WpOrg\Requests\Utility\InputValidator; - /** * IRI parser/serialiser/normaliser * @@ -45,15 +38,16 @@ use WpOrg\Requests\Utility\InputValidator; * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * @package Requests\Utilities + * @package Requests + * @subpackage Utilities * @author Geoffrey Sneddon * @author Steve Minutillo * @copyright 2007-2009 Geoffrey Sneddon and Steve Minutillo - * @license https://opensource.org/licenses/bsd-license.php + * @license http://www.opensource.org/licenses/bsd-license.php * @link http://hg.gsnedders.com/iri/ * * @property string $iri IRI we're working with - * @property-read string $uri IRI in URI form, {@see \WpOrg\Requests\IRI::to_uri()} + * @property-read string $uri IRI in URI form, {@see to_uri} * @property string $scheme Scheme part of the IRI * @property string $authority Authority part, formatted for a URI (userinfo + host + port) * @property string $iauthority Authority part of the IRI (userinfo + host + port) @@ -69,7 +63,7 @@ use WpOrg\Requests\Utility\InputValidator; * @property string $fragment Fragment, formatted for a URI (after '#') * @property string $ifragment Fragment part of the IRI (after '#') */ -class Iri { +class Requests_IRI { /** * Scheme * @@ -129,19 +123,19 @@ class Iri { */ protected $normalization = array( 'acap' => array( - 'port' => Port::ACAP, + 'port' => 674 ), 'dict' => array( - 'port' => Port::DICT, + 'port' => 2628 ), 'file' => array( - 'ihost' => 'localhost', + 'ihost' => 'localhost' ), 'http' => array( - 'port' => Port::HTTP, + 'port' => 80, ), 'https' => array( - 'port' => Port::HTTPS, + 'port' => 443, ), ); @@ -246,15 +240,9 @@ class Iri { /** * Create a new IRI object, from a specified string * - * @param string|Stringable|null $iri - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $iri argument is not a string, Stringable or null. + * @param string|null $iri */ public function __construct($iri = null) { - if ($iri !== null && InputValidator::is_string_or_stringable($iri) === false) { - throw InvalidArgument::create(1, '$iri', 'string|Stringable|null', gettype($iri)); - } - $this->set_iri($iri); } @@ -263,13 +251,13 @@ class Iri { * * Returns false if $base is not absolute, otherwise an IRI. * - * @param \WpOrg\Requests\Iri|string $base (Absolute) Base IRI - * @param \WpOrg\Requests\Iri|string $relative Relative IRI - * @return \WpOrg\Requests\Iri|false + * @param Requests_IRI|string $base (Absolute) Base IRI + * @param Requests_IRI|string $relative Relative IRI + * @return Requests_IRI|false */ public static function absolutize($base, $relative) { - if (!($relative instanceof self)) { - $relative = new self($relative); + if (!($relative instanceof Requests_IRI)) { + $relative = new Requests_IRI($relative); } if (!$relative->is_valid()) { return false; @@ -278,8 +266,8 @@ class Iri { return clone $relative; } - if (!($base instanceof self)) { - $base = new self($base); + if (!($base instanceof Requests_IRI)) { + $base = new Requests_IRI($base); } if ($base->scheme === null || !$base->is_valid()) { return false; @@ -291,7 +279,7 @@ class Iri { $target->scheme = $base->scheme; } else { - $target = new self; + $target = new Requests_IRI; $target->scheme = $base->scheme; $target->iuserinfo = $base->iuserinfo; $target->ihost = $base->ihost; @@ -342,7 +330,7 @@ class Iri { $iri = trim($iri, "\x20\x09\x0A\x0C\x0D"); $has_match = preg_match('/^((?P[^:\/?#]+):)?(\/\/(?P[^\/?#]*))?(?P[^?#]*)(\?(?P[^#]*))?(#(?P.*))?$/', $iri, $match); if (!$has_match) { - throw new Exception('Cannot parse supplied IRI', 'iri.cannot_parse', $iri); + throw new Requests_Exception('Cannot parse supplied IRI', 'iri.cannot_parse', $iri); } if ($match[1] === '') { @@ -425,18 +413,18 @@ class Iri { /** * Replace invalid character with percent encoding * - * @param string $text Input string + * @param string $string Input string * @param string $extra_chars Valid characters not in iunreserved or * iprivate (this is ASCII-only) * @param bool $iprivate Allow iprivate * @return string */ - protected function replace_invalid_with_pct_encoding($text, $extra_chars, $iprivate = false) { + protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) { // Normalize as many pct-encoded sections as possible - $text = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $text); + $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $string); // Replace invalid percent characters - $text = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $text); + $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string); // Add unreserved and % to $extra_chars (the latter is safe because all // pct-encoded sections are now valid). @@ -444,9 +432,9 @@ class Iri { // Now replace any bytes that aren't allowed with their pct-encoded versions $position = 0; - $strlen = strlen($text); - while (($position += strspn($text, $extra_chars, $position)) < $strlen) { - $value = ord($text[$position]); + $strlen = strlen($string); + while (($position += strspn($string, $extra_chars, $position)) < $strlen) { + $value = ord($string[$position]); // Start position $start = $position; @@ -483,7 +471,7 @@ class Iri { if ($remaining) { if ($position + $length <= $strlen) { for ($position++; $remaining; $position++) { - $value = ord($text[$position]); + $value = ord($string[$position]); // Check that the byte is valid, then add it to the character: if (($value & 0xC0) === 0x80) { @@ -534,7 +522,7 @@ class Iri { } for ($j = $start; $j <= $position; $j++) { - $text = substr_replace($text, sprintf('%%%02X', ord($text[$j])), $j, 1); + $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1); $j += 2; $position += 2; $strlen += 2; @@ -542,7 +530,7 @@ class Iri { } } - return $text; + return $string; } /** @@ -551,13 +539,13 @@ class Iri { * Removes sequences of percent encoded bytes that represent UTF-8 * encoded characters in iunreserved * - * @param array $regex_match PCRE match + * @param array $match PCRE match * @return string Replacement */ - protected function remove_iunreserved_percent_encoded($regex_match) { + protected function remove_iunreserved_percent_encoded($match) { // As we just have valid percent encoded sequences we can just explode // and ignore the first member of the returned array (an empty string). - $bytes = explode('%', $regex_match[0]); + $bytes = explode('%', $match[0]); // Initialize the new string (this is what will be returned) and that // there are no bytes remaining in the current sequence (unsurprising @@ -733,9 +721,6 @@ class Iri { if ($iri === null) { return true; } - - $iri = (string) $iri; - if (isset($cache[$iri])) { list($this->scheme, $this->iuserinfo, @@ -748,7 +733,7 @@ class Iri { return $return; } - $parsed = $this->parse_iri($iri); + $parsed = $this->parse_iri((string) $iri); $return = $this->set_scheme($parsed['scheme']) && $this->set_authority($parsed['authority']) @@ -878,8 +863,8 @@ class Iri { return true; } if (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') { - if (Ipv6::check_ipv6(substr($ihost, 1, -1))) { - $this->ihost = '[' . Ipv6::compress(substr($ihost, 1, -1)) . ']'; + if (Requests_IPv6::check_ipv6(substr($ihost, 1, -1))) { + $this->ihost = '[' . Requests_IPv6::compress(substr($ihost, 1, -1)) . ']'; } else { $this->ihost = null; @@ -1000,11 +985,11 @@ class Iri { /** * Convert an IRI to a URI (or parts thereof) * - * @param string|bool $iri IRI to convert (or false from {@see \WpOrg\Requests\IRI::get_iri()}) + * @param string|bool IRI to convert (or false from {@see get_iri}) * @return string|false URI if IRI is valid, false otherwise. */ - protected function to_uri($iri) { - if (!is_string($iri)) { + protected function to_uri($string) { + if (!is_string($string)) { return false; } @@ -1014,14 +999,14 @@ class Iri { } $position = 0; - $strlen = strlen($iri); - while (($position += strcspn($iri, $non_ascii, $position)) < $strlen) { - $iri = substr_replace($iri, sprintf('%%%02X', ord($iri[$position])), $position, 1); + $strlen = strlen($string); + while (($position += strcspn($string, $non_ascii, $position)) < $strlen) { + $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1); $position += 3; $strlen += 2; } - return $iri; + return $string; } /** diff --git a/wp-includes/Requests/Port.php b/wp-includes/Requests/Port.php deleted file mode 100644 index 5545409385..0000000000 --- a/wp-includes/Requests/Port.php +++ /dev/null @@ -1,75 +0,0 @@ -use_authentication = true; } else { - throw ArgumentCount::create( - 'an array with exactly one element or exactly three elements', - count($args), - 'proxyhttpbadargs' - ); + throw new Requests_Exception('Invalid number of arguments', 'proxyhttpbadargs'); } - } elseif ($args !== null) { - throw InvalidArgument::create(1, '$args', 'array|string|null', gettype($args)); } } @@ -92,19 +76,19 @@ final class Http implements Proxy { * Register the necessary callbacks * * @since 1.6 - * @see \WpOrg\Requests\Proxy\HTTP::curl_before_send() - * @see \WpOrg\Requests\Proxy\HTTP::fsockopen_remote_socket() - * @see \WpOrg\Requests\Proxy\HTTP::fsockopen_remote_host_path() - * @see \WpOrg\Requests\Proxy\HTTP::fsockopen_header() - * @param \WpOrg\Requests\Hooks $hooks Hook system + * @see curl_before_send + * @see fsockopen_remote_socket + * @see fsockopen_remote_host_path + * @see fsockopen_header + * @param Requests_Hooks $hooks Hook system */ - public function register(Hooks $hooks) { - $hooks->register('curl.before_send', [$this, 'curl_before_send']); + public function register(Requests_Hooks $hooks) { + $hooks->register('curl.before_send', array($this, 'curl_before_send')); - $hooks->register('fsockopen.remote_socket', [$this, 'fsockopen_remote_socket']); - $hooks->register('fsockopen.remote_host_path', [$this, 'fsockopen_remote_host_path']); + $hooks->register('fsockopen.remote_socket', array($this, 'fsockopen_remote_socket')); + $hooks->register('fsockopen.remote_host_path', array($this, 'fsockopen_remote_host_path')); if ($this->use_authentication) { - $hooks->register('fsockopen.after_headers', [$this, 'fsockopen_header']); + $hooks->register('fsockopen.after_headers', array($this, 'fsockopen_header')); } } @@ -112,7 +96,7 @@ final class Http implements Proxy { * Set cURL parameters before the data is sent * * @since 1.6 - * @param resource|\CurlHandle $handle cURL handle + * @param resource $handle cURL resource */ public function curl_before_send(&$handle) { curl_setopt($handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); diff --git a/wp-includes/Requests/Requests.php b/wp-includes/Requests/Requests.php deleted file mode 100644 index b611892178..0000000000 --- a/wp-includes/Requests/Requests.php +++ /dev/null @@ -1,1079 +0,0 @@ - 10, - 'connect_timeout' => 10, - 'useragent' => 'php-requests/' . self::VERSION, - 'protocol_version' => 1.1, - 'redirected' => 0, - 'redirects' => 10, - 'follow_redirects' => true, - 'blocking' => true, - 'type' => self::GET, - 'filename' => false, - 'auth' => false, - 'proxy' => false, - 'cookies' => false, - 'max_bytes' => false, - 'idn' => true, - 'hooks' => null, - 'transport' => null, - 'verify' => null, - 'verifyname' => true, - ]; - - /** - * Default supported Transport classes. - * - * @since 2.0.0 - * - * @var array - */ - const DEFAULT_TRANSPORTS = [ - Curl::class => Curl::class, - Fsockopen::class => Fsockopen::class, - ]; - - /** - * Current version of Requests - * - * @var string - */ - const VERSION = '2.0.0'; - - /** - * Selected transport name - * - * Use {@see \WpOrg\Requests\Requests::get_transport()} instead - * - * @var array - */ - public static $transport = []; - - /** - * Registered transport classes - * - * @var array - */ - protected static $transports = []; - - /** - * Default certificate path. - * - * @see \WpOrg\Requests\Requests::get_certificate_path() - * @see \WpOrg\Requests\Requests::set_certificate_path() - * - * @var string - */ - protected static $certificate_path = __DIR__ . '/../certificates/cacert.pem'; - - /** - * All (known) valid deflate, gzip header magic markers. - * - * These markers relate to different compression levels. - * - * @link https://stackoverflow.com/a/43170354/482864 Marker source. - * - * @since 2.0.0 - * - * @var array - */ - private static $magic_compression_headers = [ - "\x1f\x8b" => true, // Gzip marker. - "\x78\x01" => true, // Zlib marker - level 1. - "\x78\x5e" => true, // Zlib marker - level 2 to 5. - "\x78\x9c" => true, // Zlib marker - level 6. - "\x78\xda" => true, // Zlib marker - level 7 to 9. - ]; - - /** - * This is a static class, do not instantiate it - * - * @codeCoverageIgnore - */ - private function __construct() {} - - /** - * Register a transport - * - * @param string $transport Transport class to add, must support the \WpOrg\Requests\Transport interface - */ - public static function add_transport($transport) { - if (empty(self::$transports)) { - self::$transports = self::DEFAULT_TRANSPORTS; - } - - self::$transports[$transport] = $transport; - } - - /** - * Get the fully qualified class name (FQCN) for a working transport. - * - * @param array $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. - * @return string FQCN of the transport to use, or an empty string if no transport was - * found which provided the requested capabilities. - */ - protected static function get_transport_class(array $capabilities = []) { - // Caching code, don't bother testing coverage. - // @codeCoverageIgnoreStart - // Array of capabilities as a string to be used as an array key. - ksort($capabilities); - $cap_string = serialize($capabilities); - - // Don't search for a transport if it's already been done for these $capabilities. - if (isset(self::$transport[$cap_string])) { - return self::$transport[$cap_string]; - } - - // Ensure we will not run this same check again later on. - self::$transport[$cap_string] = ''; - // @codeCoverageIgnoreEnd - - if (empty(self::$transports)) { - self::$transports = self::DEFAULT_TRANSPORTS; - } - - // Find us a working transport. - foreach (self::$transports as $class) { - if (!class_exists($class)) { - continue; - } - - $result = $class::test($capabilities); - if ($result === true) { - self::$transport[$cap_string] = $class; - break; - } - } - - return self::$transport[$cap_string]; - } - - /** - * Get a working transport. - * - * @param array $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. - * @return \WpOrg\Requests\Transport - * @throws \WpOrg\Requests\Exception If no valid transport is found (`notransport`). - */ - protected static function get_transport(array $capabilities = []) { - $class = self::get_transport_class($capabilities); - - if ($class === '') { - throw new Exception('No working transports found', 'notransport', self::$transports); - } - - return new $class(); - } - - /** - * Checks to see if we have a transport for the capabilities requested. - * - * Supported capabilities can be found in the {@see \WpOrg\Requests\Capability} - * interface as constants. - * - * Example usage: - * `Requests::has_capabilities([Capability::SSL => true])`. - * - * @param array $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. - * @return bool Whether the transport has the requested capabilities. - */ - public static function has_capabilities(array $capabilities = []) { - return self::get_transport_class($capabilities) !== ''; - } - - /**#@+ - * @see \WpOrg\Requests\Requests::request() - * @param string $url - * @param array $headers - * @param array $options - * @return \WpOrg\Requests\Response - */ - /** - * Send a GET request - */ - public static function get($url, $headers = [], $options = []) { - return self::request($url, $headers, null, self::GET, $options); - } - - /** - * Send a HEAD request - */ - public static function head($url, $headers = [], $options = []) { - return self::request($url, $headers, null, self::HEAD, $options); - } - - /** - * Send a DELETE request - */ - public static function delete($url, $headers = [], $options = []) { - return self::request($url, $headers, null, self::DELETE, $options); - } - - /** - * Send a TRACE request - */ - public static function trace($url, $headers = [], $options = []) { - return self::request($url, $headers, null, self::TRACE, $options); - } - /**#@-*/ - - /**#@+ - * @see \WpOrg\Requests\Requests::request() - * @param string $url - * @param array $headers - * @param array $data - * @param array $options - * @return \WpOrg\Requests\Response - */ - /** - * Send a POST request - */ - public static function post($url, $headers = [], $data = [], $options = []) { - return self::request($url, $headers, $data, self::POST, $options); - } - /** - * Send a PUT request - */ - public static function put($url, $headers = [], $data = [], $options = []) { - return self::request($url, $headers, $data, self::PUT, $options); - } - - /** - * Send an OPTIONS request - */ - public static function options($url, $headers = [], $data = [], $options = []) { - return self::request($url, $headers, $data, self::OPTIONS, $options); - } - - /** - * Send a PATCH request - * - * Note: Unlike {@see \WpOrg\Requests\Requests::post()} and {@see \WpOrg\Requests\Requests::put()}, - * `$headers` is required, as the specification recommends that should send an ETag - * - * @link https://tools.ietf.org/html/rfc5789 - */ - public static function patch($url, $headers, $data = [], $options = []) { - return self::request($url, $headers, $data, self::PATCH, $options); - } - /**#@-*/ - - /** - * Main interface for HTTP requests - * - * This method initiates a request and sends it via a transport before - * parsing. - * - * The `$options` parameter takes an associative array with the following - * options: - * - * - `timeout`: How long should we wait for a response? - * Note: for cURL, a minimum of 1 second applies, as DNS resolution - * operates at second-resolution only. - * (float, seconds with a millisecond precision, default: 10, example: 0.01) - * - `connect_timeout`: How long should we wait while trying to connect? - * (float, seconds with a millisecond precision, default: 10, example: 0.01) - * - `useragent`: Useragent to send to the server - * (string, default: php-requests/$version) - * - `follow_redirects`: Should we follow 3xx redirects? - * (boolean, default: true) - * - `redirects`: How many times should we redirect before erroring? - * (integer, default: 10) - * - `blocking`: Should we block processing on this request? - * (boolean, default: true) - * - `filename`: File to stream the body to instead. - * (string|boolean, default: false) - * - `auth`: Authentication handler or array of user/password details to use - * for Basic authentication - * (\WpOrg\Requests\Auth|array|boolean, default: false) - * - `proxy`: Proxy details to use for proxy by-passing and authentication - * (\WpOrg\Requests\Proxy|array|string|boolean, default: false) - * - `max_bytes`: Limit for the response body size. - * (integer|boolean, default: false) - * - `idn`: Enable IDN parsing - * (boolean, default: true) - * - `transport`: Custom transport. Either a class name, or a - * transport object. Defaults to the first working transport from - * {@see \WpOrg\Requests\Requests::getTransport()} - * (string|\WpOrg\Requests\Transport, default: {@see \WpOrg\Requests\Requests::getTransport()}) - * - `hooks`: Hooks handler. - * (\WpOrg\Requests\HookManager, default: new WpOrg\Requests\Hooks()) - * - `verify`: Should we verify SSL certificates? Allows passing in a custom - * certificate file as a string. (Using true uses the system-wide root - * certificate store instead, but this may have different behaviour - * across transports.) - * (string|boolean, default: certificates/cacert.pem) - * - `verifyname`: Should we verify the common name in the SSL certificate? - * (boolean, default: true) - * - `data_format`: How should we send the `$data` parameter? - * (string, one of 'query' or 'body', default: 'query' for - * HEAD/GET/DELETE, 'body' for POST/PUT/OPTIONS/PATCH) - * - * @param string|Stringable $url URL to request - * @param array $headers Extra headers to send with the request - * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests - * @param string $type HTTP request type (use Requests constants) - * @param array $options Options for the request (see description for more information) - * @return \WpOrg\Requests\Response - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string or Stringable. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $type argument is not a string. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. - * @throws \WpOrg\Requests\Exception On invalid URLs (`nonhttp`) - */ - public static function request($url, $headers = [], $data = [], $type = self::GET, $options = []) { - if (InputValidator::is_string_or_stringable($url) === false) { - throw InvalidArgument::create(1, '$url', 'string|Stringable', gettype($url)); - } - - if (is_string($type) === false) { - throw InvalidArgument::create(4, '$type', 'string', gettype($type)); - } - - if (is_array($options) === false) { - throw InvalidArgument::create(5, '$options', 'array', gettype($options)); - } - - if (empty($options['type'])) { - $options['type'] = $type; - } - $options = array_merge(self::get_default_options(), $options); - - self::set_defaults($url, $headers, $data, $type, $options); - - $options['hooks']->dispatch('requests.before_request', [&$url, &$headers, &$data, &$type, &$options]); - - if (!empty($options['transport'])) { - $transport = $options['transport']; - - if (is_string($options['transport'])) { - $transport = new $transport(); - } - } - else { - $need_ssl = (stripos($url, 'https://') === 0); - $capabilities = [Capability::SSL => $need_ssl]; - $transport = self::get_transport($capabilities); - } - $response = $transport->request($url, $headers, $data, $options); - - $options['hooks']->dispatch('requests.before_parse', [&$response, $url, $headers, $data, $type, $options]); - - return self::parse_response($response, $url, $headers, $data, $options); - } - - /** - * Send multiple HTTP requests simultaneously - * - * The `$requests` parameter takes an associative or indexed array of - * request fields. The key of each request can be used to match up the - * request with the returned data, or with the request passed into your - * `multiple.request.complete` callback. - * - * The request fields value is an associative array with the following keys: - * - * - `url`: Request URL Same as the `$url` parameter to - * {@see \WpOrg\Requests\Requests::request()} - * (string, required) - * - `headers`: Associative array of header fields. Same as the `$headers` - * parameter to {@see \WpOrg\Requests\Requests::request()} - * (array, default: `array()`) - * - `data`: Associative array of data fields or a string. Same as the - * `$data` parameter to {@see \WpOrg\Requests\Requests::request()} - * (array|string, default: `array()`) - * - `type`: HTTP request type (use \WpOrg\Requests\Requests constants). Same as the `$type` - * parameter to {@see \WpOrg\Requests\Requests::request()} - * (string, default: `\WpOrg\Requests\Requests::GET`) - * - `cookies`: Associative array of cookie name to value, or cookie jar. - * (array|\WpOrg\Requests\Cookie\Jar) - * - * If the `$options` parameter is specified, individual requests will - * inherit options from it. This can be used to use a single hooking system, - * or set all the types to `\WpOrg\Requests\Requests::POST`, for example. - * - * In addition, the `$options` parameter takes the following global options: - * - * - `complete`: A callback for when a request is complete. Takes two - * parameters, a \WpOrg\Requests\Response/\WpOrg\Requests\Exception reference, and the - * ID from the request array (Note: this can also be overridden on a - * per-request basis, although that's a little silly) - * (callback) - * - * @param array $requests Requests data (see description for more information) - * @param array $options Global and default options (see {@see \WpOrg\Requests\Requests::request()}) - * @return array Responses (either \WpOrg\Requests\Response or a \WpOrg\Requests\Exception object) - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. - */ - public static function request_multiple($requests, $options = []) { - if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { - throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); - } - - if (is_array($options) === false) { - throw InvalidArgument::create(2, '$options', 'array', gettype($options)); - } - - $options = array_merge(self::get_default_options(true), $options); - - if (!empty($options['hooks'])) { - $options['hooks']->register('transport.internal.parse_response', [static::class, 'parse_multiple']); - if (!empty($options['complete'])) { - $options['hooks']->register('multiple.request.complete', $options['complete']); - } - } - - foreach ($requests as $id => &$request) { - if (!isset($request['headers'])) { - $request['headers'] = []; - } - if (!isset($request['data'])) { - $request['data'] = []; - } - if (!isset($request['type'])) { - $request['type'] = self::GET; - } - if (!isset($request['options'])) { - $request['options'] = $options; - $request['options']['type'] = $request['type']; - } - else { - if (empty($request['options']['type'])) { - $request['options']['type'] = $request['type']; - } - $request['options'] = array_merge($options, $request['options']); - } - - self::set_defaults($request['url'], $request['headers'], $request['data'], $request['type'], $request['options']); - - // Ensure we only hook in once - if ($request['options']['hooks'] !== $options['hooks']) { - $request['options']['hooks']->register('transport.internal.parse_response', [static::class, 'parse_multiple']); - if (!empty($request['options']['complete'])) { - $request['options']['hooks']->register('multiple.request.complete', $request['options']['complete']); - } - } - } - unset($request); - - if (!empty($options['transport'])) { - $transport = $options['transport']; - - if (is_string($options['transport'])) { - $transport = new $transport(); - } - } - else { - $transport = self::get_transport(); - } - $responses = $transport->request_multiple($requests, $options); - - foreach ($responses as $id => &$response) { - // If our hook got messed with somehow, ensure we end up with the - // correct response - if (is_string($response)) { - $request = $requests[$id]; - self::parse_multiple($response, $request); - $request['options']['hooks']->dispatch('multiple.request.complete', [&$response, $id]); - } - } - - return $responses; - } - - /** - * Get the default options - * - * @see \WpOrg\Requests\Requests::request() for values returned by this method - * @param boolean $multirequest Is this a multirequest? - * @return array Default option values - */ - protected static function get_default_options($multirequest = false) { - $defaults = static::OPTION_DEFAULTS; - $defaults['verify'] = self::$certificate_path; - - if ($multirequest !== false) { - $defaults['complete'] = null; - } - return $defaults; - } - - /** - * Get default certificate path. - * - * @return string Default certificate path. - */ - public static function get_certificate_path() { - return self::$certificate_path; - } - - /** - * Set default certificate path. - * - * @param string|Stringable|bool $path Certificate path, pointing to a PEM file. - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string, Stringable or boolean. - */ - public static function set_certificate_path($path) { - if (InputValidator::is_string_or_stringable($path) === false && is_bool($path) === false) { - throw InvalidArgument::create(1, '$path', 'string|Stringable|bool', gettype($path)); - } - - self::$certificate_path = $path; - } - - /** - * Set the default values - * - * @param string $url URL to request - * @param array $headers Extra headers to send with the request - * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests - * @param string $type HTTP request type - * @param array $options Options for the request - * @return void $options is updated with the results - * - * @throws \WpOrg\Requests\Exception When the $url is not an http(s) URL. - */ - protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) { - if (!preg_match('/^http(s)?:\/\//i', $url, $matches)) { - throw new Exception('Only HTTP(S) requests are handled.', 'nonhttp', $url); - } - - if (empty($options['hooks'])) { - $options['hooks'] = new Hooks(); - } - - if (is_array($options['auth'])) { - $options['auth'] = new Basic($options['auth']); - } - if ($options['auth'] !== false) { - $options['auth']->register($options['hooks']); - } - - if (is_string($options['proxy']) || is_array($options['proxy'])) { - $options['proxy'] = new Http($options['proxy']); - } - if ($options['proxy'] !== false) { - $options['proxy']->register($options['hooks']); - } - - if (is_array($options['cookies'])) { - $options['cookies'] = new Jar($options['cookies']); - } - elseif (empty($options['cookies'])) { - $options['cookies'] = new Jar(); - } - if ($options['cookies'] !== false) { - $options['cookies']->register($options['hooks']); - } - - if ($options['idn'] !== false) { - $iri = new Iri($url); - $iri->host = IdnaEncoder::encode($iri->ihost); - $url = $iri->uri; - } - - // Massage the type to ensure we support it. - $type = strtoupper($type); - - if (!isset($options['data_format'])) { - if (in_array($type, [self::HEAD, self::GET, self::DELETE], true)) { - $options['data_format'] = 'query'; - } - else { - $options['data_format'] = 'body'; - } - } - } - - /** - * HTTP response parser - * - * @param string $headers Full response text including headers and body - * @param string $url Original request URL - * @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects - * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects - * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects - * @return \WpOrg\Requests\Response - * - * @throws \WpOrg\Requests\Exception On missing head/body separator (`requests.no_crlf_separator`) - * @throws \WpOrg\Requests\Exception On missing head/body separator (`noversion`) - * @throws \WpOrg\Requests\Exception On missing head/body separator (`toomanyredirects`) - */ - protected static function parse_response($headers, $url, $req_headers, $req_data, $options) { - $return = new Response(); - if (!$options['blocking']) { - return $return; - } - - $return->raw = $headers; - $return->url = (string) $url; - $return->body = ''; - - if (!$options['filename']) { - $pos = strpos($headers, "\r\n\r\n"); - if ($pos === false) { - // Crap! - throw new Exception('Missing header/body separator', 'requests.no_crlf_separator'); - } - - $headers = substr($return->raw, 0, $pos); - // Headers will always be separated from the body by two new lines - `\n\r\n\r`. - $body = substr($return->raw, $pos + 4); - if (!empty($body)) { - $return->body = $body; - } - } - // Pretend CRLF = LF for compatibility (RFC 2616, section 19.3) - $headers = str_replace("\r\n", "\n", $headers); - // Unfold headers (replace [CRLF] 1*( SP | HT ) with SP) as per RFC 2616 (section 2.2) - $headers = preg_replace('/\n[ \t]/', ' ', $headers); - $headers = explode("\n", $headers); - preg_match('#^HTTP/(1\.\d)[ \t]+(\d+)#i', array_shift($headers), $matches); - if (empty($matches)) { - throw new Exception('Response could not be parsed', 'noversion', $headers); - } - $return->protocol_version = (float) $matches[1]; - $return->status_code = (int) $matches[2]; - if ($return->status_code >= 200 && $return->status_code < 300) { - $return->success = true; - } - - foreach ($headers as $header) { - list($key, $value) = explode(':', $header, 2); - $value = trim($value); - preg_replace('#(\s+)#i', ' ', $value); - $return->headers[$key] = $value; - } - if (isset($return->headers['transfer-encoding'])) { - $return->body = self::decode_chunked($return->body); - unset($return->headers['transfer-encoding']); - } - if (isset($return->headers['content-encoding'])) { - $return->body = self::decompress($return->body); - } - - //fsockopen and cURL compatibility - if (isset($return->headers['connection'])) { - unset($return->headers['connection']); - } - - $options['hooks']->dispatch('requests.before_redirect_check', [&$return, $req_headers, $req_data, $options]); - - if ($return->is_redirect() && $options['follow_redirects'] === true) { - if (isset($return->headers['location']) && $options['redirected'] < $options['redirects']) { - if ($return->status_code === 303) { - $options['type'] = self::GET; - } - $options['redirected']++; - $location = $return->headers['location']; - if (strpos($location, 'http://') !== 0 && strpos($location, 'https://') !== 0) { - // relative redirect, for compatibility make it absolute - $location = Iri::absolutize($url, $location); - $location = $location->uri; - } - - $hook_args = [ - &$location, - &$req_headers, - &$req_data, - &$options, - $return, - ]; - $options['hooks']->dispatch('requests.before_redirect', $hook_args); - $redirected = self::request($location, $req_headers, $req_data, $options['type'], $options); - $redirected->history[] = $return; - return $redirected; - } - elseif ($options['redirected'] >= $options['redirects']) { - throw new Exception('Too many redirects', 'toomanyredirects', $return); - } - } - - $return->redirects = $options['redirected']; - - $options['hooks']->dispatch('requests.after_request', [&$return, $req_headers, $req_data, $options]); - return $return; - } - - /** - * Callback for `transport.internal.parse_response` - * - * Internal use only. Converts a raw HTTP response to a \WpOrg\Requests\Response - * while still executing a multiple request. - * - * @param string $response Full response text including headers and body (will be overwritten with Response instance) - * @param array $request Request data as passed into {@see \WpOrg\Requests\Requests::request_multiple()} - * @return void `$response` is either set to a \WpOrg\Requests\Response instance, or a \WpOrg\Requests\Exception object - */ - public static function parse_multiple(&$response, $request) { - try { - $url = $request['url']; - $headers = $request['headers']; - $data = $request['data']; - $options = $request['options']; - $response = self::parse_response($response, $url, $headers, $data, $options); - } - catch (Exception $e) { - $response = $e; - } - } - - /** - * Decoded a chunked body as per RFC 2616 - * - * @link https://tools.ietf.org/html/rfc2616#section-3.6.1 - * @param string $data Chunked body - * @return string Decoded body - */ - protected static function decode_chunked($data) { - if (!preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', trim($data))) { - return $data; - } - - $decoded = ''; - $encoded = $data; - - while (true) { - $is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', $encoded, $matches); - if (!$is_chunked) { - // Looks like it's not chunked after all - return $data; - } - - $length = hexdec(trim($matches[1])); - if ($length === 0) { - // Ignore trailer headers - return $decoded; - } - - $chunk_length = strlen($matches[0]); - $decoded .= substr($encoded, $chunk_length, $length); - $encoded = substr($encoded, $chunk_length + $length + 2); - - if (trim($encoded) === '0' || empty($encoded)) { - return $decoded; - } - } - - // We'll never actually get down here - // @codeCoverageIgnoreStart - } - // @codeCoverageIgnoreEnd - - /** - * Convert a key => value array to a 'key: value' array for headers - * - * @param iterable $dictionary Dictionary of header values - * @return array List of headers - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not iterable. - */ - public static function flatten($dictionary) { - if (InputValidator::is_iterable($dictionary) === false) { - throw InvalidArgument::create(1, '$dictionary', 'iterable', gettype($dictionary)); - } - - $return = []; - foreach ($dictionary as $key => $value) { - $return[] = sprintf('%s: %s', $key, $value); - } - return $return; - } - - /** - * Decompress an encoded body - * - * Implements gzip, compress and deflate. Guesses which it is by attempting - * to decode. - * - * @param string $data Compressed data in one of the above formats - * @return string Decompressed string - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string. - */ - public static function decompress($data) { - if (is_string($data) === false) { - throw InvalidArgument::create(1, '$data', 'string', gettype($data)); - } - - if (trim($data) === '') { - // Empty body does not need further processing. - return $data; - } - - $marker = substr($data, 0, 2); - if (!isset(self::$magic_compression_headers[$marker])) { - // Not actually compressed. Probably cURL ruining this for us. - return $data; - } - - if (function_exists('gzdecode')) { - $decoded = @gzdecode($data); - if ($decoded !== false) { - return $decoded; - } - } - - if (function_exists('gzinflate')) { - $decoded = @gzinflate($data); - if ($decoded !== false) { - return $decoded; - } - } - - $decoded = self::compatible_gzinflate($data); - if ($decoded !== false) { - return $decoded; - } - - if (function_exists('gzuncompress')) { - $decoded = @gzuncompress($data); - if ($decoded !== false) { - return $decoded; - } - } - - return $data; - } - - /** - * Decompression of deflated string while staying compatible with the majority of servers. - * - * Certain Servers will return deflated data with headers which PHP's gzinflate() - * function cannot handle out of the box. The following function has been created from - * various snippets on the gzinflate() PHP documentation. - * - * Warning: Magic numbers within. Due to the potential different formats that the compressed - * data may be returned in, some "magic offsets" are needed to ensure proper decompression - * takes place. For a simple progmatic way to determine the magic offset in use, see: - * https://core.trac.wordpress.org/ticket/18273 - * - * @since 1.6.0 - * @link https://core.trac.wordpress.org/ticket/18273 - * @link https://www.php.net/gzinflate#70875 - * @link https://www.php.net/gzinflate#77336 - * - * @param string $gz_data String to decompress. - * @return string|bool False on failure. - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string. - */ - public static function compatible_gzinflate($gz_data) { - if (is_string($gz_data) === false) { - throw InvalidArgument::create(1, '$gz_data', 'string', gettype($gz_data)); - } - - if (trim($gz_data) === '') { - return false; - } - - // Compressed data might contain a full zlib header, if so strip it for - // gzinflate() - if (substr($gz_data, 0, 3) === "\x1f\x8b\x08") { - $i = 10; - $flg = ord(substr($gz_data, 3, 1)); - if ($flg > 0) { - if ($flg & 4) { - list($xlen) = unpack('v', substr($gz_data, $i, 2)); - $i += 2 + $xlen; - } - if ($flg & 8) { - $i = strpos($gz_data, "\0", $i) + 1; - } - if ($flg & 16) { - $i = strpos($gz_data, "\0", $i) + 1; - } - if ($flg & 2) { - $i += 2; - } - } - $decompressed = self::compatible_gzinflate(substr($gz_data, $i)); - if ($decompressed !== false) { - return $decompressed; - } - } - - // If the data is Huffman Encoded, we must first strip the leading 2 - // byte Huffman marker for gzinflate() - // The response is Huffman coded by many compressors such as - // java.util.zip.Deflater, Ruby's Zlib::Deflate, and .NET's - // System.IO.Compression.DeflateStream. - // - // See https://decompres.blogspot.com/ for a quick explanation of this - // data type - $huffman_encoded = false; - - // low nibble of first byte should be 0x08 - list(, $first_nibble) = unpack('h', $gz_data); - - // First 2 bytes should be divisible by 0x1F - list(, $first_two_bytes) = unpack('n', $gz_data); - - if ($first_nibble === 0x08 && ($first_two_bytes % 0x1F) === 0) { - $huffman_encoded = true; - } - - if ($huffman_encoded) { - $decompressed = @gzinflate(substr($gz_data, 2)); - if ($decompressed !== false) { - return $decompressed; - } - } - - if (substr($gz_data, 0, 4) === "\x50\x4b\x03\x04") { - // ZIP file format header - // Offset 6: 2 bytes, General-purpose field - // Offset 26: 2 bytes, filename length - // Offset 28: 2 bytes, optional field length - // Offset 30: Filename field, followed by optional field, followed - // immediately by data - list(, $general_purpose_flag) = unpack('v', substr($gz_data, 6, 2)); - - // If the file has been compressed on the fly, 0x08 bit is set of - // the general purpose field. We can use this to differentiate - // between a compressed document, and a ZIP file - $zip_compressed_on_the_fly = ((0x08 & $general_purpose_flag) === 0x08); - - if (!$zip_compressed_on_the_fly) { - // Don't attempt to decode a compressed zip file - return $gz_data; - } - - // Determine the first byte of data, based on the above ZIP header - // offsets: - $first_file_start = array_sum(unpack('v2', substr($gz_data, 26, 4))); - $decompressed = @gzinflate(substr($gz_data, 30 + $first_file_start)); - if ($decompressed !== false) { - return $decompressed; - } - return false; - } - - // Finally fall back to straight gzinflate - $decompressed = @gzinflate($gz_data); - if ($decompressed !== false) { - return $decompressed; - } - - // Fallback for all above failing, not expected, but included for - // debugging and preventing regressions and to track stats - $decompressed = @gzinflate(substr($gz_data, 2)); - if ($decompressed !== false) { - return $decompressed; - } - - return false; - } -} diff --git a/wp-includes/Requests/Response.php b/wp-includes/Requests/Response.php index 82ab481ba4..20861dfb82 100644 --- a/wp-includes/Requests/Response.php +++ b/wp-includes/Requests/Response.php @@ -2,26 +2,24 @@ /** * HTTP response class * - * Contains a response from \WpOrg\Requests\Requests::request() - * + * Contains a response from Requests::request() * @package Requests */ -namespace WpOrg\Requests; - -use WpOrg\Requests\Cookie\Jar; -use WpOrg\Requests\Exception; -use WpOrg\Requests\Exception\Http; -use WpOrg\Requests\Response\Headers; - /** * HTTP response class * - * Contains a response from \WpOrg\Requests\Requests::request() - * + * Contains a response from Requests::request() * @package Requests */ -class Response { +class Requests_Response { + /** + * Constructor + */ + public function __construct() { + $this->headers = new Requests_Response_Headers(); + $this->cookies = new Requests_Cookie_Jar(); + } /** * Response body @@ -40,9 +38,9 @@ class Response { /** * Headers, as an associative array * - * @var \WpOrg\Requests\Response\Headers Array-like object representing headers + * @var Requests_Response_Headers Array-like object representing headers */ - public $headers = []; + public $headers = array(); /** * Status code, false if non-blocking @@ -82,24 +80,16 @@ class Response { /** * Previous requests (from redirects) * - * @var array Array of \WpOrg\Requests\Response objects + * @var array Array of Requests_Response objects */ - public $history = []; + public $history = array(); /** * Cookies from the request * - * @var \WpOrg\Requests\Cookie\Jar Array-like object representing a cookie jar + * @var Requests_Cookie_Jar Array-like object representing a cookie jar */ - public $cookies = []; - - /** - * Constructor - */ - public function __construct() { - $this->headers = new Headers(); - $this->cookies = new Jar(); - } + public $cookies = array(); /** * Is the response a redirect? @@ -108,59 +98,25 @@ class Response { */ public function is_redirect() { $code = $this->status_code; - return in_array($code, [300, 301, 302, 303, 307], true) || $code > 307 && $code < 400; + return in_array($code, array(300, 301, 302, 303, 307), true) || $code > 307 && $code < 400; } /** * Throws an exception if the request was not successful * + * @throws Requests_Exception If `$allow_redirects` is false, and code is 3xx (`response.no_redirects`) + * @throws Requests_Exception_HTTP On non-successful status code. Exception class corresponds to code (e.g. {@see Requests_Exception_HTTP_404}) * @param boolean $allow_redirects Set to false to throw on a 3xx as well - * - * @throws \WpOrg\Requests\Exception If `$allow_redirects` is false, and code is 3xx (`response.no_redirects`) - * @throws \WpOrg\Requests\Exception\Http On non-successful status code. Exception class corresponds to "Status" + code (e.g. {@see \WpOrg\Requests\Exception\Http\Status404}) */ public function throw_for_status($allow_redirects = true) { if ($this->is_redirect()) { - if ($allow_redirects !== true) { - throw new Exception('Redirection not allowed', 'response.no_redirects', $this); + if (!$allow_redirects) { + throw new Requests_Exception('Redirection not allowed', 'response.no_redirects', $this); } } elseif (!$this->success) { - $exception = Http::get_class($this->status_code); + $exception = Requests_Exception_HTTP::get_class($this->status_code); throw new $exception(null, $this); } } - - /** - * JSON decode the response body. - * - * The method parameters are the same as those for the PHP native `json_decode()` function. - * - * @link https://php.net/json-decode - * - * @param ?bool $associative Optional. When `true`, JSON objects will be returned as associative arrays; - * When `false`, JSON objects will be returned as objects. - * When `null`, JSON objects will be returned as associative arrays - * or objects depending on whether `JSON_OBJECT_AS_ARRAY` is set in the flags. - * Defaults to `true` (in contrast to the PHP native default of `null`). - * @param int $depth Optional. Maximum nesting depth of the structure being decoded. - * Defaults to `512`. - * @param int $options Optional. Bitmask of JSON_BIGINT_AS_STRING, JSON_INVALID_UTF8_IGNORE, - * JSON_INVALID_UTF8_SUBSTITUTE, JSON_OBJECT_AS_ARRAY, JSON_THROW_ON_ERROR. - * Defaults to `0` (no options set). - * - * @return array - * - * @throws \WpOrg\Requests\Exception If `$this->body` is not valid json. - */ - public function decode_body($associative = true, $depth = 512, $options = 0) { - $data = json_decode($this->body, $associative, $depth, $options); - - if (json_last_error() !== JSON_ERROR_NONE) { - $last_error = json_last_error_msg(); - throw new Exception('Unable to parse JSON data: ' . $last_error, 'response.invalid', $this); - } - - return $data; - } } diff --git a/wp-includes/Requests/Response/Headers.php b/wp-includes/Requests/Response/Headers.php index eb4f68736b..12db128ae5 100644 --- a/wp-includes/Requests/Response/Headers.php +++ b/wp-includes/Requests/Response/Headers.php @@ -5,86 +5,68 @@ * @package Requests */ -namespace WpOrg\Requests\Response; - -use WpOrg\Requests\Exception; -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\Utility\CaseInsensitiveDictionary; -use WpOrg\Requests\Utility\FilteredIterator; - /** * Case-insensitive dictionary, suitable for HTTP headers * * @package Requests */ -class Headers extends CaseInsensitiveDictionary { +class Requests_Response_Headers extends Requests_Utility_CaseInsensitiveDictionary { /** * Get the given header * - * Unlike {@see \WpOrg\Requests\Response\Headers::getValues()}, this returns a string. If there are + * Unlike {@see self::getValues()}, this returns a string. If there are * multiple values, it concatenates them with a comma as per RFC2616. * * Avoid using this where commas may be used unquoted in values, such as * Set-Cookie headers. * - * @param string $offset + * @param string $key * @return string|null Header value */ - public function offsetGet($offset) { - if (is_string($offset)) { - $offset = strtolower($offset); - } - - if (!isset($this->data[$offset])) { + public function offsetGet($key) { + $key = strtolower($key); + if (!isset($this->data[$key])) { return null; } - return $this->flatten($this->data[$offset]); + return $this->flatten($this->data[$key]); } /** * Set the given item * - * @param string $offset Item name - * @param string $value Item value + * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`) * - * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`) + * @param string $key Item name + * @param string $value Item value */ - public function offsetSet($offset, $value) { - if ($offset === null) { - throw new Exception('Object is a dictionary, not a list', 'invalidset'); + public function offsetSet($key, $value) { + if ($key === null) { + throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset'); } - if (is_string($offset)) { - $offset = strtolower($offset); + $key = strtolower($key); + + if (!isset($this->data[$key])) { + $this->data[$key] = array(); } - if (!isset($this->data[$offset])) { - $this->data[$offset] = []; - } - - $this->data[$offset][] = $value; + $this->data[$key][] = $value; } /** * Get all values for a given header * - * @param string $offset + * @param string $key * @return array|null Header values - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not valid as an array key. */ - public function getValues($offset) { - if (!is_string($offset) && !is_int($offset)) { - throw InvalidArgument::create(1, '$offset', 'string|int', gettype($offset)); - } - - $offset = strtolower($offset); - if (!isset($this->data[$offset])) { + public function getValues($key) { + $key = strtolower($key); + if (!isset($this->data[$key])) { return null; } - return $this->data[$offset]; + return $this->data[$key]; } /** @@ -95,30 +77,22 @@ class Headers extends CaseInsensitiveDictionary { * * @param string|array $value Value to flatten * @return string Flattened value - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or an array. */ public function flatten($value) { - if (is_string($value)) { - return $value; - } - if (is_array($value)) { - return implode(',', $value); + $value = implode(',', $value); } - throw InvalidArgument::create(1, '$value', 'string|array', gettype($value)); + return $value; } /** * Get an iterator for the data * - * Converts the internally stored values to a comma-separated string if there is more - * than one value for a key. - * - * @return \ArrayIterator + * Converts the internal + * @return ArrayIterator */ public function getIterator() { - return new FilteredIterator($this->data, [$this, 'flatten']); + return new Requests_Utility_FilteredIterator($this->data, array($this, 'flatten')); } } diff --git a/wp-includes/Requests/Ssl.php b/wp-includes/Requests/SSL.php similarity index 55% rename from wp-includes/Requests/Ssl.php rename to wp-includes/Requests/SSL.php index 99da11d8f7..f7ecf3fbdb 100644 --- a/wp-includes/Requests/Ssl.php +++ b/wp-includes/Requests/SSL.php @@ -2,49 +2,37 @@ /** * SSL utilities for Requests * - * @package Requests\Utilities + * @package Requests + * @subpackage Utilities */ -namespace WpOrg\Requests; - -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\Utility\InputValidator; - /** * SSL utilities for Requests * * Collection of utilities for working with and verifying SSL certificates. * - * @package Requests\Utilities + * @package Requests + * @subpackage Utilities */ -final class Ssl { +class Requests_SSL { /** * Verify the certificate against common name and subject alternative names * * Unfortunately, PHP doesn't check the certificate against the alternative * names, leading things like 'https://www.github.com/' to be invalid. * - * @link https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1 + * @see https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1 * - * @param string|Stringable $host Host name to verify against + * @throws Requests_Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`) + * @param string $host Host name to verify against * @param array $cert Certificate data from openssl_x509_parse() * @return bool - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $host argument is not a string or a stringable object. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $cert argument is not an array or array accessible. */ public static function verify_certificate($host, $cert) { - if (InputValidator::is_string_or_stringable($host) === false) { - throw InvalidArgument::create(1, '$host', 'string|Stringable', gettype($host)); - } - - if (InputValidator::has_array_access($cert) === false) { - throw InvalidArgument::create(2, '$cert', 'array|ArrayAccess', gettype($cert)); - } - $has_dns_alt = false; // Check the subjectAltName - if (!empty($cert['extensions']['subjectAltName'])) { + if (!empty($cert['extensions']) && !empty($cert['extensions']['subjectAltName'])) { $altnames = explode(',', $cert['extensions']['subjectAltName']); foreach ($altnames as $altname) { $altname = trim($altname); @@ -62,17 +50,15 @@ final class Ssl { return true; } } - - if ($has_dns_alt === true) { - return false; - } } // Fall back to checking the common name if we didn't get any dNSName // alt names, as per RFC2818 - if (!empty($cert['subject']['CN'])) { + if (!$has_dns_alt && !empty($cert['subject']['CN'])) { // Check for a match - return (self::match_domain($host, $cert['subject']['CN']) === true); + if (self::match_domain($host, $cert['subject']['CN']) === true) { + return true; + } } return false; @@ -91,29 +77,11 @@ final class Ssl { * character to be the full first component; that is, with the exclusion of * the third rule. * - * @param string|Stringable $reference Reference dNSName + * @param string $reference Reference dNSName * @return boolean Is the name valid? - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or a stringable object. */ public static function verify_reference_name($reference) { - if (InputValidator::is_string_or_stringable($reference) === false) { - throw InvalidArgument::create(1, '$reference', 'string|Stringable', gettype($reference)); - } - - if ($reference === '') { - return false; - } - - if (preg_match('`\s`', $reference) > 0) { - // Whitespace detected. This can never be a dNSName. - return false; - } - $parts = explode('.', $reference); - if ($parts !== array_filter($parts)) { - // DNSName cannot contain two dots next to each other. - return false; - } // Check the first part of the name $first = array_shift($parts); @@ -144,35 +112,29 @@ final class Ssl { /** * Match a hostname against a dNSName reference * - * @param string|Stringable $host Requested host - * @param string|Stringable $reference dNSName to match against + * @param string $host Requested host + * @param string $reference dNSName to match against * @return boolean Does the domain match? - * @throws \WpOrg\Requests\Exception\InvalidArgument When either of the passed arguments is not a string or a stringable object. */ public static function match_domain($host, $reference) { - if (InputValidator::is_string_or_stringable($host) === false) { - throw InvalidArgument::create(1, '$host', 'string|Stringable', gettype($host)); - } - // Check if the reference is blocklisted first if (self::verify_reference_name($reference) !== true) { return false; } // Check for a direct match - if ((string) $host === (string) $reference) { + if ($host === $reference) { return true; } // Calculate the valid wildcard match if the host is not an IP address - // Also validates that the host has 3 parts or more, as per Firefox's ruleset, - // as a wildcard reference is only allowed with 3 parts or more, so the - // comparison will never match if host doesn't contain 3 parts or more as well. + // Also validates that the host has 3 parts or more, as per Firefox's + // ruleset. if (ip2long($host) === false) { $parts = explode('.', $host); $parts[0] = '*'; $wildcard = implode('.', $parts); - if ($wildcard === (string) $reference) { + if ($wildcard === $reference) { return true; } } diff --git a/wp-includes/Requests/Session.php b/wp-includes/Requests/Session.php index abecc05f77..b2e10991d6 100644 --- a/wp-includes/Requests/Session.php +++ b/wp-includes/Requests/Session.php @@ -2,17 +2,10 @@ /** * Session handler for persistent requests and default parameters * - * @package Requests\SessionHandler + * @package Requests + * @subpackage Session Handler */ -namespace WpOrg\Requests; - -use WpOrg\Requests\Cookie\Jar; -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\Iri; -use WpOrg\Requests\Requests; -use WpOrg\Requests\Utility\InputValidator; - /** * Session handler for persistent requests and default parameters * @@ -21,9 +14,10 @@ use WpOrg\Requests\Utility\InputValidator; * with all subrequests resolved from this. Base options can be set (including * a shared cookie jar), then overridden for individual requests. * - * @package Requests\SessionHandler + * @package Requests + * @subpackage Session Handler */ -class Session { +class Requests_Session { /** * Base URL for requests * @@ -38,7 +32,7 @@ class Session { * * @var array */ - public $headers = []; + public $headers = array(); /** * Base data for requests @@ -48,7 +42,7 @@ class Session { * * @var array */ - public $data = []; + public $data = array(); /** * Base options for requests @@ -61,57 +55,36 @@ class Session { * * @var array */ - public $options = []; + public $options = array(); /** * Create a new session * - * @param string|Stringable|null $url Base URL for requests + * @param string|null $url Base URL for requests * @param array $headers Default headers for requests * @param array $data Default data for requests * @param array $options Default options for requests - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string, Stringable or null. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $headers argument is not an array. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data argument is not an array. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. */ - public function __construct($url = null, $headers = [], $data = [], $options = []) { - if ($url !== null && InputValidator::is_string_or_stringable($url) === false) { - throw InvalidArgument::create(1, '$url', 'string|Stringable|null', gettype($url)); - } - - if (is_array($headers) === false) { - throw InvalidArgument::create(2, '$headers', 'array', gettype($headers)); - } - - if (is_array($data) === false) { - throw InvalidArgument::create(3, '$data', 'array', gettype($data)); - } - - if (is_array($options) === false) { - throw InvalidArgument::create(4, '$options', 'array', gettype($options)); - } - + public function __construct($url = null, $headers = array(), $data = array(), $options = array()) { $this->url = $url; $this->headers = $headers; $this->data = $data; $this->options = $options; if (empty($this->options['cookies'])) { - $this->options['cookies'] = new Jar(); + $this->options['cookies'] = new Requests_Cookie_Jar(); } } /** * Get a property's value * - * @param string $name Property name. + * @param string $key Property key * @return mixed|null Property value, null if none found */ - public function __get($name) { - if (isset($this->options[$name])) { - return $this->options[$name]; + public function __get($key) { + if (isset($this->options[$key])) { + return $this->options[$key]; } return null; @@ -120,91 +93,93 @@ class Session { /** * Set a property's value * - * @param string $name Property name. + * @param string $key Property key * @param mixed $value Property value */ - public function __set($name, $value) { - $this->options[$name] = $value; + public function __set($key, $value) { + $this->options[$key] = $value; } /** * Remove a property's value * - * @param string $name Property name. + * @param string $key Property key */ - public function __isset($name) { - return isset($this->options[$name]); + public function __isset($key) { + return isset($this->options[$key]); } /** * Remove a property's value * - * @param string $name Property name. + * @param string $key Property key */ - public function __unset($name) { - unset($this->options[$name]); + public function __unset($key) { + if (isset($this->options[$key])) { + unset($this->options[$key]); + } } /**#@+ - * @see \WpOrg\Requests\Session::request() + * @see request() * @param string $url * @param array $headers * @param array $options - * @return \WpOrg\Requests\Response + * @return Requests_Response */ /** * Send a GET request */ - public function get($url, $headers = [], $options = []) { + public function get($url, $headers = array(), $options = array()) { return $this->request($url, $headers, null, Requests::GET, $options); } /** * Send a HEAD request */ - public function head($url, $headers = [], $options = []) { + public function head($url, $headers = array(), $options = array()) { return $this->request($url, $headers, null, Requests::HEAD, $options); } /** * Send a DELETE request */ - public function delete($url, $headers = [], $options = []) { + public function delete($url, $headers = array(), $options = array()) { return $this->request($url, $headers, null, Requests::DELETE, $options); } /**#@-*/ /**#@+ - * @see \WpOrg\Requests\Session::request() + * @see request() * @param string $url * @param array $headers * @param array $data * @param array $options - * @return \WpOrg\Requests\Response + * @return Requests_Response */ /** * Send a POST request */ - public function post($url, $headers = [], $data = [], $options = []) { + public function post($url, $headers = array(), $data = array(), $options = array()) { return $this->request($url, $headers, $data, Requests::POST, $options); } /** * Send a PUT request */ - public function put($url, $headers = [], $data = [], $options = []) { + public function put($url, $headers = array(), $data = array(), $options = array()) { return $this->request($url, $headers, $data, Requests::PUT, $options); } /** * Send a PATCH request * - * Note: Unlike {@see \WpOrg\Requests\Session::post()} and {@see \WpOrg\Requests\Session::put()}, - * `$headers` is required, as the specification recommends that should send an ETag + * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the + * specification recommends that should send an ETag * * @link https://tools.ietf.org/html/rfc5789 */ - public function patch($url, $headers, $data = [], $options = []) { + public function patch($url, $headers, $data = array(), $options = array()) { return $this->request($url, $headers, $data, Requests::PATCH, $options); } /**#@-*/ @@ -215,18 +190,18 @@ class Session { * This method initiates a request and sends it via a transport before * parsing. * - * @see \WpOrg\Requests\Requests::request() + * @see Requests::request() + * + * @throws Requests_Exception On invalid URLs (`nonhttp`) * * @param string $url URL to request * @param array $headers Extra headers to send with the request * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests - * @param string $type HTTP request type (use \WpOrg\Requests\Requests constants) - * @param array $options Options for the request (see {@see \WpOrg\Requests\Requests::request()}) - * @return \WpOrg\Requests\Response - * - * @throws \WpOrg\Requests\Exception On invalid URLs (`nonhttp`) + * @param string $type HTTP request type (use Requests constants) + * @param array $options Options for the request (see {@see Requests::request}) + * @return Requests_Response */ - public function request($url, $headers = [], $data = [], $type = Requests::GET, $options = []) { + public function request($url, $headers = array(), $data = array(), $type = Requests::GET, $options = array()) { $request = $this->merge_request(compact('url', 'headers', 'data', 'options')); return Requests::request($request['url'], $request['headers'], $request['data'], $type, $request['options']); @@ -235,24 +210,13 @@ class Session { /** * Send multiple HTTP requests simultaneously * - * @see \WpOrg\Requests\Requests::request_multiple() + * @see Requests::request_multiple() * - * @param array $requests Requests data (see {@see \WpOrg\Requests\Requests::request_multiple()}) - * @param array $options Global and default options (see {@see \WpOrg\Requests\Requests::request()}) - * @return array Responses (either \WpOrg\Requests\Response or a \WpOrg\Requests\Exception object) - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. + * @param array $requests Requests data (see {@see Requests::request_multiple}) + * @param array $options Global and default options (see {@see Requests::request}) + * @return array Responses (either Requests_Response or a Requests_Exception object) */ - public function request_multiple($requests, $options = []) { - if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { - throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); - } - - if (is_array($options) === false) { - throw InvalidArgument::create(2, '$options', 'array', gettype($options)); - } - + public function request_multiple($requests, $options = array()) { foreach ($requests as $key => $request) { $requests[$key] = $this->merge_request($request, false); } @@ -268,18 +232,18 @@ class Session { /** * Merge a request's data with the default data * - * @param array $request Request data (same form as {@see \WpOrg\Requests\Session::request_multiple()}) + * @param array $request Request data (same form as {@see request_multiple}) * @param boolean $merge_options Should we merge options as well? * @return array Request data */ protected function merge_request($request, $merge_options = true) { if ($this->url !== null) { - $request['url'] = Iri::absolutize($this->url, $request['url']); + $request['url'] = Requests_IRI::absolutize($this->url, $request['url']); $request['url'] = $request['url']->uri; } if (empty($request['headers'])) { - $request['headers'] = []; + $request['headers'] = array(); } $request['headers'] = array_merge($this->headers, $request['headers']); @@ -292,7 +256,7 @@ class Session { $request['data'] = array_merge($this->data, $request['data']); } - if ($merge_options === true) { + if ($merge_options !== false) { $request['options'] = array_merge($this->options, $request['options']); // Disallow forcing the type, as that's a per request setting diff --git a/wp-includes/Requests/Transport.php b/wp-includes/Requests/Transport.php index f2e1c6ed73..5146c01d87 100644 --- a/wp-includes/Requests/Transport.php +++ b/wp-includes/Requests/Transport.php @@ -2,44 +2,40 @@ /** * Base HTTP transport * - * @package Requests\Transport + * @package Requests + * @subpackage Transport */ -namespace WpOrg\Requests; - /** * Base HTTP transport * - * @package Requests\Transport + * @package Requests + * @subpackage Transport */ -interface Transport { +interface Requests_Transport { /** * Perform a request * * @param string $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD - * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation + * @param array $options Request options, see {@see Requests::response()} for documentation * @return string Raw HTTP result */ - public function request($url, $headers = [], $data = [], $options = []); + public function request($url, $headers = array(), $data = array(), $options = array()); /** * Send multiple requests simultaneously * - * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see \WpOrg\Requests\Transport::request()} - * @param array $options Global options, see {@see \WpOrg\Requests\Requests::response()} for documentation - * @return array Array of \WpOrg\Requests\Response objects (may contain \WpOrg\Requests\Exception or string responses as well) + * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see Requests_Transport::request} + * @param array $options Global options, see {@see Requests::response()} for documentation + * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well) */ public function request_multiple($requests, $options); /** - * Self-test whether the transport can be used. - * - * The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}. - * - * @param array $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. - * @return bool Whether the transport can be used. + * Self-test whether the transport can be used + * @return bool */ - public static function test($capabilities = []); + public static function test(); } diff --git a/wp-includes/Requests/Transport/Curl.php b/wp-includes/Requests/Transport/cURL.php similarity index 70% rename from wp-includes/Requests/Transport/Curl.php rename to wp-includes/Requests/Transport/cURL.php index 289d9b15b9..01bcf3b719 100644 --- a/wp-includes/Requests/Transport/Curl.php +++ b/wp-includes/Requests/Transport/cURL.php @@ -2,27 +2,17 @@ /** * cURL HTTP transport * - * @package Requests\Transport + * @package Requests + * @subpackage Transport */ -namespace WpOrg\Requests\Transport; - -use RecursiveArrayIterator; -use RecursiveIteratorIterator; -use WpOrg\Requests\Capability; -use WpOrg\Requests\Exception; -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\Exception\Transport\Curl as CurlException; -use WpOrg\Requests\Requests; -use WpOrg\Requests\Transport; -use WpOrg\Requests\Utility\InputValidator; - /** * cURL HTTP transport * - * @package Requests\Transport + * @package Requests + * @subpackage Transport */ -final class Curl implements Transport { +class Requests_Transport_cURL implements Requests_Transport { const CURL_7_10_5 = 0x070A05; const CURL_7_16_2 = 0x071002; @@ -43,7 +33,7 @@ final class Curl implements Transport { /** * Information on the current request * - * @var array cURL information array, see {@link https://www.php.net/curl_getinfo} + * @var array cURL information array, see {@see https://secure.php.net/curl_getinfo} */ public $info; @@ -57,44 +47,44 @@ final class Curl implements Transport { /** * cURL handle * - * @var resource|\CurlHandle Resource in PHP < 8.0, Instance of CurlHandle in PHP >= 8.0. + * @var resource */ - private $handle; + protected $handle; /** * Hook dispatcher instance * - * @var \WpOrg\Requests\Hooks + * @var Requests_Hooks */ - private $hooks; + protected $hooks; /** * Have we finished the headers yet? * * @var boolean */ - private $done_headers = false; + protected $done_headers = false; /** * If streaming to a file, keep the file pointer * * @var resource */ - private $stream_handle; + protected $stream_handle; /** * How many bytes are in the response body? * * @var int */ - private $response_bytes; + protected $response_bytes; /** * What's the maximum number of bytes we should keep? * * @var int|bool Byte count, or false if no limit. */ - private $response_byte_limit; + protected $response_byte_limit; /** * Constructor @@ -131,52 +121,23 @@ final class Curl implements Transport { /** * Perform a request * - * @param string|Stringable $url URL to request + * @throws Requests_Exception On a cURL error (`curlerror`) + * + * @param string $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD - * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation + * @param array $options Request options, see {@see Requests::response()} for documentation * @return string Raw HTTP result - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string or Stringable. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $headers argument is not an array. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data parameter is not an array or string. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. - * @throws \WpOrg\Requests\Exception On a cURL error (`curlerror`) */ - public function request($url, $headers = [], $data = [], $options = []) { - if (InputValidator::is_string_or_stringable($url) === false) { - throw InvalidArgument::create(1, '$url', 'string|Stringable', gettype($url)); - } - - if (is_array($headers) === false) { - throw InvalidArgument::create(2, '$headers', 'array', gettype($headers)); - } - - if (!is_array($data) && !is_string($data)) { - if ($data === null) { - $data = ''; - } else { - throw InvalidArgument::create(3, '$data', 'array|string', gettype($data)); - } - } - - if (is_array($options) === false) { - throw InvalidArgument::create(4, '$options', 'array', gettype($options)); - } - + public function request($url, $headers = array(), $data = array(), $options = array()) { $this->hooks = $options['hooks']; $this->setup_handle($url, $headers, $data, $options); - $options['hooks']->dispatch('curl.before_send', [&$this->handle]); + $options['hooks']->dispatch('curl.before_send', array(&$this->handle)); if ($options['filename'] !== false) { - // phpcs:ignore WordPress.PHP.NoSilencedErrors -- Silenced the PHP native warning in favour of throwing an exception. - $this->stream_handle = @fopen($options['filename'], 'wb'); - if ($this->stream_handle === false) { - $error = error_get_last(); - throw new Exception($error['message'], 'fopen'); - } + $this->stream_handle = fopen($options['filename'], 'wb'); } $this->response_data = ''; @@ -203,9 +164,9 @@ final class Curl implements Transport { curl_exec($this->handle); $response = $this->response_data; - $options['hooks']->dispatch('curl.after_send', []); + $options['hooks']->dispatch('curl.after_send', array()); - if (curl_errno($this->handle) === CURLE_WRITE_ERROR || curl_errno($this->handle) === CURLE_BAD_CONTENT_ENCODING) { + if (curl_errno($this->handle) === 23 || curl_errno($this->handle) === 61) { // Reset encoding and try again curl_setopt($this->handle, CURLOPT_ENCODING, 'none'); @@ -218,7 +179,7 @@ final class Curl implements Transport { $this->process_response($response, $options); // Need to remove the $this reference from the curl handle. - // Otherwise \WpOrg\Requests\Transport\Curl won't be garbage collected and the curl_close() will never be called. + // Otherwise Requests_Transport_cURL wont be garbage collected and the curl_close() will never be called. curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, null); curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, null); @@ -230,42 +191,31 @@ final class Curl implements Transport { * * @param array $requests Request data * @param array $options Global options - * @return array Array of \WpOrg\Requests\Response objects (may contain \WpOrg\Requests\Exception or string responses as well) - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. + * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well) */ public function request_multiple($requests, $options) { // If you're not requesting, we can't get any responses ¯\_(ツ)_/¯ if (empty($requests)) { - return []; - } - - if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { - throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); - } - - if (is_array($options) === false) { - throw InvalidArgument::create(2, '$options', 'array', gettype($options)); + return array(); } $multihandle = curl_multi_init(); - $subrequests = []; - $subhandles = []; + $subrequests = array(); + $subhandles = array(); $class = get_class($this); foreach ($requests as $id => $request) { $subrequests[$id] = new $class(); $subhandles[$id] = $subrequests[$id]->get_subrequest_handle($request['url'], $request['headers'], $request['data'], $request['options']); - $request['options']['hooks']->dispatch('curl.before_multi_add', [&$subhandles[$id]]); + $request['options']['hooks']->dispatch('curl.before_multi_add', array(&$subhandles[$id])); curl_multi_add_handle($multihandle, $subhandles[$id]); } $completed = 0; - $responses = []; + $responses = array(); $subrequestcount = count($subrequests); - $request['options']['hooks']->dispatch('curl.before_multi_exec', [&$multihandle]); + $request['options']['hooks']->dispatch('curl.before_multi_exec', array(&$multihandle)); do { $active = 0; @@ -275,7 +225,7 @@ final class Curl implements Transport { } while ($status === CURLM_CALL_MULTI_PERFORM); - $to_process = []; + $to_process = array(); // Read the information as needed while ($done = curl_multi_info_read($multihandle)) { @@ -291,33 +241,33 @@ final class Curl implements Transport { if ($done['result'] !== CURLE_OK) { //get error string for handle. $reason = curl_error($done['handle']); - $exception = new CurlException( + $exception = new Requests_Exception_Transport_cURL( $reason, - CurlException::EASY, + Requests_Exception_Transport_cURL::EASY, $done['handle'], $done['result'] ); $responses[$key] = $exception; - $options['hooks']->dispatch('transport.internal.parse_error', [&$responses[$key], $requests[$key]]); + $options['hooks']->dispatch('transport.internal.parse_error', array(&$responses[$key], $requests[$key])); } else { $responses[$key] = $subrequests[$key]->process_response($subrequests[$key]->response_data, $options); - $options['hooks']->dispatch('transport.internal.parse_response', [&$responses[$key], $requests[$key]]); + $options['hooks']->dispatch('transport.internal.parse_response', array(&$responses[$key], $requests[$key])); } curl_multi_remove_handle($multihandle, $done['handle']); curl_close($done['handle']); if (!is_string($responses[$key])) { - $options['hooks']->dispatch('multiple.request.complete', [&$responses[$key], $key]); + $options['hooks']->dispatch('multiple.request.complete', array(&$responses[$key], $key)); } $completed++; } } while ($active || $completed < $subrequestcount); - $request['options']['hooks']->dispatch('curl.after_multi_exec', [&$multihandle]); + $request['options']['hooks']->dispatch('curl.after_multi_exec', array(&$multihandle)); curl_multi_close($multihandle); @@ -330,8 +280,8 @@ final class Curl implements Transport { * @param string $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD - * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation - * @return resource|\CurlHandle Subrequest's cURL handle + * @param array $options Request options, see {@see Requests::response()} for documentation + * @return resource Subrequest's cURL handle */ public function &get_subrequest_handle($url, $headers, $data, $options) { $this->setup_handle($url, $headers, $data, $options); @@ -357,10 +307,10 @@ final class Curl implements Transport { * @param string $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD - * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation + * @param array $options Request options, see {@see Requests::response()} for documentation */ - private function setup_handle($url, $headers, $data, $options) { - $options['hooks']->dispatch('curl.before_request', [&$this->handle]); + protected function setup_handle($url, $headers, $data, $options) { + $options['hooks']->dispatch('curl.before_request', array(&$this->handle)); // Force closing the connection for old versions of cURL (<7.22). if (!isset($headers['Connection'])) { @@ -392,7 +342,7 @@ final class Curl implements Transport { $data = ''; } elseif (!is_string($data)) { - $data = http_build_query($data, '', '&'); + $data = http_build_query($data, null, '&'); } } @@ -443,6 +393,7 @@ final class Curl implements Transport { curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT_MS, round($options['connect_timeout'] * 1000)); } curl_setopt($this->handle, CURLOPT_URL, $url); + curl_setopt($this->handle, CURLOPT_REFERER, $url); curl_setopt($this->handle, CURLOPT_USERAGENT, $options['useragent']); if (!empty($headers)) { curl_setopt($this->handle, CURLOPT_HTTPHEADER, $headers); @@ -455,8 +406,8 @@ final class Curl implements Transport { } if ($options['blocking'] === true) { - curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, [$this, 'stream_headers']); - curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, [$this, 'stream_body']); + curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, array($this, 'stream_headers')); + curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, array($this, 'stream_body')); curl_setopt($this->handle, CURLOPT_BUFFERSIZE, Requests::BUFFER_SIZE); } } @@ -467,12 +418,12 @@ final class Curl implements Transport { * @param string $response Response data from the body * @param array $options Request options * @return string|false HTTP response data including headers. False if non-blocking. - * @throws \WpOrg\Requests\Exception + * @throws Requests_Exception */ public function process_response($response, $options) { if ($options['blocking'] === false) { $fake_headers = ''; - $options['hooks']->dispatch('curl.after_request', [&$fake_headers]); + $options['hooks']->dispatch('curl.after_request', array(&$fake_headers)); return false; } if ($options['filename'] !== false && $this->stream_handle) { @@ -489,18 +440,18 @@ final class Curl implements Transport { curl_errno($this->handle), curl_error($this->handle) ); - throw new Exception($error, 'curlerror', $this->handle); + throw new Requests_Exception($error, 'curlerror', $this->handle); } $this->info = curl_getinfo($this->handle); - $options['hooks']->dispatch('curl.after_request', [&$this->headers, &$this->info]); + $options['hooks']->dispatch('curl.after_request', array(&$this->headers, &$this->info)); return $this->headers; } /** * Collect the headers as they are received * - * @param resource|\CurlHandle $handle cURL handle + * @param resource $handle cURL resource * @param string $headers Header string * @return integer Length of provided header */ @@ -525,12 +476,12 @@ final class Curl implements Transport { * * @since 1.6.1 * - * @param resource|\CurlHandle $handle cURL handle + * @param resource $handle cURL resource * @param string $data Body data * @return integer Length of provided data */ public function stream_body($handle, $data) { - $this->hooks->dispatch('request.progress', [$data, $this->response_bytes, $this->response_byte_limit]); + $this->hooks->dispatch('request.progress', array($data, $this->response_bytes, $this->response_byte_limit)); $data_length = strlen($data); // Are we limiting the response size? @@ -562,10 +513,10 @@ final class Curl implements Transport { * Format a URL given GET data * * @param string $url - * @param array|object $data Data to build query using, see {@link https://www.php.net/http_build_query} + * @param array|object $data Data to build query using, see {@see https://secure.php.net/http_build_query} * @return string URL with data */ - private static function format_get($url, $data) { + protected static function format_get($url, $data) { if (!empty($data)) { $query = ''; $url_parts = parse_url($url); @@ -576,7 +527,7 @@ final class Curl implements Transport { $query = $url_parts['query']; } - $query .= '&' . http_build_query($data, '', '&'); + $query .= '&' . http_build_query($data, null, '&'); $query = trim($query, '&'); if (empty($url_parts['query'])) { @@ -590,21 +541,18 @@ final class Curl implements Transport { } /** - * Self-test whether the transport can be used. - * - * The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}. + * Whether this transport is valid * * @codeCoverageIgnore - * @param array $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. - * @return bool Whether the transport can be used. + * @return boolean True if the transport is valid, false otherwise. */ - public static function test($capabilities = []) { + public static function test($capabilities = array()) { if (!function_exists('curl_init') || !function_exists('curl_exec')) { return false; } // If needed, check that our installed curl version supports SSL - if (isset($capabilities[Capability::SSL]) && $capabilities[Capability::SSL]) { + if (isset($capabilities['ssl']) && $capabilities['ssl']) { $curl_version = curl_version(); if (!(CURL_VERSION_SSL & $curl_version['features'])) { return false; @@ -620,7 +568,7 @@ final class Curl implements Transport { * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD. * @return string The "Expect" header. */ - private function get_expect_header($data) { + protected function get_expect_header($data) { if (!is_array($data)) { return strlen((string) $data) >= 1048576 ? '100-Continue' : ''; } diff --git a/wp-includes/Requests/Transport/Fsockopen.php b/wp-includes/Requests/Transport/fsockopen.php similarity index 59% rename from wp-includes/Requests/Transport/Fsockopen.php rename to wp-includes/Requests/Transport/fsockopen.php index 4779346add..56f94c99f2 100644 --- a/wp-includes/Requests/Transport/Fsockopen.php +++ b/wp-includes/Requests/Transport/fsockopen.php @@ -2,27 +2,17 @@ /** * fsockopen HTTP transport * - * @package Requests\Transport + * @package Requests + * @subpackage Transport */ -namespace WpOrg\Requests\Transport; - -use WpOrg\Requests\Capability; -use WpOrg\Requests\Exception; -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\Port; -use WpOrg\Requests\Requests; -use WpOrg\Requests\Ssl; -use WpOrg\Requests\Transport; -use WpOrg\Requests\Utility\CaseInsensitiveDictionary; -use WpOrg\Requests\Utility\InputValidator; - /** * fsockopen HTTP transport * - * @package Requests\Transport + * @package Requests + * @subpackage Transport */ -final class Fsockopen implements Transport { +class Requests_Transport_fsockopen implements Requests_Transport { /** * Second to microsecond conversion * @@ -40,7 +30,7 @@ final class Fsockopen implements Transport { /** * Stream metadata * - * @var array Associative array of properties, see {@link https://www.php.net/stream_get_meta_data} + * @var array Associative array of properties, see {@see https://secure.php.net/stream_get_meta_data} */ public $info; @@ -49,69 +39,45 @@ final class Fsockopen implements Transport { * * @var int|bool Byte count, or false if no limit. */ - private $max_bytes = false; + protected $max_bytes = false; - private $connect_error = ''; + protected $connect_error = ''; /** * Perform a request * - * @param string|Stringable $url URL to request + * @throws Requests_Exception On failure to connect to socket (`fsockopenerror`) + * @throws Requests_Exception On socket timeout (`timeout`) + * + * @param string $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD - * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation + * @param array $options Request options, see {@see Requests::response()} for documentation * @return string Raw HTTP result - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string or Stringable. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $headers argument is not an array. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data parameter is not an array or string. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. - * @throws \WpOrg\Requests\Exception On failure to connect to socket (`fsockopenerror`) - * @throws \WpOrg\Requests\Exception On socket timeout (`timeout`) */ - public function request($url, $headers = [], $data = [], $options = []) { - if (InputValidator::is_string_or_stringable($url) === false) { - throw InvalidArgument::create(1, '$url', 'string|Stringable', gettype($url)); - } - - if (is_array($headers) === false) { - throw InvalidArgument::create(2, '$headers', 'array', gettype($headers)); - } - - if (!is_array($data) && !is_string($data)) { - if ($data === null) { - $data = ''; - } else { - throw InvalidArgument::create(3, '$data', 'array|string', gettype($data)); - } - } - - if (is_array($options) === false) { - throw InvalidArgument::create(4, '$options', 'array', gettype($options)); - } - + public function request($url, $headers = array(), $data = array(), $options = array()) { $options['hooks']->dispatch('fsockopen.before_request'); $url_parts = parse_url($url); if (empty($url_parts)) { - throw new Exception('Invalid URL.', 'invalidurl', $url); + throw new Requests_Exception('Invalid URL.', 'invalidurl', $url); } $host = $url_parts['host']; $context = stream_context_create(); $verifyname = false; - $case_insensitive_headers = new CaseInsensitiveDictionary($headers); + $case_insensitive_headers = new Requests_Utility_CaseInsensitiveDictionary($headers); // HTTPS support if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') { $remote_socket = 'ssl://' . $host; if (!isset($url_parts['port'])) { - $url_parts['port'] = Port::HTTPS; + $url_parts['port'] = 443; } - $context_options = [ + $context_options = array( 'verify_peer' => true, 'capture_peer_cert' => true, - ]; + ); $verifyname = true; // SNI, if enabled (OpenSSL >=0.9.8j) @@ -139,7 +105,7 @@ final class Fsockopen implements Transport { $verifyname = false; } - stream_context_set_option($context, ['ssl' => $context_options]); + stream_context_set_option($context, array('ssl' => $context_options)); } else { $remote_socket = 'tcp://' . $host; @@ -148,30 +114,30 @@ final class Fsockopen implements Transport { $this->max_bytes = $options['max_bytes']; if (!isset($url_parts['port'])) { - $url_parts['port'] = Port::HTTP; + $url_parts['port'] = 80; } $remote_socket .= ':' . $url_parts['port']; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler - set_error_handler([$this, 'connect_error_handler'], E_WARNING | E_NOTICE); + set_error_handler(array($this, 'connect_error_handler'), E_WARNING | E_NOTICE); - $options['hooks']->dispatch('fsockopen.remote_socket', [&$remote_socket]); + $options['hooks']->dispatch('fsockopen.remote_socket', array(&$remote_socket)); $socket = stream_socket_client($remote_socket, $errno, $errstr, ceil($options['connect_timeout']), STREAM_CLIENT_CONNECT, $context); restore_error_handler(); if ($verifyname && !$this->verify_certificate_from_context($host, $context)) { - throw new Exception('SSL certificate did not match the requested domain name', 'ssl.no_match'); + throw new Requests_Exception('SSL certificate did not match the requested domain name', 'ssl.no_match'); } if (!$socket) { if ($errno === 0) { // Connection issue - throw new Exception(rtrim($this->connect_error), 'fsockopen.connect_error'); + throw new Requests_Exception(rtrim($this->connect_error), 'fsockopen.connect_error'); } - throw new Exception($errstr, 'fsockopenerror', null, $errno); + throw new Requests_Exception($errstr, 'fsockopenerror', null, $errno); } $data_format = $options['data_format']; @@ -181,10 +147,10 @@ final class Fsockopen implements Transport { $data = ''; } else { - $path = self::format_get($url_parts, []); + $path = self::format_get($url_parts, array()); } - $options['hooks']->dispatch('fsockopen.remote_host_path', [&$path, $url]); + $options['hooks']->dispatch('fsockopen.remote_host_path', array(&$path, $url)); $request_body = ''; $out = sprintf("%s %s HTTP/%.1F\r\n", $options['type'], $path, $options['protocol_version']); @@ -211,10 +177,9 @@ final class Fsockopen implements Transport { } if (!isset($case_insensitive_headers['Host'])) { - $out .= sprintf('Host: %s', $url_parts['host']); - $scheme_lower = strtolower($url_parts['scheme']); + $out .= sprintf('Host: %s', $url_parts['host']); - if (($scheme_lower === 'http' && $url_parts['port'] !== Port::HTTP) || ($scheme_lower === 'https' && $url_parts['port'] !== Port::HTTPS)) { + if ((strtolower($url_parts['scheme']) === 'http' && $url_parts['port'] !== 80) || (strtolower($url_parts['scheme']) === 'https' && $url_parts['port'] !== 443)) { $out .= ':' . $url_parts['port']; } $out .= "\r\n"; @@ -235,7 +200,7 @@ final class Fsockopen implements Transport { $out .= implode("\r\n", $headers) . "\r\n"; } - $options['hooks']->dispatch('fsockopen.after_headers', [&$out]); + $options['hooks']->dispatch('fsockopen.after_headers', array(&$out)); if (substr($out, -2) !== "\r\n") { $out .= "\r\n"; @@ -247,15 +212,15 @@ final class Fsockopen implements Transport { $out .= "\r\n" . $request_body; - $options['hooks']->dispatch('fsockopen.before_send', [&$out]); + $options['hooks']->dispatch('fsockopen.before_send', array(&$out)); fwrite($socket, $out); - $options['hooks']->dispatch('fsockopen.after_send', [$out]); + $options['hooks']->dispatch('fsockopen.after_send', array($out)); if (!$options['blocking']) { fclose($socket); $fake_headers = ''; - $options['hooks']->dispatch('fsockopen.after_request', [&$fake_headers]); + $options['hooks']->dispatch('fsockopen.after_request', array(&$fake_headers)); return ''; } @@ -276,18 +241,13 @@ final class Fsockopen implements Transport { $doingbody = false; $download = false; if ($options['filename']) { - // phpcs:ignore WordPress.PHP.NoSilencedErrors -- Silenced the PHP native warning in favour of throwing an exception. - $download = @fopen($options['filename'], 'wb'); - if ($download === false) { - $error = error_get_last(); - throw new Exception($error['message'], 'fopen'); - } + $download = fopen($options['filename'], 'wb'); } while (!feof($socket)) { $this->info = stream_get_meta_data($socket); if ($this->info['timed_out']) { - throw new Exception('fsocket timed out', 'timeout'); + throw new Requests_Exception('fsocket timed out', 'timeout'); } $block = fread($socket, Requests::BUFFER_SIZE); @@ -301,7 +261,7 @@ final class Fsockopen implements Transport { // Are we in body mode now? if ($doingbody) { - $options['hooks']->dispatch('request.progress', [$block, $size, $this->max_bytes]); + $options['hooks']->dispatch('request.progress', array($block, $size, $this->max_bytes)); $data_length = strlen($block); if ($this->max_bytes) { // Have we already hit a limit? @@ -334,49 +294,33 @@ final class Fsockopen implements Transport { } fclose($socket); - $options['hooks']->dispatch('fsockopen.after_request', [&$this->headers, &$this->info]); + $options['hooks']->dispatch('fsockopen.after_request', array(&$this->headers, &$this->info)); return $this->headers; } /** * Send multiple requests simultaneously * - * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see \WpOrg\Requests\Transport::request()} - * @param array $options Global options, see {@see \WpOrg\Requests\Requests::response()} for documentation - * @return array Array of \WpOrg\Requests\Response objects (may contain \WpOrg\Requests\Exception or string responses as well) - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. + * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see Requests_Transport::request} + * @param array $options Global options, see {@see Requests::response()} for documentation + * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well) */ public function request_multiple($requests, $options) { - // If you're not requesting, we can't get any responses ¯\_(ツ)_/¯ - if (empty($requests)) { - return []; - } - - if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { - throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); - } - - if (is_array($options) === false) { - throw InvalidArgument::create(2, '$options', 'array', gettype($options)); - } - - $responses = []; + $responses = array(); $class = get_class($this); foreach ($requests as $id => $request) { try { $handler = new $class(); $responses[$id] = $handler->request($request['url'], $request['headers'], $request['data'], $request['options']); - $request['options']['hooks']->dispatch('transport.internal.parse_response', [&$responses[$id], $request]); + $request['options']['hooks']->dispatch('transport.internal.parse_response', array(&$responses[$id], $request)); } - catch (Exception $e) { + catch (Requests_Exception $e) { $responses[$id] = $e; } if (!is_string($responses[$id])) { - $request['options']['hooks']->dispatch('multiple.request.complete', [&$responses[$id], $id]); + $request['options']['hooks']->dispatch('multiple.request.complete', array(&$responses[$id], $id)); } } @@ -388,8 +332,8 @@ final class Fsockopen implements Transport { * * @return string Accept-Encoding header value */ - private static function accept_encoding() { - $type = []; + protected static function accept_encoding() { + $type = array(); if (function_exists('gzinflate')) { $type[] = 'deflate;q=1.0'; } @@ -407,10 +351,10 @@ final class Fsockopen implements Transport { * Format a URL given GET data * * @param array $url_parts - * @param array|object $data Data to build query using, see {@link https://www.php.net/http_build_query} + * @param array|object $data Data to build query using, see {@see https://secure.php.net/http_build_query} * @return string URL with data */ - private static function format_get($url_parts, $data) { + protected static function format_get($url_parts, $data) { if (!empty($data)) { if (empty($url_parts['query'])) { $url_parts['query'] = ''; @@ -457,14 +401,13 @@ final class Fsockopen implements Transport { * names, leading things like 'https://www.github.com/' to be invalid. * Instead * - * @link https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1 + * @see https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1 * + * @throws Requests_Exception On failure to connect via TLS (`fsockopen.ssl.connect_error`) + * @throws Requests_Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`) * @param string $host Host name to verify against * @param resource $context Stream context * @return bool - * - * @throws \WpOrg\Requests\Exception On failure to connect via TLS (`fsockopen.ssl.connect_error`) - * @throws \WpOrg\Requests\Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`) */ public function verify_certificate_from_context($host, $context) { $meta = stream_context_get_options($context); @@ -472,33 +415,35 @@ final class Fsockopen implements Transport { // If we don't have SSL options, then we couldn't make the connection at // all if (empty($meta) || empty($meta['ssl']) || empty($meta['ssl']['peer_certificate'])) { - throw new Exception(rtrim($this->connect_error), 'ssl.connect_error'); + throw new Requests_Exception(rtrim($this->connect_error), 'ssl.connect_error'); } $cert = openssl_x509_parse($meta['ssl']['peer_certificate']); - return Ssl::verify_certificate($host, $cert); + return Requests_SSL::verify_certificate($host, $cert); } /** - * Self-test whether the transport can be used. - * - * The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}. + * Whether this transport is valid * * @codeCoverageIgnore - * @param array $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. - * @return bool Whether the transport can be used. + * @return boolean True if the transport is valid, false otherwise. */ - public static function test($capabilities = []) { + public static function test($capabilities = array()) { if (!function_exists('fsockopen')) { return false; } // If needed, check that streams support SSL - if (isset($capabilities[Capability::SSL]) && $capabilities[Capability::SSL]) { + if (isset($capabilities['ssl']) && $capabilities['ssl']) { if (!extension_loaded('openssl') || !function_exists('openssl_x509_parse')) { return false; } + + // Currently broken, thanks to https://github.com/facebook/hhvm/issues/2156 + if (defined('HHVM_VERSION')) { + return false; + } } return true; diff --git a/wp-includes/Requests/Utility/CaseInsensitiveDictionary.php b/wp-includes/Requests/Utility/CaseInsensitiveDictionary.php index 3c24cebd4f..7eebeb7a72 100644 --- a/wp-includes/Requests/Utility/CaseInsensitiveDictionary.php +++ b/wp-includes/Requests/Utility/CaseInsensitiveDictionary.php @@ -2,116 +2,92 @@ /** * Case-insensitive dictionary, suitable for HTTP headers * - * @package Requests\Utilities + * @package Requests + * @subpackage Utilities */ -namespace WpOrg\Requests\Utility; - -use ArrayAccess; -use ArrayIterator; -use IteratorAggregate; -use ReturnTypeWillChange; -use WpOrg\Requests\Exception; - /** * Case-insensitive dictionary, suitable for HTTP headers * - * @package Requests\Utilities + * @package Requests + * @subpackage Utilities */ -class CaseInsensitiveDictionary implements ArrayAccess, IteratorAggregate { +class Requests_Utility_CaseInsensitiveDictionary implements ArrayAccess, IteratorAggregate { /** * Actual item data * * @var array */ - protected $data = []; + protected $data = array(); /** * Creates a case insensitive dictionary. * * @param array $data Dictionary/map to convert to case-insensitive */ - public function __construct(array $data = []) { - foreach ($data as $offset => $value) { - $this->offsetSet($offset, $value); + public function __construct(array $data = array()) { + foreach ($data as $key => $value) { + $this->offsetSet($key, $value); } } /** * Check if the given item exists * - * @param string $offset Item key + * @param string $key Item key * @return boolean Does the item exist? */ - #[ReturnTypeWillChange] - public function offsetExists($offset) { - if (is_string($offset)) { - $offset = strtolower($offset); - } - - return isset($this->data[$offset]); + public function offsetExists($key) { + $key = strtolower($key); + return isset($this->data[$key]); } /** * Get the value for the item * - * @param string $offset Item key - * @return string|null Item value (null if the item key doesn't exist) + * @param string $key Item key + * @return string|null Item value (null if offsetExists is false) */ - #[ReturnTypeWillChange] - public function offsetGet($offset) { - if (is_string($offset)) { - $offset = strtolower($offset); - } - - if (!isset($this->data[$offset])) { + public function offsetGet($key) { + $key = strtolower($key); + if (!isset($this->data[$key])) { return null; } - return $this->data[$offset]; + return $this->data[$key]; } /** * Set the given item * - * @param string $offset Item name - * @param string $value Item value + * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`) * - * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`) + * @param string $key Item name + * @param string $value Item value */ - #[ReturnTypeWillChange] - public function offsetSet($offset, $value) { - if ($offset === null) { - throw new Exception('Object is a dictionary, not a list', 'invalidset'); + public function offsetSet($key, $value) { + if ($key === null) { + throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset'); } - if (is_string($offset)) { - $offset = strtolower($offset); - } - - $this->data[$offset] = $value; + $key = strtolower($key); + $this->data[$key] = $value; } /** * Unset the given header * - * @param string $offset + * @param string $key */ - #[ReturnTypeWillChange] - public function offsetUnset($offset) { - if (is_string($offset)) { - $offset = strtolower($offset); - } - - unset($this->data[$offset]); + public function offsetUnset($key) { + unset($this->data[strtolower($key)]); } /** * Get an iterator for the data * - * @return \ArrayIterator + * @return ArrayIterator */ - #[ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->data); } diff --git a/wp-includes/Requests/Utility/FilteredIterator.php b/wp-includes/Requests/Utility/FilteredIterator.php index 973a5d25a5..7c6c2c0238 100644 --- a/wp-includes/Requests/Utility/FilteredIterator.php +++ b/wp-includes/Requests/Utility/FilteredIterator.php @@ -2,60 +2,34 @@ /** * Iterator for arrays requiring filtered values * - * @package Requests\Utilities + * @package Requests + * @subpackage Utilities */ -namespace WpOrg\Requests\Utility; - -use ArrayIterator; -use ReturnTypeWillChange; -use WpOrg\Requests\Exception\InvalidArgument; -use WpOrg\Requests\Utility\InputValidator; - /** * Iterator for arrays requiring filtered values * - * @package Requests\Utilities + * @package Requests + * @subpackage Utilities */ -final class FilteredIterator extends ArrayIterator { +class Requests_Utility_FilteredIterator extends ArrayIterator { /** * Callback to run as a filter * * @var callable */ - private $callback; + protected $callback; /** * Create a new iterator * * @param array $data * @param callable $callback Callback to be called on each value - * - * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data argument is not iterable. */ public function __construct($data, $callback) { - if (InputValidator::is_iterable($data) === false) { - throw InvalidArgument::create(1, '$data', 'iterable', gettype($data)); - } - parent::__construct($data); - if (is_callable($callback)) { - $this->callback = $callback; - } - } - - /** - * @inheritdoc - * - * @phpcs:disable PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound - */ - #[ReturnTypeWillChange] - public function __unserialize($data) {} - // phpcs:enable - - public function __wakeup() { - unset($this->callback); + $this->callback = $callback; } /** @@ -63,7 +37,6 @@ final class FilteredIterator extends ArrayIterator { * * @return string */ - #[ReturnTypeWillChange] public function current() { $value = parent::current(); @@ -77,6 +50,16 @@ final class FilteredIterator extends ArrayIterator { /** * @inheritdoc */ - #[ReturnTypeWillChange] - public function unserialize($data) {} + public function unserialize($serialized) {} + + /** + * @inheritdoc + * + * @phpcs:disable PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.MethodDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound + */ + public function __unserialize($serialized) {} + + public function __wakeup() { + unset($this->callback); + } } diff --git a/wp-includes/Requests/Utility/InputValidator.php b/wp-includes/Requests/Utility/InputValidator.php deleted file mode 100644 index 7c10d61a4b..0000000000 --- a/wp-includes/Requests/Utility/InputValidator.php +++ /dev/null @@ -1,109 +0,0 @@ -dispatch('requests.before_request', array(&$url, &$headers, &$data, &$type, &$options)); + + if (!empty($options['transport'])) { + $transport = $options['transport']; + + if (is_string($options['transport'])) { + $transport = new $transport(); + } + } + else { + $need_ssl = (stripos($url, 'https://') === 0); + $capabilities = array('ssl' => $need_ssl); + $transport = self::get_transport($capabilities); + } + $response = $transport->request($url, $headers, $data, $options); + + $options['hooks']->dispatch('requests.before_parse', array(&$response, $url, $headers, $data, $type, $options)); + + return self::parse_response($response, $url, $headers, $data, $options); + } + + /** + * Send multiple HTTP requests simultaneously + * + * The `$requests` parameter takes an associative or indexed array of + * request fields. The key of each request can be used to match up the + * request with the returned data, or with the request passed into your + * `multiple.request.complete` callback. + * + * The request fields value is an associative array with the following keys: + * + * - `url`: Request URL Same as the `$url` parameter to + * {@see Requests::request} + * (string, required) + * - `headers`: Associative array of header fields. Same as the `$headers` + * parameter to {@see Requests::request} + * (array, default: `array()`) + * - `data`: Associative array of data fields or a string. Same as the + * `$data` parameter to {@see Requests::request} + * (array|string, default: `array()`) + * - `type`: HTTP request type (use Requests constants). Same as the `$type` + * parameter to {@see Requests::request} + * (string, default: `Requests::GET`) + * - `cookies`: Associative array of cookie name to value, or cookie jar. + * (array|Requests_Cookie_Jar) + * + * If the `$options` parameter is specified, individual requests will + * inherit options from it. This can be used to use a single hooking system, + * or set all the types to `Requests::POST`, for example. + * + * In addition, the `$options` parameter takes the following global options: + * + * - `complete`: A callback for when a request is complete. Takes two + * parameters, a Requests_Response/Requests_Exception reference, and the + * ID from the request array (Note: this can also be overridden on a + * per-request basis, although that's a little silly) + * (callback) + * + * @param array $requests Requests data (see description for more information) + * @param array $options Global and default options (see {@see Requests::request}) + * @return array Responses (either Requests_Response or a Requests_Exception object) + */ + public static function request_multiple($requests, $options = array()) { + $options = array_merge(self::get_default_options(true), $options); + + if (!empty($options['hooks'])) { + $options['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple')); + if (!empty($options['complete'])) { + $options['hooks']->register('multiple.request.complete', $options['complete']); + } + } + + foreach ($requests as $id => &$request) { + if (!isset($request['headers'])) { + $request['headers'] = array(); + } + if (!isset($request['data'])) { + $request['data'] = array(); + } + if (!isset($request['type'])) { + $request['type'] = self::GET; + } + if (!isset($request['options'])) { + $request['options'] = $options; + $request['options']['type'] = $request['type']; + } + else { + if (empty($request['options']['type'])) { + $request['options']['type'] = $request['type']; + } + $request['options'] = array_merge($options, $request['options']); + } + + self::set_defaults($request['url'], $request['headers'], $request['data'], $request['type'], $request['options']); + + // Ensure we only hook in once + if ($request['options']['hooks'] !== $options['hooks']) { + $request['options']['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple')); + if (!empty($request['options']['complete'])) { + $request['options']['hooks']->register('multiple.request.complete', $request['options']['complete']); + } + } + } + unset($request); + + if (!empty($options['transport'])) { + $transport = $options['transport']; + + if (is_string($options['transport'])) { + $transport = new $transport(); + } + } + else { + $transport = self::get_transport(); + } + $responses = $transport->request_multiple($requests, $options); + + foreach ($responses as $id => &$response) { + // If our hook got messed with somehow, ensure we end up with the + // correct response + if (is_string($response)) { + $request = $requests[$id]; + self::parse_multiple($response, $request); + $request['options']['hooks']->dispatch('multiple.request.complete', array(&$response, $id)); + } + } + + return $responses; + } + + /** + * Get the default options + * + * @see Requests::request() for values returned by this method + * @param boolean $multirequest Is this a multirequest? + * @return array Default option values + */ + protected static function get_default_options($multirequest = false) { + $defaults = array( + 'timeout' => 10, + 'connect_timeout' => 10, + 'useragent' => 'php-requests/' . self::VERSION, + 'protocol_version' => 1.1, + 'redirected' => 0, + 'redirects' => 10, + 'follow_redirects' => true, + 'blocking' => true, + 'type' => self::GET, + 'filename' => false, + 'auth' => false, + 'proxy' => false, + 'cookies' => false, + 'max_bytes' => false, + 'idn' => true, + 'hooks' => null, + 'transport' => null, + 'verify' => self::get_certificate_path(), + 'verifyname' => true, + ); + if ($multirequest !== false) { + $defaults['complete'] = null; + } + return $defaults; + } + + /** + * Get default certificate path. + * + * @return string Default certificate path. + */ + public static function get_certificate_path() { + if (!empty(self::$certificate_path)) { + return self::$certificate_path; + } + + return dirname(__FILE__) . '/Requests/Transport/cacert.pem'; + } + + /** + * Set default certificate path. + * + * @param string $path Certificate path, pointing to a PEM file. + */ + public static function set_certificate_path($path) { + self::$certificate_path = $path; + } + + /** + * Set the default values + * + * @param string $url URL to request + * @param array $headers Extra headers to send with the request + * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests + * @param string $type HTTP request type + * @param array $options Options for the request + * @return array $options + */ + protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) { + if (!preg_match('/^http(s)?:\/\//i', $url, $matches)) { + throw new Requests_Exception('Only HTTP(S) requests are handled.', 'nonhttp', $url); + } + + if (empty($options['hooks'])) { + $options['hooks'] = new Requests_Hooks(); + } + + if (is_array($options['auth'])) { + $options['auth'] = new Requests_Auth_Basic($options['auth']); + } + if ($options['auth'] !== false) { + $options['auth']->register($options['hooks']); + } + + if (is_string($options['proxy']) || is_array($options['proxy'])) { + $options['proxy'] = new Requests_Proxy_HTTP($options['proxy']); + } + if ($options['proxy'] !== false) { + $options['proxy']->register($options['hooks']); + } + + if (is_array($options['cookies'])) { + $options['cookies'] = new Requests_Cookie_Jar($options['cookies']); + } + elseif (empty($options['cookies'])) { + $options['cookies'] = new Requests_Cookie_Jar(); + } + if ($options['cookies'] !== false) { + $options['cookies']->register($options['hooks']); + } + + if ($options['idn'] !== false) { + $iri = new Requests_IRI($url); + $iri->host = Requests_IDNAEncoder::encode($iri->ihost); + $url = $iri->uri; + } + + // Massage the type to ensure we support it. + $type = strtoupper($type); + + if (!isset($options['data_format'])) { + if (in_array($type, array(self::HEAD, self::GET, self::DELETE), true)) { + $options['data_format'] = 'query'; + } + else { + $options['data_format'] = 'body'; + } + } + } + + /** + * HTTP response parser + * + * @throws Requests_Exception On missing head/body separator (`requests.no_crlf_separator`) + * @throws Requests_Exception On missing head/body separator (`noversion`) + * @throws Requests_Exception On missing head/body separator (`toomanyredirects`) + * + * @param string $headers Full response text including headers and body + * @param string $url Original request URL + * @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects + * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects + * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects + * @return Requests_Response + */ + protected static function parse_response($headers, $url, $req_headers, $req_data, $options) { + $return = new Requests_Response(); + if (!$options['blocking']) { + return $return; + } + + $return->raw = $headers; + $return->url = (string) $url; + $return->body = ''; + + if (!$options['filename']) { + $pos = strpos($headers, "\r\n\r\n"); + if ($pos === false) { + // Crap! + throw new Requests_Exception('Missing header/body separator', 'requests.no_crlf_separator'); + } + + $headers = substr($return->raw, 0, $pos); + // Headers will always be separated from the body by two new lines - `\n\r\n\r`. + $body = substr($return->raw, $pos + 4); + if (!empty($body)) { + $return->body = $body; + } + } + // Pretend CRLF = LF for compatibility (RFC 2616, section 19.3) + $headers = str_replace("\r\n", "\n", $headers); + // Unfold headers (replace [CRLF] 1*( SP | HT ) with SP) as per RFC 2616 (section 2.2) + $headers = preg_replace('/\n[ \t]/', ' ', $headers); + $headers = explode("\n", $headers); + preg_match('#^HTTP/(1\.\d)[ \t]+(\d+)#i', array_shift($headers), $matches); + if (empty($matches)) { + throw new Requests_Exception('Response could not be parsed', 'noversion', $headers); + } + $return->protocol_version = (float) $matches[1]; + $return->status_code = (int) $matches[2]; + if ($return->status_code >= 200 && $return->status_code < 300) { + $return->success = true; + } + + foreach ($headers as $header) { + list($key, $value) = explode(':', $header, 2); + $value = trim($value); + preg_replace('#(\s+)#i', ' ', $value); + $return->headers[$key] = $value; + } + if (isset($return->headers['transfer-encoding'])) { + $return->body = self::decode_chunked($return->body); + unset($return->headers['transfer-encoding']); + } + if (isset($return->headers['content-encoding'])) { + $return->body = self::decompress($return->body); + } + + //fsockopen and cURL compatibility + if (isset($return->headers['connection'])) { + unset($return->headers['connection']); + } + + $options['hooks']->dispatch('requests.before_redirect_check', array(&$return, $req_headers, $req_data, $options)); + + if ($return->is_redirect() && $options['follow_redirects'] === true) { + if (isset($return->headers['location']) && $options['redirected'] < $options['redirects']) { + if ($return->status_code === 303) { + $options['type'] = self::GET; + } + $options['redirected']++; + $location = $return->headers['location']; + if (strpos($location, 'http://') !== 0 && strpos($location, 'https://') !== 0) { + // relative redirect, for compatibility make it absolute + $location = Requests_IRI::absolutize($url, $location); + $location = $location->uri; + } + + $hook_args = array( + &$location, + &$req_headers, + &$req_data, + &$options, + $return, + ); + $options['hooks']->dispatch('requests.before_redirect', $hook_args); + $redirected = self::request($location, $req_headers, $req_data, $options['type'], $options); + $redirected->history[] = $return; + return $redirected; + } + elseif ($options['redirected'] >= $options['redirects']) { + throw new Requests_Exception('Too many redirects', 'toomanyredirects', $return); + } + } + + $return->redirects = $options['redirected']; + + $options['hooks']->dispatch('requests.after_request', array(&$return, $req_headers, $req_data, $options)); + return $return; + } + + /** + * Callback for `transport.internal.parse_response` + * + * Internal use only. Converts a raw HTTP response to a Requests_Response + * while still executing a multiple request. + * + * @param string $response Full response text including headers and body (will be overwritten with Response instance) + * @param array $request Request data as passed into {@see Requests::request_multiple()} + * @return null `$response` is either set to a Requests_Response instance, or a Requests_Exception object + */ + public static function parse_multiple(&$response, $request) { + try { + $url = $request['url']; + $headers = $request['headers']; + $data = $request['data']; + $options = $request['options']; + $response = self::parse_response($response, $url, $headers, $data, $options); + } + catch (Requests_Exception $e) { + $response = $e; + } + } + + /** + * Decoded a chunked body as per RFC 2616 + * + * @see https://tools.ietf.org/html/rfc2616#section-3.6.1 + * @param string $data Chunked body + * @return string Decoded body + */ + protected static function decode_chunked($data) { + if (!preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', trim($data))) { + return $data; + } + + $decoded = ''; + $encoded = $data; + + while (true) { + $is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', $encoded, $matches); + if (!$is_chunked) { + // Looks like it's not chunked after all + return $data; + } + + $length = hexdec(trim($matches[1])); + if ($length === 0) { + // Ignore trailer headers + return $decoded; + } + + $chunk_length = strlen($matches[0]); + $decoded .= substr($encoded, $chunk_length, $length); + $encoded = substr($encoded, $chunk_length + $length + 2); + + if (trim($encoded) === '0' || empty($encoded)) { + return $decoded; + } + } + + // We'll never actually get down here + // @codeCoverageIgnoreStart + } + // @codeCoverageIgnoreEnd + + /** + * Convert a key => value array to a 'key: value' array for headers + * + * @param array $array Dictionary of header values + * @return array List of headers + */ + public static function flatten($array) { + $return = array(); + foreach ($array as $key => $value) { + $return[] = sprintf('%s: %s', $key, $value); + } + return $return; + } + + /** + * Convert a key => value array to a 'key: value' array for headers + * + * @codeCoverageIgnore + * @deprecated Misspelling of {@see Requests::flatten} + * @param array $array Dictionary of header values + * @return array List of headers + */ + public static function flattern($array) { + return self::flatten($array); + } + + /** + * Decompress an encoded body + * + * Implements gzip, compress and deflate. Guesses which it is by attempting + * to decode. + * + * @param string $data Compressed data in one of the above formats + * @return string Decompressed string + */ + public static function decompress($data) { + if (substr($data, 0, 2) !== "\x1f\x8b" && substr($data, 0, 2) !== "\x78\x9c") { + // Not actually compressed. Probably cURL ruining this for us. + return $data; + } + + if (function_exists('gzdecode')) { + // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.gzdecodeFound -- Wrapped in function_exists() for PHP 5.2. + $decoded = @gzdecode($data); + if ($decoded !== false) { + return $decoded; + } + } + + if (function_exists('gzinflate')) { + $decoded = @gzinflate($data); + if ($decoded !== false) { + return $decoded; + } + } + + $decoded = self::compatible_gzinflate($data); + if ($decoded !== false) { + return $decoded; + } + + if (function_exists('gzuncompress')) { + $decoded = @gzuncompress($data); + if ($decoded !== false) { + return $decoded; + } + } + + return $data; + } + + /** + * Decompression of deflated string while staying compatible with the majority of servers. + * + * Certain Servers will return deflated data with headers which PHP's gzinflate() + * function cannot handle out of the box. The following function has been created from + * various snippets on the gzinflate() PHP documentation. + * + * Warning: Magic numbers within. Due to the potential different formats that the compressed + * data may be returned in, some "magic offsets" are needed to ensure proper decompression + * takes place. For a simple progmatic way to determine the magic offset in use, see: + * https://core.trac.wordpress.org/ticket/18273 + * + * @since 2.8.1 + * @link https://core.trac.wordpress.org/ticket/18273 + * @link https://secure.php.net/manual/en/function.gzinflate.php#70875 + * @link https://secure.php.net/manual/en/function.gzinflate.php#77336 + * + * @param string $gz_data String to decompress. + * @return string|bool False on failure. + */ + public static function compatible_gzinflate($gz_data) { + // Compressed data might contain a full zlib header, if so strip it for + // gzinflate() + if (substr($gz_data, 0, 3) === "\x1f\x8b\x08") { + $i = 10; + $flg = ord(substr($gz_data, 3, 1)); + if ($flg > 0) { + if ($flg & 4) { + list($xlen) = unpack('v', substr($gz_data, $i, 2)); + $i += 2 + $xlen; + } + if ($flg & 8) { + $i = strpos($gz_data, "\0", $i) + 1; + } + if ($flg & 16) { + $i = strpos($gz_data, "\0", $i) + 1; + } + if ($flg & 2) { + $i += 2; + } + } + $decompressed = self::compatible_gzinflate(substr($gz_data, $i)); + if ($decompressed !== false) { + return $decompressed; + } + } + + // If the data is Huffman Encoded, we must first strip the leading 2 + // byte Huffman marker for gzinflate() + // The response is Huffman coded by many compressors such as + // java.util.zip.Deflater, Ruby’s Zlib::Deflate, and .NET's + // System.IO.Compression.DeflateStream. + // + // See https://decompres.blogspot.com/ for a quick explanation of this + // data type + $huffman_encoded = false; + + // low nibble of first byte should be 0x08 + list(, $first_nibble) = unpack('h', $gz_data); + + // First 2 bytes should be divisible by 0x1F + list(, $first_two_bytes) = unpack('n', $gz_data); + + if ($first_nibble === 0x08 && ($first_two_bytes % 0x1F) === 0) { + $huffman_encoded = true; + } + + if ($huffman_encoded) { + $decompressed = @gzinflate(substr($gz_data, 2)); + if ($decompressed !== false) { + return $decompressed; + } + } + + if (substr($gz_data, 0, 4) === "\x50\x4b\x03\x04") { + // ZIP file format header + // Offset 6: 2 bytes, General-purpose field + // Offset 26: 2 bytes, filename length + // Offset 28: 2 bytes, optional field length + // Offset 30: Filename field, followed by optional field, followed + // immediately by data + list(, $general_purpose_flag) = unpack('v', substr($gz_data, 6, 2)); + + // If the file has been compressed on the fly, 0x08 bit is set of + // the general purpose field. We can use this to differentiate + // between a compressed document, and a ZIP file + $zip_compressed_on_the_fly = ((0x08 & $general_purpose_flag) === 0x08); + + if (!$zip_compressed_on_the_fly) { + // Don't attempt to decode a compressed zip file + return $gz_data; + } + + // Determine the first byte of data, based on the above ZIP header + // offsets: + $first_file_start = array_sum(unpack('v2', substr($gz_data, 26, 4))); + $decompressed = @gzinflate(substr($gz_data, 30 + $first_file_start)); + if ($decompressed !== false) { + return $decompressed; + } + return false; + } + + // Finally fall back to straight gzinflate + $decompressed = @gzinflate($gz_data); + if ($decompressed !== false) { + return $decompressed; + } + + // Fallback for all above failing, not expected, but included for + // debugging and preventing regressions and to track stats + $decompressed = @gzinflate(substr($gz_data, 2)); + if ($decompressed !== false) { + return $decompressed; + } + + return false; + } + + public static function match_domain($host, $reference) { + // Check for a direct match + if ($host === $reference) { + return true; + } + + // Calculate the valid wildcard match if the host is not an IP address + // Also validates that the host has 3 parts or more, as per Firefox's + // ruleset. + $parts = explode('.', $host); + if (ip2long($host) === false && count($parts) >= 3) { + $parts[0] = '*'; + $wildcard = implode('.', $parts); + if ($wildcard === $reference) { + return true; + } + } + + return false; } } diff --git a/wp-includes/class-wp-http-requests-hooks.php b/wp-includes/class-wp-http-requests-hooks.php index 811599d5ca..c54fdc0b8f 100644 --- a/wp-includes/class-wp-http-requests-hooks.php +++ b/wp-includes/class-wp-http-requests-hooks.php @@ -12,9 +12,9 @@ * * @since 4.7.0 * - * @see WpOrg\Requests\Hooks + * @see Requests_Hooks */ -class WP_HTTP_Requests_Hooks extends WpOrg\Requests\Hooks { +class WP_HTTP_Requests_Hooks extends Requests_Hooks { /** * Requested URL. * diff --git a/wp-includes/class-wp-http-requests-response.php b/wp-includes/class-wp-http-requests-response.php index 821077656c..45f83e2c7a 100644 --- a/wp-includes/class-wp-http-requests-response.php +++ b/wp-includes/class-wp-http-requests-response.php @@ -8,7 +8,7 @@ */ /** - * Core wrapper object for a WpOrg\Requests\Response for standardisation. + * Core wrapper object for a Requests_Response for standardisation. * * @since 4.6.0 * @@ -19,7 +19,7 @@ class WP_HTTP_Requests_Response extends WP_HTTP_Response { * Requests Response object. * * @since 4.6.0 - * @var \WpOrg\Requests\Response + * @var Requests_Response */ protected $response; @@ -36,10 +36,10 @@ class WP_HTTP_Requests_Response extends WP_HTTP_Response { * * @since 4.6.0 * - * @param \WpOrg\Requests\Response $response HTTP response. - * @param string $filename Optional. File name. Default empty. + * @param Requests_Response $response HTTP response. + * @param string $filename Optional. File name. Default empty. */ - public function __construct( WpOrg\Requests\Response $response, $filename = '' ) { + public function __construct( Requests_Response $response, $filename = '' ) { $this->response = $response; $this->filename = $filename; } @@ -49,7 +49,7 @@ class WP_HTTP_Requests_Response extends WP_HTTP_Response { * * @since 4.6.0 * - * @return WpOrg\Requests\Response HTTP response. + * @return Requests_Response HTTP response. */ public function get_response_object() { return $this->response; @@ -60,11 +60,11 @@ class WP_HTTP_Requests_Response extends WP_HTTP_Response { * * @since 4.6.0 * - * @return \WpOrg\Requests\Utility\CaseInsensitiveDictionary Map of header name to header value. + * @return \Requests_Utility_CaseInsensitiveDictionary Map of header name to header value. */ public function get_headers() { // Ensure headers remain case-insensitive. - $converted = new WpOrg\Requests\Utility\CaseInsensitiveDictionary(); + $converted = new Requests_Utility_CaseInsensitiveDictionary(); foreach ( $this->response->headers->getAll() as $key => $value ) { if ( count( $value ) === 1 ) { @@ -85,7 +85,7 @@ class WP_HTTP_Requests_Response extends WP_HTTP_Response { * @param array $headers Map of header name to header value. */ public function set_headers( $headers ) { - $this->response->headers = new WpOrg\Requests\Response\Headers( $headers ); + $this->response->headers = new Requests_Response_Headers( $headers ); } /** diff --git a/wp-includes/class-wp-http.php b/wp-includes/class-wp-http.php index a4a501c90a..0cc9c8f78b 100644 --- a/wp-includes/class-wp-http.php +++ b/wp-includes/class-wp-http.php @@ -7,11 +7,11 @@ * @since 2.7.0 */ -if ( ! class_exists( 'WpOrg\Requests\Autoload' ) ) { - require ABSPATH . WPINC . '/Requests/Autoload.php'; +if ( ! class_exists( 'Requests' ) ) { + require ABSPATH . WPINC . '/class-requests.php'; - WpOrg\Requests\Autoload::register(); - WpOrg\Requests\Requests::set_certificate_path( ABSPATH . WPINC . '/certificates/ca-bundle.crt' ); + Requests::register_autoloader(); + Requests::set_certificate_path( ABSPATH . WPINC . '/certificates/ca-bundle.crt' ); } /** @@ -274,14 +274,14 @@ class WP_Http { if ( empty( $url ) || empty( $parsed_url['scheme'] ) ) { $response = new WP_Error( 'http_request_failed', __( 'A valid URL was not provided.' ) ); /** This action is documented in wp-includes/class-wp-http.php */ - do_action( 'http_api_debug', $response, 'response', 'WpOrg\Requests\Requests', $parsed_args, $url ); + do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url ); return $response; } if ( $this->block_request( $url ) ) { $response = new WP_Error( 'http_request_not_executed', __( 'User has blocked requests through HTTP.' ) ); /** This action is documented in wp-includes/class-wp-http.php */ - do_action( 'http_api_debug', $response, 'response', 'WpOrg\Requests\Requests', $parsed_args, $url ); + do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url ); return $response; } @@ -298,7 +298,7 @@ class WP_Http { if ( ! wp_is_writable( dirname( $parsed_args['filename'] ) ) ) { $response = new WP_Error( 'http_request_failed', __( 'Destination directory for file streaming does not exist or is not writable.' ) ); /** This action is documented in wp-includes/class-wp-http.php */ - do_action( 'http_api_debug', $response, 'response', 'WpOrg\Requests\Requests', $parsed_args, $url ); + do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url ); return $response; } } @@ -346,7 +346,7 @@ class WP_Http { $options['max_bytes'] = $parsed_args['limit_response_size']; } - // If we've got cookies, use and convert them to WpOrg\Requests\Cookie. + // If we've got cookies, use and convert them to Requests_Cookie. if ( ! empty( $parsed_args['cookies'] ) ) { $options['cookies'] = WP_Http::normalize_cookies( $parsed_args['cookies'] ); } @@ -378,7 +378,7 @@ class WP_Http { // Check for proxies. $proxy = new WP_HTTP_Proxy(); if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { - $options['proxy'] = new WpOrg\Requests\Proxy\HTTP( $proxy->host() . ':' . $proxy->port() ); + $options['proxy'] = new Requests_Proxy_HTTP( $proxy->host() . ':' . $proxy->port() ); if ( $proxy->use_authentication() ) { $options['proxy']->use_authentication = true; @@ -391,7 +391,7 @@ class WP_Http { mbstring_binary_safe_encoding(); try { - $requests_response = WpOrg\Requests\Requests::request( $url, $headers, $data, $type, $options ); + $requests_response = Requests::request( $url, $headers, $data, $type, $options ); // Convert the response into an array. $http_response = new WP_HTTP_Requests_Response( $requests_response, $parsed_args['filename'] ); @@ -399,7 +399,7 @@ class WP_Http { // Add the original object to the array. $response['http_response'] = $http_response; - } catch ( WpOrg\Requests\Exception $e ) { + } catch ( Requests_Exception $e ) { $response = new WP_Error( 'http_request_failed', $e->getMessage() ); } @@ -416,7 +416,7 @@ class WP_Http { * @param array $parsed_args HTTP request arguments. * @param string $url The request URL. */ - do_action( 'http_api_debug', $response, 'response', 'WpOrg\Requests\Requests', $parsed_args, $url ); + do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url ); if ( is_wp_error( $response ) ) { return $response; } @@ -452,10 +452,10 @@ class WP_Http { * @since 4.6.0 * * @param array $cookies Array of cookies to send with the request. - * @return WpOrg\Requests\Cookie\Jar Cookie holder object. + * @return Requests_Cookie_Jar Cookie holder object. */ public static function normalize_cookies( $cookies ) { - $cookie_jar = new WpOrg\Requests\Cookie\Jar(); + $cookie_jar = new Requests_Cookie_Jar(); foreach ( $cookies as $name => $value ) { if ( $value instanceof WP_Http_Cookie ) { @@ -465,9 +465,9 @@ class WP_Http { return null !== $attr; } ); - $cookie_jar[ $value->name ] = new WpOrg\Requests\Cookie( $value->name, $value->value, $attributes, array( 'host-only' => $value->host_only ) ); + $cookie_jar[ $value->name ] = new Requests_Cookie( $value->name, $value->value, $attributes, array( 'host-only' => $value->host_only ) ); } elseif ( is_scalar( $value ) ) { - $cookie_jar[ $name ] = new WpOrg\Requests\Cookie( $name, (string) $value ); + $cookie_jar[ $name ] = new Requests_Cookie( $name, $value ); } } @@ -483,16 +483,16 @@ class WP_Http { * * @since 4.6.0 * - * @param string $location URL to redirect to. - * @param array $headers Headers for the redirect. - * @param string|array $data Body to send with the request. - * @param array $options Redirect request options. - * @param WpOrg\Requests\Response $original Response object. + * @param string $location URL to redirect to. + * @param array $headers Headers for the redirect. + * @param string|array $data Body to send with the request. + * @param array $options Redirect request options. + * @param Requests_Response $original Response object. */ public static function browser_redirect_compatibility( $location, $headers, $data, &$options, $original ) { // Browser compatibility. if ( 302 === $original->status_code ) { - $options['type'] = WpOrg\Requests\Requests::GET; + $options['type'] = Requests::GET; } } @@ -501,12 +501,12 @@ class WP_Http { * * @since 4.7.5 * - * @throws WpOrg\Requests\Exception On unsuccessful URL validation. + * @throws Requests_Exception On unsuccessful URL validation. * @param string $location URL to redirect to. */ public static function validate_redirects( $location ) { if ( ! wp_http_validate_url( $location ) ) { - throw new WpOrg\Requests\Exception( __( 'A valid URL was not provided.' ), 'wp_http.redirect_failed_validation' ); + throw new Requests_Exception( __( 'A valid URL was not provided.' ), 'wp_http.redirect_failed_validation' ); } } diff --git a/wp-includes/http.php b/wp-includes/http.php index fc47ec73df..d76298368f 100644 --- a/wp-includes/http.php +++ b/wp-includes/http.php @@ -200,12 +200,12 @@ function wp_remote_head( $url, $args = array() ) { * Retrieve only the headers from the raw response. * * @since 2.7.0 - * @since 4.6.0 Return value changed from an array to an WpOrg\Requests\Utility\CaseInsensitiveDictionary instance. + * @since 4.6.0 Return value changed from an array to an Requests_Utility_CaseInsensitiveDictionary instance. * - * @see \WpOrg\Requests\Utility\CaseInsensitiveDictionary + * @see \Requests_Utility_CaseInsensitiveDictionary * * @param array|WP_Error $response HTTP response. - * @return array|\WpOrg\Requests\Utility\CaseInsensitiveDictionary The headers of the response. Empty array if incorrect parameter given. + * @return array|\Requests_Utility_CaseInsensitiveDictionary The headers of the response. Empty array if incorrect parameter given. */ function wp_remote_retrieve_headers( $response ) { if ( is_wp_error( $response ) || ! isset( $response['headers'] ) ) { diff --git a/wp-includes/rest-api.php b/wp-includes/rest-api.php index 9617c81c91..a7cd0178b0 100644 --- a/wp-includes/rest-api.php +++ b/wp-includes/rest-api.php @@ -1390,7 +1390,7 @@ function rest_parse_request_arg( $value, $request, $param ) { function rest_is_ip_address( $ip ) { $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]?)$/'; - if ( ! preg_match( $ipv4_pattern, $ip ) && ! WpOrg\Requests\Ipv6::check_ipv6( $ip ) ) { + if ( ! preg_match( $ipv4_pattern, $ip ) && ! Requests_IPv6::check_ipv6( $ip ) ) { return false; } diff --git a/wp-includes/version.php b/wp-includes/version.php index d89f69a0f2..03ad333ee3 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '5.9-beta1-52327'; +$wp_version = '5.9-beta1-52328'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.