External Libraries: Update the Requests library to version 1.8.0.

While some of the changes in the `1.8.0` release have already been copied to WordPress Core in earlier releases (see [38727], [46258], [47902] and [49382]), this release contains additional improvements, including:

- A significant performance fix when using cURL.
- Improved compliance with RFC2616.

The library has also been moved under the WordPress project’s GitHub organization and can now be found at https://github.com/WordPress/Requests.

Props jrf, dd32, rmccue, justinahinon, netweb, schlessera, TimothyBJacobs, soulseekah, ozh, skithund, carlalexander, travisnorthcutt, desrosj.
Fixes #53101.
Built from https://develop.svn.wordpress.org/trunk@50842


git-svn-id: http://core.svn.wordpress.org/trunk@50451 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
desrosj 2021-05-11 19:42:02 +00:00
parent 2e762721b1
commit f221b3eb54
56 changed files with 398 additions and 325 deletions

View File

@ -29,5 +29,5 @@ interface Requests_Auth {
* @see Requests_Hooks::register * @see Requests_Hooks::register
* @param Requests_Hooks $hooks Hook system * @param Requests_Hooks $hooks Hook system
*/ */
public function register(Requests_Hooks &$hooks); public function register(Requests_Hooks $hooks);
} }

View File

@ -53,9 +53,9 @@ class Requests_Auth_Basic implements Requests_Auth {
* @see fsockopen_header * @see fsockopen_header
* @param Requests_Hooks $hooks Hook system * @param Requests_Hooks $hooks Hook system
*/ */
public function register(Requests_Hooks &$hooks) { public function register(Requests_Hooks $hooks) {
$hooks->register('curl.before_send', array(&$this, 'curl_before_send')); $hooks->register('curl.before_send', array($this, 'curl_before_send'));
$hooks->register('fsockopen.after_headers', array(&$this, 'fsockopen_header')); $hooks->register('fsockopen.after_headers', array($this, 'fsockopen_header'));
} }
/** /**
@ -85,4 +85,4 @@ class Requests_Auth_Basic implements Requests_Auth {
public function getAuthString() { public function getAuthString() {
return $this->user . ':' . $this->pass; return $this->user . ':' . $this->pass;
} }
} }

View File

@ -65,16 +65,16 @@ class Requests_Cookie {
* @param array|Requests_Utility_CaseInsensitiveDictionary $attributes Associative array of attribute data * @param array|Requests_Utility_CaseInsensitiveDictionary $attributes Associative array of attribute data
*/ */
public function __construct($name, $value, $attributes = array(), $flags = array(), $reference_time = null) { public function __construct($name, $value, $attributes = array(), $flags = array(), $reference_time = null) {
$this->name = $name; $this->name = $name;
$this->value = $value; $this->value = $value;
$this->attributes = $attributes; $this->attributes = $attributes;
$default_flags = array( $default_flags = array(
'creation' => time(), 'creation' => time(),
'last-access' => time(), 'last-access' => time(),
'persistent' => false, 'persistent' => false,
'host-only' => true, 'host-only' => true,
); );
$this->flags = array_merge($default_flags, $flags); $this->flags = array_merge($default_flags, $flags);
$this->reference_time = time(); $this->reference_time = time();
if ($reference_time !== null) { if ($reference_time !== null) {
@ -228,7 +228,7 @@ class Requests_Cookie {
public function normalize() { public function normalize() {
foreach ($this->attributes as $key => $value) { foreach ($this->attributes as $key => $value) {
$orig_value = $value; $orig_value = $value;
$value = $this->normalize_attribute($key, $value); $value = $this->normalize_attribute($key, $value);
if ($value === null) { if ($value === null) {
unset($this->attributes[$key]); unset($this->attributes[$key]);
continue; continue;
@ -385,7 +385,7 @@ class Requests_Cookie {
* @return Requests_Cookie Parsed cookie object * @return Requests_Cookie Parsed cookie object
*/ */
public static function parse($string, $name = '', $reference_time = null) { public static function parse($string, $name = '', $reference_time = null) {
$parts = explode(';', $string); $parts = explode(';', $string);
$kvparts = array_shift($parts); $kvparts = array_shift($parts);
if (!empty($name)) { if (!empty($name)) {
@ -397,13 +397,13 @@ class Requests_Cookie {
// (`=foo`) // (`=foo`)
// //
// https://bugzilla.mozilla.org/show_bug.cgi?id=169091 // https://bugzilla.mozilla.org/show_bug.cgi?id=169091
$name = ''; $name = '';
$value = $kvparts; $value = $kvparts;
} }
else { else {
list($name, $value) = explode('=', $kvparts, 2); list($name, $value) = explode('=', $kvparts, 2);
} }
$name = trim($name); $name = trim($name);
$value = trim($value); $value = trim($value);
// Attribute key are handled case-insensitively // Attribute key are handled case-insensitively
@ -412,15 +412,15 @@ class Requests_Cookie {
if (!empty($parts)) { if (!empty($parts)) {
foreach ($parts as $part) { foreach ($parts as $part) {
if (strpos($part, '=') === false) { if (strpos($part, '=') === false) {
$part_key = $part; $part_key = $part;
$part_value = true; $part_value = true;
} }
else { else {
list($part_key, $part_value) = explode('=', $part, 2); list($part_key, $part_value) = explode('=', $part, 2);
$part_value = trim($part_value); $part_value = trim($part_value);
} }
$part_key = trim($part_key); $part_key = trim($part_key);
$attributes[$part_key] = $part_value; $attributes[$part_key] = $part_value;
} }
} }
@ -449,7 +449,7 @@ class Requests_Cookie {
// Default domain/path attributes // Default domain/path attributes
if (empty($parsed->attributes['domain']) && !empty($origin)) { if (empty($parsed->attributes['domain']) && !empty($origin)) {
$parsed->attributes['domain'] = $origin->host; $parsed->attributes['domain'] = $origin->host;
$parsed->flags['host-only'] = true; $parsed->flags['host-only'] = true;
} }
else { else {
$parsed->flags['host-only'] = false; $parsed->flags['host-only'] = false;
@ -497,7 +497,7 @@ class Requests_Cookie {
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @deprecated Use {@see Requests_Cookie::parse_from_headers} * @deprecated Use {@see Requests_Cookie::parse_from_headers}
* @return string * @return array
*/ */
public static function parseFromHeaders(Requests_Response_Headers $headers) { public static function parseFromHeaders(Requests_Response_Headers $headers) {
return self::parse_from_headers($headers); return self::parse_from_headers($headers);

View File

@ -68,7 +68,7 @@ class Requests_Cookie_Jar implements ArrayAccess, IteratorAggregate {
* Get the value for the item * Get the value for the item
* *
* @param string $key Item key * @param string $key Item key
* @return string Item value * @return string|null Item value (null if offsetExists is false)
*/ */
public function offsetGet($key) { public function offsetGet($key) {
if (!isset($this->cookies[$key])) { if (!isset($this->cookies[$key])) {
@ -162,14 +162,14 @@ class Requests_Cookie_Jar implements ArrayAccess, IteratorAggregate {
* *
* @var Requests_Response $response * @var Requests_Response $response
*/ */
public function before_redirect_check(Requests_Response &$return) { public function before_redirect_check(Requests_Response $return) {
$url = $return->url; $url = $return->url;
if (!$url instanceof Requests_IRI) { if (!$url instanceof Requests_IRI) {
$url = new Requests_IRI($url); $url = new Requests_IRI($url);
} }
$cookies = Requests_Cookie::parse_from_headers($return->headers, $url); $cookies = Requests_Cookie::parse_from_headers($return->headers, $url);
$this->cookies = array_merge($this->cookies, $cookies); $this->cookies = array_merge($this->cookies, $cookies);
$return->cookies = $this; $return->cookies = $this;
} }
} }

View File

@ -59,4 +59,4 @@ class Requests_Exception extends Exception {
public function getData() { public function getData() {
return $this->data; return $this->data;
} }
} }

View File

@ -68,4 +68,4 @@ class Requests_Exception_HTTP extends Requests_Exception {
return 'Requests_Exception_HTTP_Unknown'; return 'Requests_Exception_HTTP_Unknown';
} }
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_304 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Not Modified'; protected $reason = 'Not Modified';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_400 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Bad Request'; protected $reason = 'Bad Request';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_401 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Unauthorized'; protected $reason = 'Unauthorized';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_402 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Payment Required'; protected $reason = 'Payment Required';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_403 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Forbidden'; protected $reason = 'Forbidden';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_404 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Not Found'; protected $reason = 'Not Found';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_405 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Method Not Allowed'; protected $reason = 'Method Not Allowed';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_406 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Not Acceptable'; protected $reason = 'Not Acceptable';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_407 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Proxy Authentication Required'; protected $reason = 'Proxy Authentication Required';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_408 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Request Timeout'; protected $reason = 'Request Timeout';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_409 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Conflict'; protected $reason = 'Conflict';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_410 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Gone'; protected $reason = 'Gone';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_411 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Length Required'; protected $reason = 'Length Required';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_412 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Precondition Failed'; protected $reason = 'Precondition Failed';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_413 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Request Entity Too Large'; protected $reason = 'Request Entity Too Large';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_414 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Request-URI Too Large'; protected $reason = 'Request-URI Too Large';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_415 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Unsupported Media Type'; protected $reason = 'Unsupported Media Type';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_416 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Requested Range Not Satisfiable'; protected $reason = 'Requested Range Not Satisfiable';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_417 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Expectation Failed'; protected $reason = 'Expectation Failed';
} }

View File

@ -26,4 +26,4 @@ class Requests_Exception_HTTP_418 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = "I'm A Teapot"; protected $reason = "I'm A Teapot";
} }

View File

@ -26,4 +26,4 @@ class Requests_Exception_HTTP_428 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Precondition Required'; protected $reason = 'Precondition Required';
} }

View File

@ -26,4 +26,4 @@ class Requests_Exception_HTTP_429 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Too Many Requests'; protected $reason = 'Too Many Requests';
} }

View File

@ -26,4 +26,4 @@ class Requests_Exception_HTTP_431 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Request Header Fields Too Large'; protected $reason = 'Request Header Fields Too Large';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_500 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Internal Server Error'; protected $reason = 'Internal Server Error';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_501 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Not Implemented'; protected $reason = 'Not Implemented';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_502 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Bad Gateway'; protected $reason = 'Bad Gateway';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_503 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Service Unavailable'; protected $reason = 'Service Unavailable';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_504 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Gateway Timeout'; protected $reason = 'Gateway Timeout';
} }

View File

@ -24,4 +24,4 @@ class Requests_Exception_HTTP_505 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'HTTP Version Not Supported'; protected $reason = 'HTTP Version Not Supported';
} }

View File

@ -26,4 +26,4 @@ class Requests_Exception_HTTP_511 extends Requests_Exception_HTTP {
* @var string * @var string
*/ */
protected $reason = 'Network Authentication Required'; protected $reason = 'Network Authentication Required';
} }

View File

@ -41,4 +41,4 @@ class Requests_Exception_HTTP_Unknown extends Requests_Exception_HTTP {
parent::__construct($reason, $data); parent::__construct($reason, $data);
} }
} }

View File

@ -2,7 +2,7 @@
class Requests_Exception_Transport_cURL extends Requests_Exception_Transport { class Requests_Exception_Transport_cURL extends Requests_Exception_Transport {
const EASY = 'cURLEasy'; const EASY = 'cURLEasy';
const MULTI = 'cURLMulti'; const MULTI = 'cURLMulti';
const SHARE = 'cURLShare'; const SHARE = 'cURLShare';

View File

@ -30,4 +30,4 @@ interface Requests_Hooker {
* @return boolean Successfulness * @return boolean Successfulness
*/ */
public function dispatch($hook, $parameters = array()); public function dispatch($hook, $parameters = array());
} }

View File

@ -65,4 +65,4 @@ class Requests_Hooks implements Requests_Hooker {
return true; return true;
} }
} }

View File

@ -141,31 +141,32 @@ class Requests_IDNAEncoder {
// Get number of bytes // Get number of bytes
$strlen = strlen($input); $strlen = strlen($input);
// phpcs:ignore Generic.CodeAnalysis.JumbledIncrementer -- This is a deliberate choice.
for ($position = 0; $position < $strlen; $position++) { for ($position = 0; $position < $strlen; $position++) {
$value = ord($input[$position]); $value = ord($input[$position]);
// One byte sequence: // One byte sequence:
if ((~$value & 0x80) === 0x80) { if ((~$value & 0x80) === 0x80) {
$character = $value; $character = $value;
$length = 1; $length = 1;
$remaining = 0; $remaining = 0;
} }
// Two byte sequence: // Two byte sequence:
elseif (($value & 0xE0) === 0xC0) { elseif (($value & 0xE0) === 0xC0) {
$character = ($value & 0x1F) << 6; $character = ($value & 0x1F) << 6;
$length = 2; $length = 2;
$remaining = 1; $remaining = 1;
} }
// Three byte sequence: // Three byte sequence:
elseif (($value & 0xF0) === 0xE0) { elseif (($value & 0xF0) === 0xE0) {
$character = ($value & 0x0F) << 12; $character = ($value & 0x0F) << 12;
$length = 3; $length = 3;
$remaining = 2; $remaining = 2;
} }
// Four byte sequence: // Four byte sequence:
elseif (($value & 0xF8) === 0xF0) { elseif (($value & 0xF8) === 0xF0) {
$character = ($value & 0x07) << 18; $character = ($value & 0x07) << 18;
$length = 4; $length = 4;
$remaining = 3; $remaining = 3;
} }
// Invalid byte: // Invalid byte:
@ -185,14 +186,14 @@ class Requests_IDNAEncoder {
throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
} }
$character |= ($value & 0x3F) << (--$remaining * 6); --$remaining;
$character |= ($value & 0x3F) << ($remaining * 6);
} }
$position--; $position--;
} }
if ( if (// Non-shortest form sequences are invalid
// Non-shortest form sequences are invalid $length > 1 && $character <= 0x7F
$length > 1 && $character <= 0x7F
|| $length > 2 && $character <= 0x7FF || $length > 2 && $character <= 0x7FF
|| $length > 3 && $character <= 0xFFFF || $length > 3 && $character <= 0xFFFF
// Outside of range of ucschar codepoints // Outside of range of ucschar codepoints
@ -201,7 +202,7 @@ class Requests_IDNAEncoder {
|| $character >= 0xFDD0 && $character <= 0xFDEF || $character >= 0xFDD0 && $character <= 0xFDEF
|| ( || (
// Everything else not in ucschar // Everything else not in ucschar
$character > 0xD7FF && $character < 0xF900 $character > 0xD7FF && $character < 0xF900
|| $character < 0x20 || $character < 0x20
|| $character > 0x7E && $character < 0xA0 || $character > 0x7E && $character < 0xA0
|| $character > 0xEFFFD || $character > 0xEFFFD
@ -227,17 +228,18 @@ class Requests_IDNAEncoder {
*/ */
public static function punycode_encode($input) { public static function punycode_encode($input) {
$output = ''; $output = '';
# let n = initial_n // let n = initial_n
$n = self::BOOTSTRAP_INITIAL_N; $n = self::BOOTSTRAP_INITIAL_N;
# let delta = 0 // let delta = 0
$delta = 0; $delta = 0;
# let bias = initial_bias // let bias = initial_bias
$bias = self::BOOTSTRAP_INITIAL_BIAS; $bias = self::BOOTSTRAP_INITIAL_BIAS;
# let h = b = the number of basic code points in the input // let h = b = the number of basic code points in the input
$h = $b = 0; // see loop $h = 0;
# copy them to the output in order $b = 0; // see loop
// copy them to the output in order
$codepoints = self::utf8_to_codepoints($input); $codepoints = self::utf8_to_codepoints($input);
$extended = array(); $extended = array();
foreach ($codepoints as $char) { foreach ($codepoints as $char) {
if ($char < 128) { if ($char < 128) {
@ -260,35 +262,36 @@ class Requests_IDNAEncoder {
$extended = array_keys($extended); $extended = array_keys($extended);
sort($extended); sort($extended);
$b = $h; $b = $h;
# [copy them] followed by a delimiter if b > 0 // [copy them] followed by a delimiter if b > 0
if (strlen($output) > 0) { if (strlen($output) > 0) {
$output .= '-'; $output .= '-';
} }
# {if the input contains a non-basic code point < n then fail} // {if the input contains a non-basic code point < n then fail}
# while h < length(input) do begin // while h < length(input) do begin
while ($h < count($codepoints)) { $codepointcount = count($codepoints);
# let m = the minimum code point >= n in the input while ($h < $codepointcount) {
// let m = the minimum code point >= n in the input
$m = array_shift($extended); $m = array_shift($extended);
//printf('next code point to insert is %s' . PHP_EOL, dechex($m)); //printf('next code point to insert is %s' . PHP_EOL, dechex($m));
# let delta = delta + (m - n) * (h + 1), fail on overflow // let delta = delta + (m - n) * (h + 1), fail on overflow
$delta += ($m - $n) * ($h + 1); $delta += ($m - $n) * ($h + 1);
# let n = m // let n = m
$n = $m; $n = $m;
# for each code point c in the input (in order) do begin // for each code point c in the input (in order) do begin
for ($num = 0; $num < count($codepoints); $num++) { for ($num = 0; $num < $codepointcount; $num++) {
$c = $codepoints[$num]; $c = $codepoints[$num];
# if c < n then increment delta, fail on overflow // if c < n then increment delta, fail on overflow
if ($c < $n) { if ($c < $n) {
$delta++; $delta++;
} }
# if c == n then begin // if c == n then begin
elseif ($c === $n) { elseif ($c === $n) {
# let q = delta // let q = delta
$q = $delta; $q = $delta;
# for k = base to infinity in steps of base do begin // for k = base to infinity in steps of base do begin
for ($k = self::BOOTSTRAP_BASE; ; $k += self::BOOTSTRAP_BASE) { for ($k = self::BOOTSTRAP_BASE; ; $k += self::BOOTSTRAP_BASE) {
# let t = tmin if k <= bias {+ tmin}, or // let t = tmin if k <= bias {+ tmin}, or
# tmax if k >= bias + tmax, or k - bias otherwise // tmax if k >= bias + tmax, or k - bias otherwise
if ($k <= ($bias + self::BOOTSTRAP_TMIN)) { if ($k <= ($bias + self::BOOTSTRAP_TMIN)) {
$t = self::BOOTSTRAP_TMIN; $t = self::BOOTSTRAP_TMIN;
} }
@ -298,34 +301,30 @@ class Requests_IDNAEncoder {
else { else {
$t = $k - $bias; $t = $k - $bias;
} }
# if q < t then break // if q < t then break
if ($q < $t) { if ($q < $t) {
break; break;
} }
# output the code point for digit t + ((q - t) mod (base - t)) // output the code point for digit t + ((q - t) mod (base - t))
$digit = $t + (($q - $t) % (self::BOOTSTRAP_BASE - $t)); $digit = $t + (($q - $t) % (self::BOOTSTRAP_BASE - $t));
$output .= self::digit_to_char($digit); $output .= self::digit_to_char($digit);
# let q = (q - t) div (base - t) // let q = (q - t) div (base - t)
$q = floor(($q - $t) / (self::BOOTSTRAP_BASE - $t)); $q = floor(($q - $t) / (self::BOOTSTRAP_BASE - $t));
# end } // end
} // output the code point for digit q
# output the code point for digit q
$output .= self::digit_to_char($q); $output .= self::digit_to_char($q);
# let bias = adapt(delta, h + 1, test h equals b?) // let bias = adapt(delta, h + 1, test h equals b?)
$bias = self::adapt($delta, $h + 1, $h === $b); $bias = self::adapt($delta, $h + 1, $h === $b);
# let delta = 0 // let delta = 0
$delta = 0; $delta = 0;
# increment h // increment h
$h++; $h++;
# end } // end
} } // end
# end // increment delta and n
}
# increment delta and n
$delta++; $delta++;
$n++; $n++;
# end } // end
}
return $output; return $output;
} }
@ -358,31 +357,31 @@ class Requests_IDNAEncoder {
* @param int $numpoints * @param int $numpoints
* @param bool $firsttime * @param bool $firsttime
* @return int New bias * @return int New bias
*
* function adapt(delta,numpoints,firsttime):
*/ */
protected static function adapt($delta, $numpoints, $firsttime) { protected static function adapt($delta, $numpoints, $firsttime) {
# function adapt(delta,numpoints,firsttime): // if firsttime then let delta = delta div damp
# if firsttime then let delta = delta div damp
if ($firsttime) { if ($firsttime) {
$delta = floor($delta / self::BOOTSTRAP_DAMP); $delta = floor($delta / self::BOOTSTRAP_DAMP);
} }
# else let delta = delta div 2 // else let delta = delta div 2
else { else {
$delta = floor($delta / 2); $delta = floor($delta / 2);
} }
# let delta = delta + (delta div numpoints) // let delta = delta + (delta div numpoints)
$delta += floor($delta / $numpoints); $delta += floor($delta / $numpoints);
# let k = 0 // let k = 0
$k = 0; $k = 0;
# while delta > ((base - tmin) * tmax) div 2 do begin // while delta > ((base - tmin) * tmax) div 2 do begin
$max = floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN) * self::BOOTSTRAP_TMAX) / 2); $max = floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN) * self::BOOTSTRAP_TMAX) / 2);
while ($delta > $max) { while ($delta > $max) {
# let delta = delta div (base - tmin) // let delta = delta div (base - tmin)
$delta = floor($delta / (self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN)); $delta = floor($delta / (self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN));
# let k = k + base // let k = k + base
$k += self::BOOTSTRAP_BASE; $k += self::BOOTSTRAP_BASE;
# end } // end
} // return k + (((base - tmin + 1) * delta) div (delta + skew))
# return k + (((base - tmin + 1) * delta) div (delta + skew))
return $k + floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN + 1) * $delta) / ($delta + self::BOOTSTRAP_SKEW)); return $k + floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN + 1) * $delta) / ($delta + self::BOOTSTRAP_SKEW));
} }
} }

View File

@ -40,8 +40,8 @@ class Requests_IPv6 {
} }
list($ip1, $ip2) = explode('::', $ip); list($ip1, $ip2) = explode('::', $ip);
$c1 = ($ip1 === '') ? -1 : substr_count($ip1, ':'); $c1 = ($ip1 === '') ? -1 : substr_count($ip1, ':');
$c2 = ($ip2 === '') ? -1 : substr_count($ip2, ':'); $c2 = ($ip2 === '') ? -1 : substr_count($ip2, ':');
if (strpos($ip2, '.') !== false) { if (strpos($ip2, '.') !== false) {
$c2++; $c2++;
@ -51,19 +51,19 @@ class Requests_IPv6 {
$ip = '0:0:0:0:0:0:0:0'; $ip = '0:0:0:0:0:0:0:0';
} }
// ::xxx // ::xxx
else if ($c1 === -1) { elseif ($c1 === -1) {
$fill = str_repeat('0:', 7 - $c2); $fill = str_repeat('0:', 7 - $c2);
$ip = str_replace('::', $fill, $ip); $ip = str_replace('::', $fill, $ip);
} }
// xxx:: // xxx::
else if ($c2 === -1) { elseif ($c2 === -1) {
$fill = str_repeat(':0', 7 - $c1); $fill = str_repeat(':0', 7 - $c1);
$ip = str_replace('::', $fill, $ip); $ip = str_replace('::', $fill, $ip);
} }
// xxx::xxx // xxx::xxx
else { else {
$fill = ':' . str_repeat('0:', 6 - $c2 - $c1); $fill = ':' . str_repeat('0:', 6 - $c2 - $c1);
$ip = str_replace('::', $fill, $ip); $ip = str_replace('::', $fill, $ip);
} }
return $ip; return $ip;
} }
@ -84,7 +84,7 @@ class Requests_IPv6 {
*/ */
public static function compress($ip) { public static function compress($ip) {
// Prepare the IP to be compressed // Prepare the IP to be compressed
$ip = self::uncompress($ip); $ip = self::uncompress($ip);
$ip_parts = self::split_v6_v4($ip); $ip_parts = self::split_v6_v4($ip);
// Replace all leading zeros // Replace all leading zeros
@ -126,7 +126,7 @@ class Requests_IPv6 {
*/ */
protected static function split_v6_v4($ip) { protected static function split_v6_v4($ip) {
if (strpos($ip, '.') !== false) { if (strpos($ip, '.') !== false) {
$pos = strrpos($ip, ':'); $pos = strrpos($ip, ':');
$ipv6_part = substr($ip, 0, $pos); $ipv6_part = substr($ip, 0, $pos);
$ipv4_part = substr($ip, $pos + 1); $ipv4_part = substr($ip, $pos + 1);
return array($ipv6_part, $ipv4_part); return array($ipv6_part, $ipv4_part);
@ -145,10 +145,10 @@ class Requests_IPv6 {
* @return bool true if $ip is a valid IPv6 address * @return bool true if $ip is a valid IPv6 address
*/ */
public static function check_ipv6($ip) { public static function check_ipv6($ip) {
$ip = self::uncompress($ip); $ip = self::uncompress($ip);
list($ipv6, $ipv4) = self::split_v6_v4($ip); list($ipv6, $ipv4) = self::split_v6_v4($ip);
$ipv6 = explode(':', $ipv6); $ipv6 = explode(':', $ipv6);
$ipv4 = explode('.', $ipv4); $ipv4 = explode('.', $ipv4);
if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4) { if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4) {
foreach ($ipv6 as $ipv6_part) { foreach ($ipv6 as $ipv6_part) {
// The section can't be empty // The section can't be empty

View File

@ -67,28 +67,28 @@ class Requests_IRI {
/** /**
* Scheme * Scheme
* *
* @var string * @var string|null
*/ */
protected $scheme = null; protected $scheme = null;
/** /**
* User Information * User Information
* *
* @var string * @var string|null
*/ */
protected $iuserinfo = null; protected $iuserinfo = null;
/** /**
* ihost * ihost
* *
* @var string * @var string|null
*/ */
protected $ihost = null; protected $ihost = null;
/** /**
* Port * Port
* *
* @var string * @var string|null
*/ */
protected $port = null; protected $port = null;
@ -102,12 +102,12 @@ class Requests_IRI {
/** /**
* iquery * iquery
* *
* @var string * @var string|null
*/ */
protected $iquery = null; protected $iquery = null;
/** /**
* ifragment * ifragment|null
* *
* @var string * @var string
*/ */
@ -118,6 +118,8 @@ class Requests_IRI {
* *
* Each key is the scheme, each value is an array with each key as the IRI * Each key is the scheme, each value is an array with each key as the IRI
* part and value as the default value for that part. * part and value as the default value for that part.
*
* @var array
*/ */
protected $normalization = array( protected $normalization = array(
'acap' => array( 'acap' => array(
@ -249,9 +251,9 @@ class Requests_IRI {
* *
* Returns false if $base is not absolute, otherwise an IRI. * Returns false if $base is not absolute, otherwise an IRI.
* *
* @param IRI|string $base (Absolute) Base IRI * @param Requests_IRI|string $base (Absolute) Base IRI
* @param IRI|string $relative Relative IRI * @param Requests_IRI|string $relative Relative IRI
* @return IRI|false * @return Requests_IRI|false
*/ */
public static function absolutize($base, $relative) { public static function absolutize($base, $relative) {
if (!($relative instanceof Requests_IRI)) { if (!($relative instanceof Requests_IRI)) {
@ -419,7 +421,7 @@ class Requests_IRI {
*/ */
protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) { protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) {
// Normalize as many pct-encoded sections as possible // Normalize as many pct-encoded sections as possible
$string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string); $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $string);
// Replace invalid percent characters // Replace invalid percent characters
$string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string); $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
@ -1010,7 +1012,7 @@ class Requests_IRI {
/** /**
* Get the complete IRI * Get the complete IRI
* *
* @return string * @return string|false
*/ */
protected function get_iri() { protected function get_iri() {
if (!$this->is_valid()) { if (!$this->is_valid()) {
@ -1047,7 +1049,7 @@ class Requests_IRI {
/** /**
* Get the complete iauthority * Get the complete iauthority
* *
* @return string * @return string|null
*/ */
protected function get_iauthority() { protected function get_iauthority() {
if ($this->iuserinfo === null && $this->ihost === null && $this->port === null) { if ($this->iuserinfo === null && $this->ihost === null && $this->port === null) {

View File

@ -31,5 +31,5 @@ interface Requests_Proxy {
* @see Requests_Hooks::register * @see Requests_Hooks::register
* @param Requests_Hooks $hooks Hook system * @param Requests_Hooks $hooks Hook system
*/ */
public function register(Requests_Hooks &$hooks); public function register(Requests_Hooks $hooks);
} }

View File

@ -59,12 +59,12 @@ class Requests_Proxy_HTTP implements Requests_Proxy {
$this->proxy = $args; $this->proxy = $args;
} }
elseif (is_array($args)) { elseif (is_array($args)) {
if (count($args) == 1) { if (count($args) === 1) {
list($this->proxy) = $args; list($this->proxy) = $args;
} }
elseif (count($args) == 3) { elseif (count($args) === 3) {
list($this->proxy, $this->user, $this->pass) = $args; list($this->proxy, $this->user, $this->pass) = $args;
$this->use_authentication = true; $this->use_authentication = true;
} }
else { else {
throw new Requests_Exception('Invalid number of arguments', 'proxyhttpbadargs'); throw new Requests_Exception('Invalid number of arguments', 'proxyhttpbadargs');
@ -82,13 +82,13 @@ class Requests_Proxy_HTTP implements Requests_Proxy {
* @see fsockopen_header * @see fsockopen_header
* @param Requests_Hooks $hooks Hook system * @param Requests_Hooks $hooks Hook system
*/ */
public function register(Requests_Hooks &$hooks) { public function register(Requests_Hooks $hooks) {
$hooks->register('curl.before_send', array(&$this, 'curl_before_send')); $hooks->register('curl.before_send', array($this, 'curl_before_send'));
$hooks->register('fsockopen.remote_socket', array(&$this, 'fsockopen_remote_socket')); $hooks->register('fsockopen.remote_socket', array($this, 'fsockopen_remote_socket'));
$hooks->register('fsockopen.remote_host_path', array(&$this, 'fsockopen_remote_host_path')); $hooks->register('fsockopen.remote_host_path', array($this, 'fsockopen_remote_host_path'));
if ($this->use_authentication) { if ($this->use_authentication) {
$hooks->register('fsockopen.after_headers', array(&$this, 'fsockopen_header')); $hooks->register('fsockopen.after_headers', array($this, 'fsockopen_header'));
} }
} }
@ -148,4 +148,4 @@ class Requests_Proxy_HTTP implements Requests_Proxy {
public function get_auth_string() { public function get_auth_string() {
return $this->user . ':' . $this->pass; return $this->user . ':' . $this->pass;
} }
} }

View File

@ -51,6 +51,7 @@ class Requests_Response {
/** /**
* Protocol version, false if non-blocking * Protocol version, false if non-blocking
*
* @var float|boolean * @var float|boolean
*/ */
public $protocol_version = false; public $protocol_version = false;
@ -97,7 +98,7 @@ class Requests_Response {
*/ */
public function is_redirect() { public function is_redirect() {
$code = $this->status_code; $code = $this->status_code;
return in_array($code, array(300, 301, 302, 303, 307)) || $code > 307 && $code < 400; return in_array($code, array(300, 301, 302, 303, 307), true) || $code > 307 && $code < 400;
} }
/** /**

View File

@ -21,7 +21,7 @@ class Requests_Response_Headers extends Requests_Utility_CaseInsensitiveDictiona
* Set-Cookie headers. * Set-Cookie headers.
* *
* @param string $key * @param string $key
* @return string Header value * @return string|null Header value
*/ */
public function offsetGet($key) { public function offsetGet($key) {
$key = strtolower($key); $key = strtolower($key);
@ -58,7 +58,7 @@ class Requests_Response_Headers extends Requests_Utility_CaseInsensitiveDictiona
* Get all values for a given header * Get all values for a given header
* *
* @param string $key * @param string $key
* @return array Header values * @return array|null Header values
*/ */
public function getValues($key) { public function getValues($key) {
$key = strtolower($key); $key = strtolower($key);

View File

@ -20,7 +20,6 @@ class Requests_SSL {
* *
* Unfortunately, PHP doesn't check the certificate against the alternative * Unfortunately, PHP doesn't check the certificate against the alternative
* names, leading things like 'https://www.github.com/' to be invalid. * names, leading things like 'https://www.github.com/' to be invalid.
* Instead
* *
* @see 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
* *
@ -30,13 +29,6 @@ class Requests_SSL {
* @return bool * @return bool
*/ */
public static function verify_certificate($host, $cert) { public static function verify_certificate($host, $cert) {
// Calculate the valid wildcard match if the host is not an IP address
$parts = explode('.', $host);
if (ip2long($host) === false) {
$parts[0] = '*';
}
$wildcard = implode('.', $parts);
$has_dns_alt = false; $has_dns_alt = false;
// Check the subjectAltName // Check the subjectAltName
@ -139,7 +131,7 @@ class Requests_SSL {
// Also validates that the host has 3 parts or more, as per Firefox's // Also validates that the host has 3 parts or more, as per Firefox's
// ruleset. // ruleset.
if (ip2long($host) === false) { if (ip2long($host) === false) {
$parts = explode('.', $host); $parts = explode('.', $host);
$parts[0] = '*'; $parts[0] = '*';
$wildcard = implode('.', $parts); $wildcard = implode('.', $parts);
if ($wildcard === $reference) { if ($wildcard === $reference) {

View File

@ -22,12 +22,14 @@ class Requests_Session {
* Base URL for requests * Base URL for requests
* *
* URLs will be made absolute using this as the base * URLs will be made absolute using this as the base
*
* @var string|null * @var string|null
*/ */
public $url = null; public $url = null;
/** /**
* Base headers for requests * Base headers for requests
*
* @var array * @var array
*/ */
public $headers = array(); public $headers = array();
@ -64,9 +66,9 @@ class Requests_Session {
* @param array $options Default options for requests * @param array $options Default options for requests
*/ */
public function __construct($url = null, $headers = array(), $data = array(), $options = array()) { public function __construct($url = null, $headers = array(), $data = array(), $options = array()) {
$this->url = $url; $this->url = $url;
$this->headers = $headers; $this->headers = $headers;
$this->data = $data; $this->data = $data;
$this->options = $options; $this->options = $options;
if (empty($this->options['cookies'])) { if (empty($this->options['cookies'])) {

View File

@ -38,4 +38,4 @@ interface Requests_Transport {
* @return bool * @return bool
*/ */
public static function test(); public static function test();
} }

View File

@ -38,9 +38,9 @@ class Requests_Transport_cURL implements Requests_Transport {
public $info; public $info;
/** /**
* Version string * cURL version number
* *
* @var long * @var int
*/ */
public $version; public $version;
@ -90,9 +90,9 @@ class Requests_Transport_cURL implements Requests_Transport {
* Constructor * Constructor
*/ */
public function __construct() { public function __construct() {
$curl = curl_version(); $curl = curl_version();
$this->version = $curl['version_number']; $this->version = $curl['version_number'];
$this->handle = curl_init(); $this->handle = curl_init();
curl_setopt($this->handle, CURLOPT_HEADER, false); curl_setopt($this->handle, CURLOPT_HEADER, false);
curl_setopt($this->handle, CURLOPT_RETURNTRANSFER, 1); curl_setopt($this->handle, CURLOPT_RETURNTRANSFER, 1);
@ -100,9 +100,11 @@ class Requests_Transport_cURL implements Requests_Transport {
curl_setopt($this->handle, CURLOPT_ENCODING, ''); curl_setopt($this->handle, CURLOPT_ENCODING, '');
} }
if (defined('CURLOPT_PROTOCOLS')) { if (defined('CURLOPT_PROTOCOLS')) {
// phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_protocolsFound
curl_setopt($this->handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); curl_setopt($this->handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
} }
if (defined('CURLOPT_REDIR_PROTOCOLS')) { if (defined('CURLOPT_REDIR_PROTOCOLS')) {
// phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_redir_protocolsFound
curl_setopt($this->handle, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); curl_setopt($this->handle, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
} }
} }
@ -138,8 +140,8 @@ class Requests_Transport_cURL implements Requests_Transport {
$this->stream_handle = fopen($options['filename'], 'wb'); $this->stream_handle = fopen($options['filename'], 'wb');
} }
$this->response_data = ''; $this->response_data = '';
$this->response_bytes = 0; $this->response_bytes = 0;
$this->response_byte_limit = false; $this->response_byte_limit = false;
if ($options['max_bytes'] !== false) { if ($options['max_bytes'] !== false) {
$this->response_byte_limit = $options['max_bytes']; $this->response_byte_limit = $options['max_bytes'];
@ -168,7 +170,7 @@ class Requests_Transport_cURL implements Requests_Transport {
// Reset encoding and try again // Reset encoding and try again
curl_setopt($this->handle, CURLOPT_ENCODING, 'none'); curl_setopt($this->handle, CURLOPT_ENCODING, 'none');
$this->response_data = ''; $this->response_data = '';
$this->response_bytes = 0; $this->response_bytes = 0;
curl_exec($this->handle); curl_exec($this->handle);
$response = $this->response_data; $response = $this->response_data;
@ -199,23 +201,24 @@ class Requests_Transport_cURL implements Requests_Transport {
$multihandle = curl_multi_init(); $multihandle = curl_multi_init();
$subrequests = array(); $subrequests = array();
$subhandles = array(); $subhandles = array();
$class = get_class($this); $class = get_class($this);
foreach ($requests as $id => $request) { foreach ($requests as $id => $request) {
$subrequests[$id] = new $class(); $subrequests[$id] = new $class();
$subhandles[$id] = $subrequests[$id]->get_subrequest_handle($request['url'], $request['headers'], $request['data'], $request['options']); $subhandles[$id] = $subrequests[$id]->get_subrequest_handle($request['url'], $request['headers'], $request['data'], $request['options']);
$request['options']['hooks']->dispatch('curl.before_multi_add', array(&$subhandles[$id])); $request['options']['hooks']->dispatch('curl.before_multi_add', array(&$subhandles[$id]));
curl_multi_add_handle($multihandle, $subhandles[$id]); curl_multi_add_handle($multihandle, $subhandles[$id]);
} }
$completed = 0; $completed = 0;
$responses = array(); $responses = array();
$subrequestcount = count($subrequests);
$request['options']['hooks']->dispatch('curl.before_multi_exec', array(&$multihandle)); $request['options']['hooks']->dispatch('curl.before_multi_exec', array(&$multihandle));
do { do {
$active = false; $active = 0;
do { do {
$status = curl_multi_exec($multihandle, $active); $status = curl_multi_exec($multihandle, $active);
@ -235,15 +238,15 @@ class Requests_Transport_cURL implements Requests_Transport {
// Parse the finished requests before we start getting the new ones // Parse the finished requests before we start getting the new ones
foreach ($to_process as $key => $done) { foreach ($to_process as $key => $done) {
$options = $requests[$key]['options']; $options = $requests[$key]['options'];
if (CURLE_OK !== $done['result']) { if ($done['result'] !== CURLE_OK) {
//get error string for handle. //get error string for handle.
$reason = curl_error($done['handle']); $reason = curl_error($done['handle']);
$exception = new Requests_Exception_Transport_cURL( $exception = new Requests_Exception_Transport_cURL(
$reason, $reason,
Requests_Exception_Transport_cURL::EASY, Requests_Exception_Transport_cURL::EASY,
$done['handle'], $done['handle'],
$done['result'] $done['result']
); );
$responses[$key] = $exception; $responses[$key] = $exception;
$options['hooks']->dispatch('transport.internal.parse_error', array(&$responses[$key], $requests[$key])); $options['hooks']->dispatch('transport.internal.parse_error', array(&$responses[$key], $requests[$key]));
} }
@ -262,7 +265,7 @@ class Requests_Transport_cURL implements Requests_Transport {
$completed++; $completed++;
} }
} }
while ($active || $completed < count($subrequests)); while ($active || $completed < $subrequestcount);
$request['options']['hooks']->dispatch('curl.after_multi_exec', array(&$multihandle)); $request['options']['hooks']->dispatch('curl.after_multi_exec', array(&$multihandle));
@ -287,8 +290,8 @@ class Requests_Transport_cURL implements Requests_Transport {
$this->stream_handle = fopen($options['filename'], 'wb'); $this->stream_handle = fopen($options['filename'], 'wb');
} }
$this->response_data = ''; $this->response_data = '';
$this->response_bytes = 0; $this->response_bytes = 0;
$this->response_byte_limit = false; $this->response_byte_limit = false;
if ($options['max_bytes'] !== false) { if ($options['max_bytes'] !== false) {
$this->response_byte_limit = $options['max_bytes']; $this->response_byte_limit = $options['max_bytes'];
@ -310,17 +313,32 @@ class Requests_Transport_cURL implements Requests_Transport {
$options['hooks']->dispatch('curl.before_request', array(&$this->handle)); $options['hooks']->dispatch('curl.before_request', array(&$this->handle));
// Force closing the connection for old versions of cURL (<7.22). // Force closing the connection for old versions of cURL (<7.22).
if ( ! isset( $headers['Connection'] ) ) { if (!isset($headers['Connection'])) {
$headers['Connection'] = 'close'; $headers['Connection'] = 'close';
} }
/**
* Add "Expect" header.
*
* By default, cURL adds a "Expect: 100-Continue" to most requests. This header can
* add as much as a second to the time it takes for cURL to perform a request. To
* prevent this, we need to set an empty "Expect" header. To match the behaviour of
* Guzzle, we'll add the empty header to requests that are smaller than 1 MB and use
* HTTP/1.1.
*
* https://curl.se/mail/lib-2017-07/0013.html
*/
if (!isset($headers['Expect']) && $options['protocol_version'] === 1.1) {
$headers['Expect'] = $this->get_expect_header($data);
}
$headers = Requests::flatten($headers); $headers = Requests::flatten($headers);
if (!empty($data)) { if (!empty($data)) {
$data_format = $options['data_format']; $data_format = $options['data_format'];
if ($data_format === 'query') { if ($data_format === 'query') {
$url = self::format_get($url, $data); $url = self::format_get($url, $data);
$data = ''; $data = '';
} }
elseif (!is_string($data)) { elseif (!is_string($data)) {
@ -363,6 +381,7 @@ class Requests_Transport_cURL implements Requests_Transport {
curl_setopt($this->handle, CURLOPT_TIMEOUT, ceil($timeout)); curl_setopt($this->handle, CURLOPT_TIMEOUT, ceil($timeout));
} }
else { else {
// phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_timeout_msFound
curl_setopt($this->handle, CURLOPT_TIMEOUT_MS, round($timeout * 1000)); curl_setopt($this->handle, CURLOPT_TIMEOUT_MS, round($timeout * 1000));
} }
@ -370,6 +389,7 @@ class Requests_Transport_cURL implements Requests_Transport {
curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT, ceil($options['connect_timeout'])); curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT, ceil($options['connect_timeout']));
} }
else { else {
// phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_connecttimeout_msFound
curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT_MS, round($options['connect_timeout'] * 1000)); curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT_MS, round($options['connect_timeout'] * 1000));
} }
curl_setopt($this->handle, CURLOPT_URL, $url); curl_setopt($this->handle, CURLOPT_URL, $url);
@ -385,9 +405,9 @@ class Requests_Transport_cURL implements Requests_Transport {
curl_setopt($this->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_setopt($this->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
} }
if (true === $options['blocking']) { if ($options['blocking'] === true) {
curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, array(&$this, 'stream_headers')); 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_WRITEFUNCTION, array($this, 'stream_body'));
curl_setopt($this->handle, CURLOPT_BUFFERSIZE, Requests::BUFFER_SIZE); curl_setopt($this->handle, CURLOPT_BUFFERSIZE, Requests::BUFFER_SIZE);
} }
} }
@ -397,7 +417,8 @@ class Requests_Transport_cURL implements Requests_Transport {
* *
* @param string $response Response data from the body * @param string $response Response data from the body
* @param array $options Request options * @param array $options Request options
* @return string HTTP response data including headers * @return string|false HTTP response data including headers. False if non-blocking.
* @throws Requests_Exception
*/ */
public function process_response($response, $options) { public function process_response($response, $options) {
if ($options['blocking'] === false) { if ($options['blocking'] === false) {
@ -405,7 +426,7 @@ class Requests_Transport_cURL implements Requests_Transport {
$options['hooks']->dispatch('curl.after_request', array(&$fake_headers)); $options['hooks']->dispatch('curl.after_request', array(&$fake_headers));
return false; return false;
} }
if ($options['filename'] !== false) { if ($options['filename'] !== false && $this->stream_handle) {
fclose($this->stream_handle); fclose($this->stream_handle);
$this->headers = trim($this->headers); $this->headers = trim($this->headers);
} }
@ -439,7 +460,7 @@ class Requests_Transport_cURL implements Requests_Transport {
// interim responses, such as a 100 Continue. We don't need that. // interim responses, such as a 100 Continue. We don't need that.
// (We may want to keep this somewhere just in case) // (We may want to keep this somewhere just in case)
if ($this->done_headers) { if ($this->done_headers) {
$this->headers = ''; $this->headers = '';
$this->done_headers = false; $this->done_headers = false;
} }
$this->headers .= $headers; $this->headers .= $headers;
@ -473,7 +494,7 @@ class Requests_Transport_cURL implements Requests_Transport {
if (($this->response_bytes + $data_length) > $this->response_byte_limit) { if (($this->response_bytes + $data_length) > $this->response_byte_limit) {
// Limit the length // Limit the length
$limited_length = ($this->response_byte_limit - $this->response_bytes); $limited_length = ($this->response_byte_limit - $this->response_bytes);
$data = substr($data, 0, $limited_length); $data = substr($data, 0, $limited_length);
} }
} }
@ -497,16 +518,17 @@ class Requests_Transport_cURL implements Requests_Transport {
*/ */
protected static function format_get($url, $data) { protected static function format_get($url, $data) {
if (!empty($data)) { if (!empty($data)) {
$query = '';
$url_parts = parse_url($url); $url_parts = parse_url($url);
if (empty($url_parts['query'])) { if (empty($url_parts['query'])) {
$query = $url_parts['query'] = ''; $url_parts['query'] = '';
} }
else { else {
$query = $url_parts['query']; $query = $url_parts['query'];
} }
$query .= '&' . http_build_query($data, null, '&'); $query .= '&' . http_build_query($data, null, '&');
$query = trim($query, '&'); $query = trim($query, '&');
if (empty($url_parts['query'])) { if (empty($url_parts['query'])) {
$url .= '?' . $query; $url .= '?' . $query;
@ -539,4 +561,29 @@ class Requests_Transport_cURL implements Requests_Transport {
return true; return true;
} }
/**
* Get the correct "Expect" header for the given request data.
*
* @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.
*/
protected function get_expect_header($data) {
if (!is_array($data)) {
return strlen((string) $data) >= 1048576 ? '100-Continue' : '';
}
$bytesize = 0;
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($data));
foreach ($iterator as $datum) {
$bytesize += strlen((string) $datum);
if ($bytesize >= 1048576) {
return '100-Continue';
}
}
return '';
}
} }

View File

@ -62,9 +62,9 @@ class Requests_Transport_fsockopen implements Requests_Transport {
if (empty($url_parts)) { if (empty($url_parts)) {
throw new Requests_Exception('Invalid URL.', 'invalidurl', $url); throw new Requests_Exception('Invalid URL.', 'invalidurl', $url);
} }
$host = $url_parts['host']; $host = $url_parts['host'];
$context = stream_context_create(); $context = stream_context_create();
$verifyname = false; $verifyname = false;
$case_insensitive_headers = new Requests_Utility_CaseInsensitiveDictionary($headers); $case_insensitive_headers = new Requests_Utility_CaseInsensitiveDictionary($headers);
// HTTPS support // HTTPS support
@ -75,13 +75,13 @@ class Requests_Transport_fsockopen implements Requests_Transport {
} }
$context_options = array( $context_options = array(
'verify_peer' => true, 'verify_peer' => true,
// 'CN_match' => $host, 'capture_peer_cert' => true,
'capture_peer_cert' => true
); );
$verifyname = true; $verifyname = true;
// SNI, if enabled (OpenSSL >=0.9.8j) // SNI, if enabled (OpenSSL >=0.9.8j)
// phpcs:ignore PHPCompatibility.Constants.NewConstants.openssl_tlsext_server_nameFound
if (defined('OPENSSL_TLSEXT_SERVER_NAME') && OPENSSL_TLSEXT_SERVER_NAME) { if (defined('OPENSSL_TLSEXT_SERVER_NAME') && OPENSSL_TLSEXT_SERVER_NAME) {
$context_options['SNI_enabled'] = true; $context_options['SNI_enabled'] = true;
if (isset($options['verifyname']) && $options['verifyname'] === false) { if (isset($options['verifyname']) && $options['verifyname'] === false) {
@ -91,7 +91,9 @@ class Requests_Transport_fsockopen implements Requests_Transport {
if (isset($options['verify'])) { if (isset($options['verify'])) {
if ($options['verify'] === false) { if ($options['verify'] === false) {
$context_options['verify_peer'] = false; $context_options['verify_peer'] = false;
$context_options['verify_peer_name'] = false;
$verifyname = false;
} }
elseif (is_string($options['verify'])) { elseif (is_string($options['verify'])) {
$context_options['cafile'] = $options['verify']; $context_options['cafile'] = $options['verify'];
@ -100,7 +102,7 @@ class Requests_Transport_fsockopen implements Requests_Transport {
if (isset($options['verifyname']) && $options['verifyname'] === false) { if (isset($options['verifyname']) && $options['verifyname'] === false) {
$context_options['verify_peer_name'] = false; $context_options['verify_peer_name'] = false;
$verifyname = false; $verifyname = false;
} }
stream_context_set_option($context, array('ssl' => $context_options)); stream_context_set_option($context, array('ssl' => $context_options));
@ -116,6 +118,7 @@ class Requests_Transport_fsockopen implements Requests_Transport {
} }
$remote_socket .= ':' . $url_parts['port']; $remote_socket .= ':' . $url_parts['port'];
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler
set_error_handler(array($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', array(&$remote_socket)); $options['hooks']->dispatch('fsockopen.remote_socket', array(&$remote_socket));
@ -150,17 +153,19 @@ class Requests_Transport_fsockopen implements Requests_Transport {
$options['hooks']->dispatch('fsockopen.remote_host_path', array(&$path, $url)); $options['hooks']->dispatch('fsockopen.remote_host_path', array(&$path, $url));
$request_body = ''; $request_body = '';
$out = sprintf("%s %s HTTP/%.1F\r\n", $options['type'], $path, $options['protocol_version']); $out = sprintf("%s %s HTTP/%.1F\r\n", $options['type'], $path, $options['protocol_version']);
if ($options['type'] !== Requests::TRACE) { if ($options['type'] !== Requests::TRACE) {
if (is_array($data)) { if (is_array($data)) {
$request_body = http_build_query($data, null, '&'); $request_body = http_build_query($data, '', '&');
} }
else { else {
$request_body = $data; $request_body = $data;
} }
if (!empty($data)) { // Always include Content-length on POST requests to prevent
// 411 errors from some servers when the body is empty.
if (!empty($data) || $options['type'] === Requests::POST) {
if (!isset($case_insensitive_headers['Content-Length'])) { if (!isset($case_insensitive_headers['Content-Length'])) {
$headers['Content-Length'] = strlen($request_body); $headers['Content-Length'] = strlen($request_body);
} }
@ -174,7 +179,7 @@ class Requests_Transport_fsockopen implements Requests_Transport {
if (!isset($case_insensitive_headers['Host'])) { if (!isset($case_insensitive_headers['Host'])) {
$out .= sprintf('Host: %s', $url_parts['host']); $out .= sprintf('Host: %s', $url_parts['host']);
if (( 'http' === strtolower($url_parts['scheme']) && $url_parts['port'] !== 80 ) || ( 'https' === strtolower($url_parts['scheme']) && $url_parts['port'] !== 443 )) { if ((strtolower($url_parts['scheme']) === 'http' && $url_parts['port'] !== 80) || (strtolower($url_parts['scheme']) === 'https' && $url_parts['port'] !== 443)) {
$out .= ':' . $url_parts['port']; $out .= ':' . $url_parts['port'];
} }
$out .= "\r\n"; $out .= "\r\n";
@ -220,7 +225,7 @@ class Requests_Transport_fsockopen implements Requests_Transport {
} }
$timeout_sec = (int) floor($options['timeout']); $timeout_sec = (int) floor($options['timeout']);
if ($timeout_sec == $options['timeout']) { if ($timeout_sec === $options['timeout']) {
$timeout_msec = 0; $timeout_msec = 0;
} }
else { else {
@ -228,11 +233,13 @@ class Requests_Transport_fsockopen implements Requests_Transport {
} }
stream_set_timeout($socket, $timeout_sec, $timeout_msec); stream_set_timeout($socket, $timeout_sec, $timeout_msec);
$response = $body = $headers = ''; $response = '';
$body = '';
$headers = '';
$this->info = stream_get_meta_data($socket); $this->info = stream_get_meta_data($socket);
$size = 0; $size = 0;
$doingbody = false; $doingbody = false;
$download = false; $download = false;
if ($options['filename']) { if ($options['filename']) {
$download = fopen($options['filename'], 'wb'); $download = fopen($options['filename'], 'wb');
} }
@ -248,7 +255,7 @@ class Requests_Transport_fsockopen implements Requests_Transport {
$response .= $block; $response .= $block;
if (strpos($response, "\r\n\r\n")) { if (strpos($response, "\r\n\r\n")) {
list($headers, $block) = explode("\r\n\r\n", $response, 2); list($headers, $block) = explode("\r\n\r\n", $response, 2);
$doingbody = true; $doingbody = true;
} }
} }
@ -264,7 +271,7 @@ class Requests_Transport_fsockopen implements Requests_Transport {
if (($size + $data_length) > $this->max_bytes) { if (($size + $data_length) > $this->max_bytes) {
// Limit the length // Limit the length
$limited_length = ($this->max_bytes - $size); $limited_length = ($this->max_bytes - $size);
$block = substr($block, 0, $limited_length); $block = substr($block, 0, $limited_length);
} }
} }
@ -300,10 +307,10 @@ class Requests_Transport_fsockopen implements Requests_Transport {
*/ */
public function request_multiple($requests, $options) { public function request_multiple($requests, $options) {
$responses = array(); $responses = array();
$class = get_class($this); $class = get_class($this);
foreach ($requests as $id => $request) { foreach ($requests as $id => $request) {
try { try {
$handler = new $class(); $handler = new $class();
$responses[$id] = $handler->request($request['url'], $request['headers'], $request['data'], $request['options']); $responses[$id] = $handler->request($request['url'], $request['headers'], $request['data'], $request['options']);
$request['options']['hooks']->dispatch('transport.internal.parse_response', array(&$responses[$id], $request)); $request['options']['hooks']->dispatch('transport.internal.parse_response', array(&$responses[$id], $request));
@ -353,8 +360,8 @@ class Requests_Transport_fsockopen implements Requests_Transport {
$url_parts['query'] = ''; $url_parts['query'] = '';
} }
$url_parts['query'] .= '&' . http_build_query($data, null, '&'); $url_parts['query'] .= '&' . http_build_query($data, '', '&');
$url_parts['query'] = trim($url_parts['query'], '&'); $url_parts['query'] = trim($url_parts['query'], '&');
} }
if (isset($url_parts['path'])) { if (isset($url_parts['path'])) {
if (isset($url_parts['query'])) { if (isset($url_parts['query'])) {

View File

@ -46,7 +46,7 @@ class Requests_Utility_CaseInsensitiveDictionary implements ArrayAccess, Iterato
* Get the value for the item * Get the value for the item
* *
* @param string $key Item key * @param string $key Item key
* @return string Item value * @return string|null Item value (null if offsetExists is false)
*/ */
public function offsetGet($key) { public function offsetGet($key) {
$key = strtolower($key); $key = strtolower($key);
@ -70,7 +70,7 @@ class Requests_Utility_CaseInsensitiveDictionary implements ArrayAccess, Iterato
throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset'); throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset');
} }
$key = strtolower($key); $key = strtolower($key);
$this->data[$key] = $value; $this->data[$key] = $value;
} }

View File

@ -39,23 +39,27 @@ class Requests_Utility_FilteredIterator extends ArrayIterator {
*/ */
public function current() { public function current() {
$value = parent::current(); $value = parent::current();
$value = call_user_func($this->callback, $value);
if (is_callable($this->callback)) {
$value = call_user_func($this->callback, $value);
}
return $value; return $value;
} }
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function unserialize( $serialized ) { public function unserialize($serialized) {}
}
/** /**
* @inheritdoc * @inheritdoc
*
* @phpcs:disable PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.MethodDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound
*/ */
public function __unserialize( $serialized ) { // phpcs:ignore PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.MethodDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound public function __unserialize($serialized) {}
}
public function __wakeup() { // phpcs:ignore PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.MethodDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__wakeupFound public function __wakeup() {
unset( $this->callback ); unset($this->callback);
} }
} }

View File

@ -88,7 +88,7 @@ class Requests {
* *
* @var string * @var string
*/ */
const VERSION = '1.7-3470169'; const VERSION = '1.7';
/** /**
* Registered transport classes * Registered transport classes
@ -143,7 +143,7 @@ class Requests {
$file = str_replace('_', '/', $class); $file = str_replace('_', '/', $class);
if (file_exists(dirname(__FILE__) . '/' . $file . '.php')) { if (file_exists(dirname(__FILE__) . '/' . $file . '.php')) {
require_once(dirname(__FILE__) . '/' . $file . '.php'); require_once dirname(__FILE__) . '/' . $file . '.php';
} }
} }
@ -342,7 +342,7 @@ class Requests {
* across transports.) * across transports.)
* (string|boolean, default: library/Requests/Transport/cacert.pem) * (string|boolean, default: library/Requests/Transport/cacert.pem)
* - `verifyname`: Should we verify the common name in the SSL certificate? * - `verifyname`: Should we verify the common name in the SSL certificate?
* (boolean: default, true) * (boolean, default: true)
* - `data_format`: How should we send the `$data` parameter? * - `data_format`: How should we send the `$data` parameter?
* (string, one of 'query' or 'body', default: 'query' for * (string, one of 'query' or 'body', default: 'query' for
* HEAD/GET/DELETE, 'body' for POST/PUT/OPTIONS/PATCH) * HEAD/GET/DELETE, 'body' for POST/PUT/OPTIONS/PATCH)
@ -374,9 +374,9 @@ class Requests {
} }
} }
else { else {
$need_ssl = (0 === stripos($url, 'https://')); $need_ssl = (stripos($url, 'https://') === 0);
$capabilities = array('ssl' => $need_ssl); $capabilities = array('ssl' => $need_ssl);
$transport = self::get_transport($capabilities); $transport = self::get_transport($capabilities);
} }
$response = $transport->request($url, $headers, $data, $options); $response = $transport->request($url, $headers, $data, $options);
@ -447,7 +447,7 @@ class Requests {
$request['type'] = self::GET; $request['type'] = self::GET;
} }
if (!isset($request['options'])) { if (!isset($request['options'])) {
$request['options'] = $options; $request['options'] = $options;
$request['options']['type'] = $request['type']; $request['options']['type'] = $request['type'];
} }
else { else {
@ -503,25 +503,25 @@ class Requests {
*/ */
protected static function get_default_options($multirequest = false) { protected static function get_default_options($multirequest = false) {
$defaults = array( $defaults = array(
'timeout' => 10, 'timeout' => 10,
'connect_timeout' => 10, 'connect_timeout' => 10,
'useragent' => 'php-requests/' . self::VERSION, 'useragent' => 'php-requests/' . self::VERSION,
'protocol_version' => 1.1, 'protocol_version' => 1.1,
'redirected' => 0, 'redirected' => 0,
'redirects' => 10, 'redirects' => 10,
'follow_redirects' => true, 'follow_redirects' => true,
'blocking' => true, 'blocking' => true,
'type' => self::GET, 'type' => self::GET,
'filename' => false, 'filename' => false,
'auth' => false, 'auth' => false,
'proxy' => false, 'proxy' => false,
'cookies' => false, 'cookies' => false,
'max_bytes' => false, 'max_bytes' => false,
'idn' => true, 'idn' => true,
'hooks' => null, 'hooks' => null,
'transport' => null, 'transport' => null,
'verify' => Requests::get_certificate_path(), 'verify' => self::get_certificate_path(),
'verifyname' => true, 'verifyname' => true,
); );
if ($multirequest !== false) { if ($multirequest !== false) {
$defaults['complete'] = null; $defaults['complete'] = null;
@ -535,8 +535,8 @@ class Requests {
* @return string Default certificate path. * @return string Default certificate path.
*/ */
public static function get_certificate_path() { public static function get_certificate_path() {
if ( ! empty( Requests::$certificate_path ) ) { if (!empty(self::$certificate_path)) {
return Requests::$certificate_path; return self::$certificate_path;
} }
return dirname(__FILE__) . '/Requests/Transport/cacert.pem'; return dirname(__FILE__) . '/Requests/Transport/cacert.pem';
@ -547,8 +547,8 @@ class Requests {
* *
* @param string $path Certificate path, pointing to a PEM file. * @param string $path Certificate path, pointing to a PEM file.
*/ */
public static function set_certificate_path( $path ) { public static function set_certificate_path($path) {
Requests::$certificate_path = $path; self::$certificate_path = $path;
} }
/** /**
@ -595,16 +595,16 @@ class Requests {
} }
if ($options['idn'] !== false) { if ($options['idn'] !== false) {
$iri = new Requests_IRI($url); $iri = new Requests_IRI($url);
$iri->host = Requests_IDNAEncoder::encode($iri->ihost); $iri->host = Requests_IDNAEncoder::encode($iri->ihost);
$url = $iri->uri; $url = $iri->uri;
} }
// Massage the type to ensure we support it. // Massage the type to ensure we support it.
$type = strtoupper($type); $type = strtoupper($type);
if (!isset($options['data_format'])) { if (!isset($options['data_format'])) {
if (in_array($type, array(self::HEAD, self::GET, self::DELETE))) { if (in_array($type, array(self::HEAD, self::GET, self::DELETE), true)) {
$options['data_format'] = 'query'; $options['data_format'] = 'query';
} }
else { else {
@ -633,20 +633,23 @@ class Requests {
return $return; return $return;
} }
$return->raw = $headers; $return->raw = $headers;
$return->url = $url; $return->url = (string) $url;
$return->body = '';
if (!$options['filename']) { if (!$options['filename']) {
if (($pos = strpos($headers, "\r\n\r\n")) === false) { $pos = strpos($headers, "\r\n\r\n");
if ($pos === false) {
// Crap! // Crap!
throw new Requests_Exception('Missing header/body separator', 'requests.no_crlf_separator'); throw new Requests_Exception('Missing header/body separator', 'requests.no_crlf_separator');
} }
$headers = substr($return->raw, 0, $pos); $headers = substr($return->raw, 0, $pos);
$return->body = substr($return->raw, $pos + strlen("\n\r\n\r")); // Headers will always be separated from the body by two new lines - `\n\r\n\r`.
} $body = substr($return->raw, $pos + 4);
else { if (!empty($body)) {
$return->body = ''; $return->body = $body;
}
} }
// Pretend CRLF = LF for compatibility (RFC 2616, section 19.3) // Pretend CRLF = LF for compatibility (RFC 2616, section 19.3)
$headers = str_replace("\r\n", "\n", $headers); $headers = str_replace("\r\n", "\n", $headers);
@ -658,14 +661,14 @@ class Requests {
throw new Requests_Exception('Response could not be parsed', 'noversion', $headers); throw new Requests_Exception('Response could not be parsed', 'noversion', $headers);
} }
$return->protocol_version = (float) $matches[1]; $return->protocol_version = (float) $matches[1];
$return->status_code = (int) $matches[2]; $return->status_code = (int) $matches[2];
if ($return->status_code >= 200 && $return->status_code < 300) { if ($return->status_code >= 200 && $return->status_code < 300) {
$return->success = true; $return->success = true;
} }
foreach ($headers as $header) { foreach ($headers as $header) {
list($key, $value) = explode(':', $header, 2); list($key, $value) = explode(':', $header, 2);
$value = trim($value); $value = trim($value);
preg_replace('#(\s+)#i', ' ', $value); preg_replace('#(\s+)#i', ' ', $value);
$return->headers[$key] = $value; $return->headers[$key] = $value;
} }
@ -702,10 +705,10 @@ class Requests {
&$req_headers, &$req_headers,
&$req_data, &$req_data,
&$options, &$options,
$return $return,
); );
$options['hooks']->dispatch('requests.before_redirect', $hook_args); $options['hooks']->dispatch('requests.before_redirect', $hook_args);
$redirected = self::request($location, $req_headers, $req_data, $options['type'], $options); $redirected = self::request($location, $req_headers, $req_data, $options['type'], $options);
$redirected->history[] = $return; $redirected->history[] = $return;
return $redirected; return $redirected;
} }
@ -732,10 +735,10 @@ class Requests {
*/ */
public static function parse_multiple(&$response, $request) { public static function parse_multiple(&$response, $request) {
try { try {
$url = $request['url']; $url = $request['url'];
$headers = $request['headers']; $headers = $request['headers'];
$data = $request['data']; $data = $request['data'];
$options = $request['options']; $options = $request['options'];
$response = self::parse_response($response, $url, $headers, $data, $options); $response = self::parse_response($response, $url, $headers, $data, $options);
} }
catch (Requests_Exception $e) { catch (Requests_Exception $e) {
@ -755,8 +758,6 @@ class Requests {
return $data; return $data;
} }
$decoded = ''; $decoded = '';
$encoded = $data; $encoded = $data;
@ -774,8 +775,8 @@ class Requests {
} }
$chunk_length = strlen($matches[0]); $chunk_length = strlen($matches[0]);
$decoded .= substr($encoded, $chunk_length, $length); $decoded .= substr($encoded, $chunk_length, $length);
$encoded = substr($encoded, $chunk_length + $length + 2); $encoded = substr($encoded, $chunk_length + $length + 2);
if (trim($encoded) === '0' || empty($encoded)) { if (trim($encoded) === '0' || empty($encoded)) {
return $decoded; return $decoded;
@ -791,7 +792,7 @@ class Requests {
* Convert a key => value array to a 'key: value' array for headers * Convert a key => value array to a 'key: value' array for headers
* *
* @param array $array Dictionary of header values * @param array $array Dictionary of header values
* @return string[] List of headers * @return array List of headers
*/ */
public static function flatten($array) { public static function flatten($array) {
$return = array(); $return = array();
@ -807,7 +808,7 @@ class Requests {
* @codeCoverageIgnore * @codeCoverageIgnore
* @deprecated Misspelling of {@see Requests::flatten} * @deprecated Misspelling of {@see Requests::flatten}
* @param array $array Dictionary of header values * @param array $array Dictionary of header values
* @return string[] List of headers * @return array List of headers
*/ */
public static function flattern($array) { public static function flattern($array) {
return self::flatten($array); return self::flatten($array);
@ -828,17 +829,31 @@ class Requests {
return $data; return $data;
} }
if (function_exists('gzdecode') && ($decoded = @gzdecode($data)) !== false) { 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; return $decoded;
} }
elseif (function_exists('gzinflate') && ($decoded = @gzinflate($data)) !== false) {
return $decoded; if (function_exists('gzuncompress')) {
} $decoded = @gzuncompress($data);
elseif (($decoded = self::compatible_gzinflate($data)) !== false) { if ($decoded !== false) {
return $decoded; return $decoded;
} }
elseif (function_exists('gzuncompress') && ($decoded = @gzuncompress($data)) !== false) {
return $decoded;
} }
return $data; return $data;
@ -861,32 +876,32 @@ class Requests {
* @link https://secure.php.net/manual/en/function.gzinflate.php#70875 * @link https://secure.php.net/manual/en/function.gzinflate.php#70875
* @link https://secure.php.net/manual/en/function.gzinflate.php#77336 * @link https://secure.php.net/manual/en/function.gzinflate.php#77336
* *
* @param string $gzData String to decompress. * @param string $gz_data String to decompress.
* @return string|bool False on failure. * @return string|bool False on failure.
*/ */
public static function compatible_gzinflate($gzData) { public static function compatible_gzinflate($gz_data) {
// Compressed data might contain a full zlib header, if so strip it for // Compressed data might contain a full zlib header, if so strip it for
// gzinflate() // gzinflate()
if (substr($gzData, 0, 3) == "\x1f\x8b\x08") { if (substr($gz_data, 0, 3) === "\x1f\x8b\x08") {
$i = 10; $i = 10;
$flg = ord(substr($gzData, 3, 1)); $flg = ord(substr($gz_data, 3, 1));
if ($flg > 0) { if ($flg > 0) {
if ($flg & 4) { if ($flg & 4) {
list($xlen) = unpack('v', substr($gzData, $i, 2)); list($xlen) = unpack('v', substr($gz_data, $i, 2));
$i = $i + 2 + $xlen; $i += 2 + $xlen;
} }
if ($flg & 8) { if ($flg & 8) {
$i = strpos($gzData, "\0", $i) + 1; $i = strpos($gz_data, "\0", $i) + 1;
} }
if ($flg & 16) { if ($flg & 16) {
$i = strpos($gzData, "\0", $i) + 1; $i = strpos($gz_data, "\0", $i) + 1;
} }
if ($flg & 2) { if ($flg & 2) {
$i = $i + 2; $i += 2;
} }
} }
$decompressed = self::compatible_gzinflate(substr($gzData, $i)); $decompressed = self::compatible_gzinflate(substr($gz_data, $i));
if (false !== $decompressed) { if ($decompressed !== false) {
return $decompressed; return $decompressed;
} }
} }
@ -902,57 +917,61 @@ class Requests {
$huffman_encoded = false; $huffman_encoded = false;
// low nibble of first byte should be 0x08 // low nibble of first byte should be 0x08
list(, $first_nibble) = unpack('h', $gzData); list(, $first_nibble) = unpack('h', $gz_data);
// First 2 bytes should be divisible by 0x1F // First 2 bytes should be divisible by 0x1F
list(, $first_two_bytes) = unpack('n', $gzData); list(, $first_two_bytes) = unpack('n', $gz_data);
if (0x08 == $first_nibble && 0 == ($first_two_bytes % 0x1F)) { if ($first_nibble === 0x08 && ($first_two_bytes % 0x1F) === 0) {
$huffman_encoded = true; $huffman_encoded = true;
} }
if ($huffman_encoded) { if ($huffman_encoded) {
if (false !== ($decompressed = @gzinflate(substr($gzData, 2)))) { $decompressed = @gzinflate(substr($gz_data, 2));
if ($decompressed !== false) {
return $decompressed; return $decompressed;
} }
} }
if ("\x50\x4b\x03\x04" == substr($gzData, 0, 4)) { if (substr($gz_data, 0, 4) === "\x50\x4b\x03\x04") {
// ZIP file format header // ZIP file format header
// Offset 6: 2 bytes, General-purpose field // Offset 6: 2 bytes, General-purpose field
// Offset 26: 2 bytes, filename length // Offset 26: 2 bytes, filename length
// Offset 28: 2 bytes, optional field length // Offset 28: 2 bytes, optional field length
// Offset 30: Filename field, followed by optional field, followed // Offset 30: Filename field, followed by optional field, followed
// immediately by data // immediately by data
list(, $general_purpose_flag) = unpack('v', substr($gzData, 6, 2)); 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 // If the file has been compressed on the fly, 0x08 bit is set of
// the general purpose field. We can use this to differentiate // the general purpose field. We can use this to differentiate
// between a compressed document, and a ZIP file // between a compressed document, and a ZIP file
$zip_compressed_on_the_fly = (0x08 == (0x08 & $general_purpose_flag)); $zip_compressed_on_the_fly = ((0x08 & $general_purpose_flag) === 0x08);
if (!$zip_compressed_on_the_fly) { if (!$zip_compressed_on_the_fly) {
// Don't attempt to decode a compressed zip file // Don't attempt to decode a compressed zip file
return $gzData; return $gz_data;
} }
// Determine the first byte of data, based on the above ZIP header // Determine the first byte of data, based on the above ZIP header
// offsets: // offsets:
$first_file_start = array_sum(unpack('v2', substr($gzData, 26, 4))); $first_file_start = array_sum(unpack('v2', substr($gz_data, 26, 4)));
if (false !== ($decompressed = @gzinflate(substr($gzData, 30 + $first_file_start)))) { $decompressed = @gzinflate(substr($gz_data, 30 + $first_file_start));
if ($decompressed !== false) {
return $decompressed; return $decompressed;
} }
return false; return false;
} }
// Finally fall back to straight gzinflate // Finally fall back to straight gzinflate
if (false !== ($decompressed = @gzinflate($gzData))) { $decompressed = @gzinflate($gz_data);
if ($decompressed !== false) {
return $decompressed; return $decompressed;
} }
// Fallback for all above failing, not expected, but included for // Fallback for all above failing, not expected, but included for
// debugging and preventing regressions and to track stats // debugging and preventing regressions and to track stats
if (false !== ($decompressed = @gzinflate(substr($gzData, 2)))) { $decompressed = @gzinflate(substr($gz_data, 2));
if ($decompressed !== false) {
return $decompressed; return $decompressed;
} }

View File

@ -13,7 +13,7 @@
* *
* @global string $wp_version * @global string $wp_version
*/ */
$wp_version = '5.8-alpha-50841'; $wp_version = '5.8-alpha-50842';
/** /**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.