Changeset 54997
- Timestamp:
- 12/15/2022 09:30:26 PM (20 months ago)
- Location:
- trunk
- Files:
-
- 74 added
- 20 deleted
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/includes/update-core.php
r54891 r54997 867 867 868 868 /** 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 869 959 * Stores new files in wp-content to copy 870 960 * … … 950 1040 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. 951 1041 * @global array $_old_files 1042 952 1043 * @global array $_new_bundled_files 953 1044 * @global wpdb $wpdb WordPress database abstraction object. … … 961 1052 */ 962 1053 function update_core( $from, $to ) { 963 global $wp_filesystem, $_old_files, $_ new_bundled_files, $wpdb;1054 global $wp_filesystem, $_old_files, $_new_bundled_files, $wpdb; 964 1055 965 1056 set_time_limit( 300 ); 1057 1058 1059 1060 1061 1062 1063 1064 966 1065 967 1066 /** … … 1480 1579 1481 1580 /** 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1482 1623 * Redirect to the About WordPress page after a successful upgrade. 1483 1624 * -
trunk/src/wp-includes/class-requests.php
r52328 r54997 8 8 * 9 9 * @package Requests 10 11 10 12 */ 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 11 34 12 35 /** … … 18 41 * 19 42 * @package Requests 43 44 45 20 46 */ 21 class Requests { 22 /** 23 * POST method 24 * 25 * @var string 26 */ 27 const POST = 'POST'; 47 class Requests extends WpOrg\Requests\Requests { 28 48 29 49 /** 30 * PUT method50 * 31 51 * 32 * @var string 33 */ 34 const PUT = 'PUT'; 35 36 /** 37 * GET method 38 * 39 * @var string 40 */ 41 const GET = 'GET'; 42 43 /** 44 * HEAD method 45 * 46 * @var string 47 */ 48 const HEAD = 'HEAD'; 49 50 /** 51 * DELETE method 52 * 53 * @var string 54 */ 55 const DELETE = 'DELETE'; 56 57 /** 58 * OPTIONS method 59 * 60 * @var string 61 */ 62 const OPTIONS = 'OPTIONS'; 63 64 /** 65 * TRACE method 66 * 67 * @var string 68 */ 69 const TRACE = 'TRACE'; 70 71 /** 72 * PATCH method 73 * 74 * @link https://tools.ietf.org/html/rfc5789 75 * @var string 76 */ 77 const PATCH = 'PATCH'; 78 79 /** 80 * Default size of buffer size to read streams 81 * 82 * @var integer 83 */ 84 const BUFFER_SIZE = 1160; 85 86 /** 87 * Current version of Requests 88 * 89 * @var string 90 */ 91 const VERSION = '1.8.1'; 92 93 /** 94 * Registered transport classes 95 * 96 * @var array 97 */ 98 protected static $transports = array(); 99 100 /** 101 * Selected transport name 102 * 103 * Use {@see get_transport()} instead 104 * 105 * @var array 106 */ 107 public static $transport = array(); 108 109 /** 110 * Default certificate path. 111 * 112 * @see Requests::get_certificate_path() 113 * @see Requests::set_certificate_path() 114 * 115 * @var string 116 */ 117 protected static $certificate_path; 118 119 /** 120 * This is a static class, do not instantiate it 121 * 122 * @codeCoverageIgnore 123 */ 124 private function __construct() {} 125 126 /** 127 * Autoloader for Requests 128 * 129 * Register this with {@see register_autoloader()} if you'd like to avoid 130 * having to create your own. 131 * 132 * (You can also use `spl_autoload_register` directly if you'd prefer.) 52 * @deprecated 6.2.0 Use the `WpOrg\Requests\Autoload::load()` method instead. 133 53 * 134 54 * @codeCoverageIgnore … … 137 57 */ 138 58 public static function autoloader($class) { 139 // Check that the class starts with "Requests" 140 if (strpos($class, 'Requests') !== 0) { 141 return; 59 if (class_exists('WpOrg\Requests\Autoload') === false) { 60 require_once __DIR__ . '/Requests/src/Autoload.php'; 142 61 } 143 62 144 $file = str_replace('_', '/', $class); 145 if (file_exists(dirname(__FILE__) . '/' . $file . '.php')) { 146 require_once dirname(__FILE__) . '/' . $file . '.php'; 147 } 63 return WpOrg\Requests\Autoload::load($class); 148 64 } 149 65 … … 151 67 * Register the built-in autoloader 152 68 * 69 70 71 153 72 * @codeCoverageIgnore 154 73 */ 155 74 public static function register_autoloader() { 156 spl_autoload_register(array('Requests', 'autoloader')); 157 } 158 159 /** 160 * Register a transport 161 * 162 * @param string $transport Transport class to add, must support the Requests_Transport interface 163 */ 164 public static function add_transport($transport) { 165 if (empty(self::$transports)) { 166 self::$transports = array( 167 'Requests_Transport_cURL', 168 'Requests_Transport_fsockopen', 169 ); 170 } 171 172 self::$transports = array_merge(self::$transports, array($transport)); 173 } 174 175 /** 176 * Get a working transport 177 * 178 * @throws Requests_Exception If no valid transport is found (`notransport`) 179 * @return Requests_Transport 180 */ 181 protected static function get_transport($capabilities = array()) { 182 // Caching code, don't bother testing coverage 183 // @codeCoverageIgnoreStart 184 // array of capabilities as a string to be used as an array key 185 ksort($capabilities); 186 $cap_string = serialize($capabilities); 187 188 // Don't search for a transport if it's already been done for these $capabilities 189 if (isset(self::$transport[$cap_string]) && self::$transport[$cap_string] !== null) { 190 $class = self::$transport[$cap_string]; 191 return new $class(); 192 } 193 // @codeCoverageIgnoreEnd 194 195 if (empty(self::$transports)) { 196 self::$transports = array( 197 'Requests_Transport_cURL', 198 'Requests_Transport_fsockopen', 199 ); 200 } 201 202 // Find us a working transport 203 foreach (self::$transports as $class) { 204 if (!class_exists($class)) { 205 continue; 206 } 207 208 $result = call_user_func(array($class, 'test'), $capabilities); 209 if ($result) { 210 self::$transport[$cap_string] = $class; 211 break; 212 } 213 } 214 if (self::$transport[$cap_string] === null) { 215 throw new Requests_Exception('No working transports found', 'notransport', self::$transports); 216 } 217 218 $class = self::$transport[$cap_string]; 219 return new $class(); 220 } 221 222 /**#@+ 223 * @see request() 224 * @param string $url 225 * @param array $headers 226 * @param array $options 227 * @return Requests_Response 228 */ 229 /** 230 * Send a GET request 231 */ 232 public static function get($url, $headers = array(), $options = array()) { 233 return self::request($url, $headers, null, self::GET, $options); 234 } 235 236 /** 237 * Send a HEAD request 238 */ 239 public static function head($url, $headers = array(), $options = array()) { 240 return self::request($url, $headers, null, self::HEAD, $options); 241 } 242 243 /** 244 * Send a DELETE request 245 */ 246 public static function delete($url, $headers = array(), $options = array()) { 247 return self::request($url, $headers, null, self::DELETE, $options); 248 } 249 250 /** 251 * Send a TRACE request 252 */ 253 public static function trace($url, $headers = array(), $options = array()) { 254 return self::request($url, $headers, null, self::TRACE, $options); 255 } 256 /**#@-*/ 257 258 /**#@+ 259 * @see request() 260 * @param string $url 261 * @param array $headers 262 * @param array $data 263 * @param array $options 264 * @return Requests_Response 265 */ 266 /** 267 * Send a POST request 268 */ 269 public static function post($url, $headers = array(), $data = array(), $options = array()) { 270 return self::request($url, $headers, $data, self::POST, $options); 271 } 272 /** 273 * Send a PUT request 274 */ 275 public static function put($url, $headers = array(), $data = array(), $options = array()) { 276 return self::request($url, $headers, $data, self::PUT, $options); 277 } 278 279 /** 280 * Send an OPTIONS request 281 */ 282 public static function options($url, $headers = array(), $data = array(), $options = array()) { 283 return self::request($url, $headers, $data, self::OPTIONS, $options); 284 } 285 286 /** 287 * Send a PATCH request 288 * 289 * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the 290 * specification recommends that should send an ETag 291 * 292 * @link https://tools.ietf.org/html/rfc5789 293 */ 294 public static function patch($url, $headers, $data = array(), $options = array()) { 295 return self::request($url, $headers, $data, self::PATCH, $options); 296 } 297 /**#@-*/ 298 299 /** 300 * Main interface for HTTP requests 301 * 302 * This method initiates a request and sends it via a transport before 303 * parsing. 304 * 305 * The `$options` parameter takes an associative array with the following 306 * options: 307 * 308 * - `timeout`: How long should we wait for a response? 309 * Note: for cURL, a minimum of 1 second applies, as DNS resolution 310 * operates at second-resolution only. 311 * (float, seconds with a millisecond precision, default: 10, example: 0.01) 312 * - `connect_timeout`: How long should we wait while trying to connect? 313 * (float, seconds with a millisecond precision, default: 10, example: 0.01) 314 * - `useragent`: Useragent to send to the server 315 * (string, default: php-requests/$version) 316 * - `follow_redirects`: Should we follow 3xx redirects? 317 * (boolean, default: true) 318 * - `redirects`: How many times should we redirect before erroring? 319 * (integer, default: 10) 320 * - `blocking`: Should we block processing on this request? 321 * (boolean, default: true) 322 * - `filename`: File to stream the body to instead. 323 * (string|boolean, default: false) 324 * - `auth`: Authentication handler or array of user/password details to use 325 * for Basic authentication 326 * (Requests_Auth|array|boolean, default: false) 327 * - `proxy`: Proxy details to use for proxy by-passing and authentication 328 * (Requests_Proxy|array|string|boolean, default: false) 329 * - `max_bytes`: Limit for the response body size. 330 * (integer|boolean, default: false) 331 * - `idn`: Enable IDN parsing 332 * (boolean, default: true) 333 * - `transport`: Custom transport. Either a class name, or a 334 * transport object. Defaults to the first working transport from 335 * {@see getTransport()} 336 * (string|Requests_Transport, default: {@see getTransport()}) 337 * - `hooks`: Hooks handler. 338 * (Requests_Hooker, default: new Requests_Hooks()) 339 * - `verify`: Should we verify SSL certificates? Allows passing in a custom 340 * certificate file as a string. (Using true uses the system-wide root 341 * certificate store instead, but this may have different behaviour 342 * across transports.) 343 * (string|boolean, default: library/Requests/Transport/cacert.pem) 344 * - `verifyname`: Should we verify the common name in the SSL certificate? 345 * (boolean, default: true) 346 * - `data_format`: How should we send the `$data` parameter? 347 * (string, one of 'query' or 'body', default: 'query' for 348 * HEAD/GET/DELETE, 'body' for POST/PUT/OPTIONS/PATCH) 349 * 350 * @throws Requests_Exception On invalid URLs (`nonhttp`) 351 * 352 * @param string $url URL to request 353 * @param array $headers Extra headers to send with the request 354 * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests 355 * @param string $type HTTP request type (use Requests constants) 356 * @param array $options Options for the request (see description for more information) 357 * @return Requests_Response 358 */ 359 public static function request($url, $headers = array(), $data = array(), $type = self::GET, $options = array()) { 360 if (empty($options['type'])) { 361 $options['type'] = $type; 362 } 363 $options = array_merge(self::get_default_options(), $options); 364 365 self::set_defaults($url, $headers, $data, $type, $options); 366 367 $options['hooks']->dispatch('requests.before_request', array(&$url, &$headers, &$data, &$type, &$options)); 368 369 if (!empty($options['transport'])) { 370 $transport = $options['transport']; 371 372 if (is_string($options['transport'])) { 373 $transport = new $transport(); 374 } 375 } 376 else { 377 $need_ssl = (stripos($url, 'https://') === 0); 378 $capabilities = array('ssl' => $need_ssl); 379 $transport = self::get_transport($capabilities); 380 } 381 $response = $transport->request($url, $headers, $data, $options); 382 383 $options['hooks']->dispatch('requests.before_parse', array(&$response, $url, $headers, $data, $type, $options)); 384 385 return self::parse_response($response, $url, $headers, $data, $options); 386 } 387 388 /** 389 * Send multiple HTTP requests simultaneously 390 * 391 * The `$requests` parameter takes an associative or indexed array of 392 * request fields. The key of each request can be used to match up the 393 * request with the returned data, or with the request passed into your 394 * `multiple.request.complete` callback. 395 * 396 * The request fields value is an associative array with the following keys: 397 * 398 * - `url`: Request URL Same as the `$url` parameter to 399 * {@see Requests::request} 400 * (string, required) 401 * - `headers`: Associative array of header fields. Same as the `$headers` 402 * parameter to {@see Requests::request} 403 * (array, default: `array()`) 404 * - `data`: Associative array of data fields or a string. Same as the 405 * `$data` parameter to {@see Requests::request} 406 * (array|string, default: `array()`) 407 * - `type`: HTTP request type (use Requests constants). Same as the `$type` 408 * parameter to {@see Requests::request} 409 * (string, default: `Requests::GET`) 410 * - `cookies`: Associative array of cookie name to value, or cookie jar. 411 * (array|Requests_Cookie_Jar) 412 * 413 * If the `$options` parameter is specified, individual requests will 414 * inherit options from it. This can be used to use a single hooking system, 415 * or set all the types to `Requests::POST`, for example. 416 * 417 * In addition, the `$options` parameter takes the following global options: 418 * 419 * - `complete`: A callback for when a request is complete. Takes two 420 * parameters, a Requests_Response/Requests_Exception reference, and the 421 * ID from the request array (Note: this can also be overridden on a 422 * per-request basis, although that's a little silly) 423 * (callback) 424 * 425 * @param array $requests Requests data (see description for more information) 426 * @param array $options Global and default options (see {@see Requests::request}) 427 * @return array Responses (either Requests_Response or a Requests_Exception object) 428 */ 429 public static function request_multiple($requests, $options = array()) { 430 $options = array_merge(self::get_default_options(true), $options); 431 432 if (!empty($options['hooks'])) { 433 $options['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple')); 434 if (!empty($options['complete'])) { 435 $options['hooks']->register('multiple.request.complete', $options['complete']); 436 } 437 } 438 439 foreach ($requests as $id => &$request) { 440 if (!isset($request['headers'])) { 441 $request['headers'] = array(); 442 } 443 if (!isset($request['data'])) { 444 $request['data'] = array(); 445 } 446 if (!isset($request['type'])) { 447 $request['type'] = self::GET; 448 } 449 if (!isset($request['options'])) { 450 $request['options'] = $options; 451 $request['options']['type'] = $request['type']; 452 } 453 else { 454 if (empty($request['options']['type'])) { 455 $request['options']['type'] = $request['type']; 456 } 457 $request['options'] = array_merge($options, $request['options']); 458 } 459 460 self::set_defaults($request['url'], $request['headers'], $request['data'], $request['type'], $request['options']); 461 462 // Ensure we only hook in once 463 if ($request['options']['hooks'] !== $options['hooks']) { 464 $request['options']['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple')); 465 if (!empty($request['options']['complete'])) { 466 $request['options']['hooks']->register('multiple.request.complete', $request['options']['complete']); 467 } 468 } 469 } 470 unset($request); 471 472 if (!empty($options['transport'])) { 473 $transport = $options['transport']; 474 475 if (is_string($options['transport'])) { 476 $transport = new $transport(); 477 } 478 } 479 else { 480 $transport = self::get_transport(); 481 } 482 $responses = $transport->request_multiple($requests, $options); 483 484 foreach ($responses as $id => &$response) { 485 // If our hook got messed with somehow, ensure we end up with the 486 // correct response 487 if (is_string($response)) { 488 $request = $requests[$id]; 489 self::parse_multiple($response, $request); 490 $request['options']['hooks']->dispatch('multiple.request.complete', array(&$response, $id)); 491 } 492 } 493 494 return $responses; 495 } 496 497 /** 498 * Get the default options 499 * 500 * @see Requests::request() for values returned by this method 501 * @param boolean $multirequest Is this a multirequest? 502 * @return array Default option values 503 */ 504 protected static function get_default_options($multirequest = false) { 505 $defaults = array( 506 'timeout' => 10, 507 'connect_timeout' => 10, 508 'useragent' => 'php-requests/' . self::VERSION, 509 'protocol_version' => 1.1, 510 'redirected' => 0, 511 'redirects' => 10, 512 'follow_redirects' => true, 513 'blocking' => true, 514 'type' => self::GET, 515 'filename' => false, 516 'auth' => false, 517 'proxy' => false, 518 'cookies' => false, 519 'max_bytes' => false, 520 'idn' => true, 521 'hooks' => null, 522 'transport' => null, 523 'verify' => self::get_certificate_path(), 524 'verifyname' => true, 525 ); 526 if ($multirequest !== false) { 527 $defaults['complete'] = null; 528 } 529 return $defaults; 530 } 531 532 /** 533 * Get default certificate path. 534 * 535 * @return string Default certificate path. 536 */ 537 public static function get_certificate_path() { 538 if (!empty(self::$certificate_path)) { 539 return self::$certificate_path; 540 } 541 542 return dirname(__FILE__) . '/Requests/Transport/cacert.pem'; 543 } 544 545 /** 546 * Set default certificate path. 547 * 548 * @param string $path Certificate path, pointing to a PEM file. 549 */ 550 public static function set_certificate_path($path) { 551 self::$certificate_path = $path; 552 } 553 554 /** 555 * Set the default values 556 * 557 * @param string $url URL to request 558 * @param array $headers Extra headers to send with the request 559 * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests 560 * @param string $type HTTP request type 561 * @param array $options Options for the request 562 * @return array $options 563 */ 564 protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) { 565 if (!preg_match('/^http(s)?:\/\//i', $url, $matches)) { 566 throw new Requests_Exception('Only HTTP(S) requests are handled.', 'nonhttp', $url); 567 } 568 569 if (empty($options['hooks'])) { 570 $options['hooks'] = new Requests_Hooks(); 571 } 572 573 if (is_array($options['auth'])) { 574 $options['auth'] = new Requests_Auth_Basic($options['auth']); 575 } 576 if ($options['auth'] !== false) { 577 $options['auth']->register($options['hooks']); 578 } 579 580 if (is_string($options['proxy']) || is_array($options['proxy'])) { 581 $options['proxy'] = new Requests_Proxy_HTTP($options['proxy']); 582 } 583 if ($options['proxy'] !== false) { 584 $options['proxy']->register($options['hooks']); 585 } 586 587 if (is_array($options['cookies'])) { 588 $options['cookies'] = new Requests_Cookie_Jar($options['cookies']); 589 } 590 elseif (empty($options['cookies'])) { 591 $options['cookies'] = new Requests_Cookie_Jar(); 592 } 593 if ($options['cookies'] !== false) { 594 $options['cookies']->register($options['hooks']); 595 } 596 597 if ($options['idn'] !== false) { 598 $iri = new Requests_IRI($url); 599 $iri->host = Requests_IDNAEncoder::encode($iri->ihost); 600 $url = $iri->uri; 601 } 602 603 // Massage the type to ensure we support it. 604 $type = strtoupper($type); 605 606 if (!isset($options['data_format'])) { 607 if (in_array($type, array(self::HEAD, self::GET, self::DELETE), true)) { 608 $options['data_format'] = 'query'; 609 } 610 else { 611 $options['data_format'] = 'body'; 612 } 613 } 614 } 615 616 /** 617 * HTTP response parser 618 * 619 * @throws Requests_Exception On missing head/body separator (`requests.no_crlf_separator`) 620 * @throws Requests_Exception On missing head/body separator (`noversion`) 621 * @throws Requests_Exception On missing head/body separator (`toomanyredirects`) 622 * 623 * @param string $headers Full response text including headers and body 624 * @param string $url Original request URL 625 * @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects 626 * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects 627 * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects 628 * @return Requests_Response 629 */ 630 protected static function parse_response($headers, $url, $req_headers, $req_data, $options) { 631 $return = new Requests_Response(); 632 if (!$options['blocking']) { 633 return $return; 634 } 635 636 $return->raw = $headers; 637 $return->url = (string) $url; 638 $return->body = ''; 639 640 if (!$options['filename']) { 641 $pos = strpos($headers, "\r\n\r\n"); 642 if ($pos === false) { 643 // Crap! 644 throw new Requests_Exception('Missing header/body separator', 'requests.no_crlf_separator'); 645 } 646 647 $headers = substr($return->raw, 0, $pos); 648 // Headers will always be separated from the body by two new lines - `\n\r\n\r`. 649 $body = substr($return->raw, $pos + 4); 650 if (!empty($body)) { 651 $return->body = $body; 652 } 653 } 654 // Pretend CRLF = LF for compatibility (RFC 2616, section 19.3) 655 $headers = str_replace("\r\n", "\n", $headers); 656 // Unfold headers (replace [CRLF] 1*( SP | HT ) with SP) as per RFC 2616 (section 2.2) 657 $headers = preg_replace('/\n[ \t]/', ' ', $headers); 658 $headers = explode("\n", $headers); 659 preg_match('#^HTTP/(1\.\d)[ \t]+(\d+)#i', array_shift($headers), $matches); 660 if (empty($matches)) { 661 throw new Requests_Exception('Response could not be parsed', 'noversion', $headers); 662 } 663 $return->protocol_version = (float) $matches[1]; 664 $return->status_code = (int) $matches[2]; 665 if ($return->status_code >= 200 && $return->status_code < 300) { 666 $return->success = true; 667 } 668 669 foreach ($headers as $header) { 670 list($key, $value) = explode(':', $header, 2); 671 $value = trim($value); 672 preg_replace('#(\s+)#i', ' ', $value); 673 $return->headers[$key] = $value; 674 } 675 if (isset($return->headers['transfer-encoding'])) { 676 $return->body = self::decode_chunked($return->body); 677 unset($return->headers['transfer-encoding']); 678 } 679 if (isset($return->headers['content-encoding'])) { 680 $return->body = self::decompress($return->body); 681 } 682 683 //fsockopen and cURL compatibility 684 if (isset($return->headers['connection'])) { 685 unset($return->headers['connection']); 686 } 687 688 $options['hooks']->dispatch('requests.before_redirect_check', array(&$return, $req_headers, $req_data, $options)); 689 690 if ($return->is_redirect() && $options['follow_redirects'] === true) { 691 if (isset($return->headers['location']) && $options['redirected'] < $options['redirects']) { 692 if ($return->status_code === 303) { 693 $options['type'] = self::GET; 694 } 695 $options['redirected']++; 696 $location = $return->headers['location']; 697 if (strpos($location, 'http://') !== 0 && strpos($location, 'https://') !== 0) { 698 // relative redirect, for compatibility make it absolute 699 $location = Requests_IRI::absolutize($url, $location); 700 $location = $location->uri; 701 } 702 703 $hook_args = array( 704 &$location, 705 &$req_headers, 706 &$req_data, 707 &$options, 708 $return, 709 ); 710 $options['hooks']->dispatch('requests.before_redirect', $hook_args); 711 $redirected = self::request($location, $req_headers, $req_data, $options['type'], $options); 712 $redirected->history[] = $return; 713 return $redirected; 714 } 715 elseif ($options['redirected'] >= $options['redirects']) { 716 throw new Requests_Exception('Too many redirects', 'toomanyredirects', $return); 717 } 718 } 719 720 $return->redirects = $options['redirected']; 721 722 $options['hooks']->dispatch('requests.after_request', array(&$return, $req_headers, $req_data, $options)); 723 return $return; 724 } 725 726 /** 727 * Callback for `transport.internal.parse_response` 728 * 729 * Internal use only. Converts a raw HTTP response to a Requests_Response 730 * while still executing a multiple request. 731 * 732 * @param string $response Full response text including headers and body (will be overwritten with Response instance) 733 * @param array $request Request data as passed into {@see Requests::request_multiple()} 734 * @return null `$response` is either set to a Requests_Response instance, or a Requests_Exception object 735 */ 736 public static function parse_multiple(&$response, $request) { 737 try { 738 $url = $request['url']; 739 $headers = $request['headers']; 740 $data = $request['data']; 741 $options = $request['options']; 742 $response = self::parse_response($response, $url, $headers, $data, $options); 743 } 744 catch (Requests_Exception $e) { 745 $response = $e; 746 } 747 } 748 749 /** 750 * Decoded a chunked body as per RFC 2616 751 * 752 * @see https://tools.ietf.org/html/rfc2616#section-3.6.1 753 * @param string $data Chunked body 754 * @return string Decoded body 755 */ 756 protected static function decode_chunked($data) { 757 if (!preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', trim($data))) { 758 return $data; 759 } 760 761 $decoded = ''; 762 $encoded = $data; 763 764 while (true) { 765 $is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', $encoded, $matches); 766 if (!$is_chunked) { 767 // Looks like it's not chunked after all 768 return $data; 769 } 770 771 $length = hexdec(trim($matches[1])); 772 if ($length === 0) { 773 // Ignore trailer headers 774 return $decoded; 775 } 776 777 $chunk_length = strlen($matches[0]); 778 $decoded .= substr($encoded, $chunk_length, $length); 779 $encoded = substr($encoded, $chunk_length + $length + 2); 780 781 if (trim($encoded) === '0' || empty($encoded)) { 782 return $decoded; 783 } 784 } 785 786 // We'll never actually get down here 787 // @codeCoverageIgnoreStart 788 } 789 // @codeCoverageIgnoreEnd 790 791 /** 792 * Convert a key => value array to a 'key: value' array for headers 793 * 794 * @param array $array Dictionary of header values 795 * @return array List of headers 796 */ 797 public static function flatten($array) { 798 $return = array(); 799 foreach ($array as $key => $value) { 800 $return[] = sprintf('%s: %s', $key, $value); 801 } 802 return $return; 803 } 804 805 /** 806 * Convert a key => value array to a 'key: value' array for headers 807 * 808 * @codeCoverageIgnore 809 * @deprecated Misspelling of {@see Requests::flatten} 810 * @param array $array Dictionary of header values 811 * @return array List of headers 812 */ 813 public static function flattern($array) { 814 return self::flatten($array); 815 } 816 817 /** 818 * Decompress an encoded body 819 * 820 * Implements gzip, compress and deflate. Guesses which it is by attempting 821 * to decode. 822 * 823 * @param string $data Compressed data in one of the above formats 824 * @return string Decompressed string 825 */ 826 public static function decompress($data) { 827 if (substr($data, 0, 2) !== "\x1f\x8b" && substr($data, 0, 2) !== "\x78\x9c") { 828 // Not actually compressed. Probably cURL ruining this for us. 829 return $data; 830 } 831 832 if (function_exists('gzdecode')) { 833 // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.gzdecodeFound -- Wrapped in function_exists() for PHP 5.2. 834 $decoded = @gzdecode($data); 835 if ($decoded !== false) { 836 return $decoded; 837 } 838 } 839 840 if (function_exists('gzinflate')) { 841 $decoded = @gzinflate($data); 842 if ($decoded !== false) { 843 return $decoded; 844 } 845 } 846 847 $decoded = self::compatible_gzinflate($data); 848 if ($decoded !== false) { 849 return $decoded; 850 } 851 852 if (function_exists('gzuncompress')) { 853 $decoded = @gzuncompress($data); 854 if ($decoded !== false) { 855 return $decoded; 856 } 857 } 858 859 return $data; 860 } 861 862 /** 863 * Decompression of deflated string while staying compatible with the majority of servers. 864 * 865 * Certain Servers will return deflated data with headers which PHP's gzinflate() 866 * function cannot handle out of the box. The following function has been created from 867 * various snippets on the gzinflate() PHP documentation. 868 * 869 * Warning: Magic numbers within. Due to the potential different formats that the compressed 870 * data may be returned in, some "magic offsets" are needed to ensure proper decompression 871 * takes place. For a simple progmatic way to determine the magic offset in use, see: 872 * https://core.trac.wordpress.org/ticket/18273 873 * 874 * @since 2.8.1 875 * @link https://core.trac.wordpress.org/ticket/18273 876 * @link https://secure.php.net/manual/en/function.gzinflate.php#70875 877 * @link https://secure.php.net/manual/en/function.gzinflate.php#77336 878 * 879 * @param string $gz_data String to decompress. 880 * @return string|bool False on failure. 881 */ 882 public static function compatible_gzinflate($gz_data) { 883 // Compressed data might contain a full zlib header, if so strip it for 884 // gzinflate() 885 if (substr($gz_data, 0, 3) === "\x1f\x8b\x08") { 886 $i = 10; 887 $flg = ord(substr($gz_data, 3, 1)); 888 if ($flg > 0) { 889 if ($flg & 4) { 890 list($xlen) = unpack('v', substr($gz_data, $i, 2)); 891 $i += 2 + $xlen; 892 } 893 if ($flg & 8) { 894 $i = strpos($gz_data, "\0", $i) + 1; 895 } 896 if ($flg & 16) { 897 $i = strpos($gz_data, "\0", $i) + 1; 898 } 899 if ($flg & 2) { 900 $i += 2; 901 } 902 } 903 $decompressed = self::compatible_gzinflate(substr($gz_data, $i)); 904 if ($decompressed !== false) { 905 return $decompressed; 906 } 907 } 908 909 // If the data is Huffman Encoded, we must first strip the leading 2 910 // byte Huffman marker for gzinflate() 911 // The response is Huffman coded by many compressors such as 912 // java.util.zip.Deflater, Ruby’s Zlib::Deflate, and .NET's 913 // System.IO.Compression.DeflateStream. 914 // 915 // See https://decompres.blogspot.com/ for a quick explanation of this 916 // data type 917 $huffman_encoded = false; 918 919 // low nibble of first byte should be 0x08 920 list(, $first_nibble) = unpack('h', $gz_data); 921 922 // First 2 bytes should be divisible by 0x1F 923 list(, $first_two_bytes) = unpack('n', $gz_data); 924 925 if ($first_nibble === 0x08 && ($first_two_bytes % 0x1F) === 0) { 926 $huffman_encoded = true; 927 } 928 929 if ($huffman_encoded) { 930 $decompressed = @gzinflate(substr($gz_data, 2)); 931 if ($decompressed !== false) { 932 return $decompressed; 933 } 934 } 935 936 if (substr($gz_data, 0, 4) === "\x50\x4b\x03\x04") { 937 // ZIP file format header 938 // Offset 6: 2 bytes, General-purpose field 939 // Offset 26: 2 bytes, filename length 940 // Offset 28: 2 bytes, optional field length 941 // Offset 30: Filename field, followed by optional field, followed 942 // immediately by data 943 list(, $general_purpose_flag) = unpack('v', substr($gz_data, 6, 2)); 944 945 // If the file has been compressed on the fly, 0x08 bit is set of 946 // the general purpose field. We can use this to differentiate 947 // between a compressed document, and a ZIP file 948 $zip_compressed_on_the_fly = ((0x08 & $general_purpose_flag) === 0x08); 949 950 if (!$zip_compressed_on_the_fly) { 951 // Don't attempt to decode a compressed zip file 952 return $gz_data; 953 } 954 955 // Determine the first byte of data, based on the above ZIP header 956 // offsets: 957 $first_file_start = array_sum(unpack('v2', substr($gz_data, 26, 4))); 958 $decompressed = @gzinflate(substr($gz_data, 30 + $first_file_start)); 959 if ($decompressed !== false) { 960 return $decompressed; 961 } 962 return false; 963 } 964 965 // Finally fall back to straight gzinflate 966 $decompressed = @gzinflate($gz_data); 967 if ($decompressed !== false) { 968 return $decompressed; 969 } 970 971 // Fallback for all above failing, not expected, but included for 972 // debugging and preventing regressions and to track stats 973 $decompressed = @gzinflate(substr($gz_data, 2)); 974 if ($decompressed !== false) { 975 return $decompressed; 976 } 977 978 return false; 979 } 980 981 public static function match_domain($host, $reference) { 982 // Check for a direct match 983 if ($host === $reference) { 984 return true; 985 } 986 987 // Calculate the valid wildcard match if the host is not an IP address 988 // Also validates that the host has 3 parts or more, as per Firefox's 989 // ruleset. 990 $parts = explode('.', $host); 991 if (ip2long($host) === false && count($parts) >= 3) { 992 $parts[0] = '*'; 993 $wildcard = implode('.', $parts); 994 if ($wildcard === $reference) { 995 return true; 996 } 997 } 998 999 return false; 75 require_once __DIR__ . '/Requests/src/Autoload.php'; 76 WpOrg\Requests\Autoload::register(); 1000 77 } 1001 78 } -
trunk/src/wp-includes/class-wp-http-requests-hooks.php
r54133 r54997 13 13 * @since 4.7.0 14 14 * 15 * @see Requests_Hooks15 * @see Hooks 16 16 */ 17 17 #[AllowDynamicProperties] 18 class WP_HTTP_Requests_Hooks extends Requests_Hooks {18 class WP_HTTP_Requests_Hooks extends Hooks { 19 19 /** 20 20 * Requested URL. -
trunk/src/wp-includes/class-wp-http-requests-response.php
r52328 r54997 9 9 10 10 /** 11 * Core wrapper object for a Requests_Response for standardisation.11 * Core wrapper object for a Response for standardisation. 12 12 * 13 13 * @since 4.6.0 … … 20 20 * 21 21 * @since 4.6.0 22 * @var Requests_Response22 * @var Response 23 23 */ 24 24 protected $response; … … 37 37 * @since 4.6.0 38 38 * 39 * @param Requests_Response $response HTTP response.40 * @param string $filename Optional. File name. Default empty.39 * @param Response $response HTTP response. 40 * @param string $filename Optional. File name. Default empty. 41 41 */ 42 public function __construct( Requests_Response $response, $filename = '' ) {42 public function __construct( Response $response, $filename = '' ) { 43 43 $this->response = $response; 44 44 $this->filename = $filename; … … 50 50 * @since 4.6.0 51 51 * 52 * @return Requests_Response HTTP response.52 * @return Response HTTP response. 53 53 */ 54 54 public function get_response_object() { … … 61 61 * @since 4.6.0 62 62 * 63 * @return \ Requests_Utility_CaseInsensitiveDictionary Map of header name to header value.63 * @return \CaseInsensitiveDictionary Map of header name to header value. 64 64 */ 65 65 public function get_headers() { 66 66 // Ensure headers remain case-insensitive. 67 $converted = new Requests_Utility_CaseInsensitiveDictionary();67 $converted = new CaseInsensitiveDictionary(); 68 68 69 69 foreach ( $this->response->headers->getAll() as $key => $value ) { … … 86 86 */ 87 87 public function set_headers( $headers ) { 88 $this->response->headers = new Requests_Response_Headers( $headers );88 $this->response->headers = new Headers( $headers ); 89 89 } 90 90 -
trunk/src/wp-includes/class-wp-http.php
r54891 r54997 8 8 */ 9 9 10 if ( ! class_exists( ' Requests' ) ) {11 require ABSPATH . WPINC . '/ class-requests.php';12 13 Requests::register_autoloader();14 Requests::set_certificate_path( ABSPATH . WPINC . '/certificates/ca-bundle.crt' );10 if ( ! class_exists( '' ) ) { 11 require ABSPATH . WPINC . '/.php'; 12 13 er(); 14 Requests::set_certificate_path( ABSPATH . WPINC . '/certificates/ca-bundle.crt' ); 15 15 } 16 16 … … 276 276 $response = new WP_Error( 'http_request_failed', __( 'A valid URL was not provided.' ) ); 277 277 /** This action is documented in wp-includes/class-wp-http.php */ 278 do_action( 'http_api_debug', $response, 'response', ' Requests', $parsed_args, $url );278 do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url ); 279 279 return $response; 280 280 } … … 283 283 $response = new WP_Error( 'http_request_not_executed', __( 'User has blocked requests through HTTP.' ) ); 284 284 /** This action is documented in wp-includes/class-wp-http.php */ 285 do_action( 'http_api_debug', $response, 'response', ' Requests', $parsed_args, $url );285 do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url ); 286 286 return $response; 287 287 } … … 300 300 $response = new WP_Error( 'http_request_failed', __( 'Destination directory for file streaming does not exist or is not writable.' ) ); 301 301 /** This action is documented in wp-includes/class-wp-http.php */ 302 do_action( 'http_api_debug', $response, 'response', ' Requests', $parsed_args, $url );302 do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url ); 303 303 return $response; 304 304 } … … 348 348 } 349 349 350 // If we've got cookies, use and convert them to Requests_Cookie.350 // If we've got cookies, use and convert them to Cookie. 351 351 if ( ! empty( $parsed_args['cookies'] ) ) { 352 352 $options['cookies'] = WP_Http::normalize_cookies( $parsed_args['cookies'] ); … … 380 380 $proxy = new WP_HTTP_Proxy(); 381 381 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { 382 $options['proxy'] = new Requests_Proxy_HTTP( $proxy->host() . ':' . $proxy->port() );382 $options['proxy'] = new HTTP( $proxy->host() . ':' . $proxy->port() ); 383 383 384 384 if ( $proxy->use_authentication() ) { … … 393 393 394 394 try { 395 $requests_response = Requests::request( $url, $headers, $data, $type, $options );395 $requests_response = Requests::request( $url, $headers, $data, $type, $options ); 396 396 397 397 // Convert the response into an array. … … 401 401 // Add the original object to the array. 402 402 $response['http_response'] = $http_response; 403 } catch ( Requests_Exception $e ) {403 } catch ( Exception $e ) { 404 404 $response = new WP_Error( 'http_request_failed', $e->getMessage() ); 405 405 } … … 418 418 * @param string $url The request URL. 419 419 */ 420 do_action( 'http_api_debug', $response, 'response', ' Requests', $parsed_args, $url );420 do_action( 'http_api_debug', $response, 'response', 'Requests', $parsed_args, $url ); 421 421 if ( is_wp_error( $response ) ) { 422 422 return $response; … … 454 454 * 455 455 * @param array $cookies Array of cookies to send with the request. 456 * @return Requests_Cookie_Jar Cookie holder object.456 * @return Jar Cookie holder object. 457 457 */ 458 458 public static function normalize_cookies( $cookies ) { 459 $cookie_jar = new Requests_Cookie_Jar();459 $cookie_jar = new Jar(); 460 460 461 461 foreach ( $cookies as $name => $value ) { … … 467 467 } 468 468 ); 469 $cookie_jar[ $value->name ] = new Requests_Cookie( $value->name, $value->value, $attributes, array( 'host-only' => $value->host_only ) );469 $cookie_jar[ $value->name ] = new Cookie( $value->name, $value->value, $attributes, array( 'host-only' => $value->host_only ) ); 470 470 } elseif ( is_scalar( $value ) ) { 471 $cookie_jar[ $name ] = new Requests_Cookie( $name,$value );471 $cookie_jar[ $name ] = new $value ); 472 472 } 473 473 } … … 485 485 * @since 4.6.0 486 486 * 487 * @param string $location URL to redirect to.488 * @param array $headers Headers for the redirect.489 * @param string|array $data Body to send with the request.490 * @param array $options Redirect request options.491 * @param Requests_Response $original Response object.487 * @param string $location URL to redirect to. 488 * @param array $headers Headers for the redirect. 489 * @param string|array $data Body to send with the request. 490 * @param array $options Redirect request options. 491 * @param Response $original Response object. 492 492 */ 493 493 public static function browser_redirect_compatibility( $location, $headers, $data, &$options, $original ) { 494 494 // Browser compatibility. 495 495 if ( 302 === $original->status_code ) { 496 $options['type'] = Requests::GET;496 $options['type'] = Requests::GET; 497 497 } 498 498 } … … 503 503 * @since 4.7.5 504 504 * 505 * @throws Requests_Exception On unsuccessful URL validation.505 * @throws Exception On unsuccessful URL validation. 506 506 * @param string $location URL to redirect to. 507 507 */ 508 508 public static function validate_redirects( $location ) { 509 509 if ( ! wp_http_validate_url( $location ) ) { 510 throw new Requests_Exception( __( 'A valid URL was not provided.' ), 'wp_http.redirect_failed_validation' );510 throw new Exception( __( 'A valid URL was not provided.' ), 'wp_http.redirect_failed_validation' ); 511 511 } 512 512 } -
trunk/src/wp-includes/deprecated.php
r54878 r54997 3655 3655 * @param int $red Optional. The number of Redirects followed, Upon 5 being hit, 3656 3656 * returns false. Default 1. 3657 * @return \ Requests_Utility_CaseInsensitiveDictionary|false Headers on success, false on failure.3657 * @return \CaseInsensitiveDictionary|false Headers on success, false on failure. 3658 3658 */ 3659 3659 function wp_get_http( $url, $file_path = false, $red = 1 ) { -
trunk/src/wp-includes/functions.php
r54929 r54997 977 977 * @param string $url URL to retrieve HTTP headers from. 978 978 * @param bool $deprecated Not Used. 979 * @return \ Requests_Utility_CaseInsensitiveDictionary|false Headers on success, false on failure.979 * @return \CaseInsensitiveDictionary|false Headers on success, false on failure. 980 980 */ 981 981 function wp_get_http_headers( $url, $deprecated = false ) { -
trunk/src/wp-includes/http.php
r54157 r54997 201 201 * 202 202 * @since 2.7.0 203 * @since 4.6.0 Return value changed from an array to an Requests_Utility_CaseInsensitiveDictionary instance.204 * 205 * @see \ Requests_Utility_CaseInsensitiveDictionary203 * @since 4.6.0 Return value changed from an array to an CaseInsensitiveDictionary instance. 204 * 205 * @see \CaseInsensitiveDictionary 206 206 * 207 207 * @param array|WP_Error $response HTTP response. 208 * @return \ Requests_Utility_CaseInsensitiveDictionary|array The headers of the response, or empty array209 * if incorrect parameter given.208 * @return \CaseInsensitiveDictionary|array The headers of the response, or empty array 209 * if incorrect parameter given. 210 210 */ 211 211 function wp_remote_retrieve_headers( $response ) { -
trunk/src/wp-includes/rest-api.php
r54964 r54997 1415 1415 $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]?)$/'; 1416 1416 1417 if ( ! preg_match( $ipv4_pattern, $ip ) && ! Requests_IPv6::check_ipv6( $ip ) ) {1417 if ( ! preg_match( $ipv4_pattern, $ip ) && ! v6::check_ipv6( $ip ) ) { 1418 1418 return false; 1419 1419 } -
trunk/tests/phpunit/tests/feed/wpSimplePieFile.php
r54872 r54997 86 86 87 87 return array( 88 'headers' => new Requests_Utility_CaseInsensitiveDictionary( $single_value_headers ),88 'headers' => new CaseInsensitiveDictionary( $single_value_headers ), 89 89 'body' => file_get_contents( DIR_TESTDATA . '/feed/wordpress-org-news.xml' ), 90 90 'response' => array( … … 115 115 ); 116 116 117 $response['headers'] = new Requests_Utility_CaseInsensitiveDictionary( $multiple_value_headers );117 $response['headers'] = new CaseInsensitiveDictionary( $multiple_value_headers ); 118 118 119 119 return $response; -
trunk/tests/phpunit/tests/functions/maybeSerialize.php
r53890 r54997 214 214 $serialized = maybe_serialize( $value ); 215 215 216 if ( get_class( $value ) === ' Requests_Utility_FilteredIterator' ) {216 if ( get_class( $value ) === 'FilteredIterator' ) { 217 217 $new_value = unserialize( $serialized ); 218 $property = ( new ReflectionClass( ' Requests_Utility_FilteredIterator' ) )->getProperty( 'callback' );218 $property = ( new ReflectionClass( 'FilteredIterator' ) )->getProperty( 'callback' ); 219 219 $property->setAccessible( true ); 220 220 $callback_value = $property->getValue( $new_value ); … … 234 234 return array( 235 235 'filtered iterator using md5' => array( 236 new Requests_Utility_FilteredIterator( array( 1 ), 'md5' ),236 new FilteredIterator( array( 1 ), 'md5' ), 237 237 ), 238 238 'filtered iterator using sha1' => array( 239 new Requests_Utility_FilteredIterator( array( 1, 2 ), 'sha1' ),239 new FilteredIterator( array( 1, 2 ), 'sha1' ), 240 240 ), 241 241 'array iterator' => array( -
trunk/tests/phpunit/tests/http/functions.php
r53491 r54997 217 217 public function test_get_cookie_host_only() { 218 218 // Emulate WP_Http::request() internals. 219 $requests_response = new Requests_Response();220 221 $requests_response->cookies['test'] = Requests_Cookie::parse( 'test=foo; domain=.wordpress.org' );219 $requests_response = new Response(); 220 221 $requests_response->cookies['test'] = Cookie::parse( 'test=foo; domain=.wordpress.org' ); 222 222 223 223 $requests_response->cookies['test']->flags['host-only'] = false; // https://github.com/WordPress/Requests/issues/306 … … 232 232 $this->assertFalse( $cookie->host_only, 'host-only flag not set' ); 233 233 234 // Regurgitate ( Requests_Cookie -> WP_Http_Cookie -> Requests_Cookie).234 // Regurgitate (Cookie). 235 235 $cookies = WP_Http::normalize_cookies( wp_remote_retrieve_cookies( $response ) ); 236 236 $this->assertFalse( $cookies['test']->flags['host-only'], 'host-only flag data lost' ); -
trunk/tests/phpunit/tests/http/http.php
r54968 r54997 310 310 ); 311 311 312 $this->assertInstanceOf( ' Requests_Cookie_Jar', $cookie_jar );312 $this->assertInstanceOf( 'Jar', $cookie_jar ); 313 313 314 314 foreach ( array_keys( $cookies ) as $cookie ) { … … 316 316 $this->assertArrayNotHasKey( $cookie, $cookie_jar ); 317 317 } else { 318 $this->assertInstanceOf( ' Requests_Cookie', $cookie_jar[ $cookie ] );318 $this->assertInstanceOf( 'Cookie', $cookie_jar[ $cookie ] ); 319 319 } 320 320 } -
trunk/tests/phpunit/tests/rest-api/rest-widgets-controller.php
r54896 r54997 418 418 419 419 return array( 420 'headers' => new Requests_Utility_CaseInsensitiveDictionary( $single_value_headers ),420 'headers' => new CaseInsensitiveDictionary( $single_value_headers ), 421 421 'body' => file_get_contents( DIR_TESTDATA . '/feed/wordpress-org-news.xml' ), 422 422 'response' => array( -
trunk/tests/phpunit/tests/widgets/wpWidgetRss.php
r52328 r54997 107 107 108 108 return array( 109 'headers' => new Requests_Utility_CaseInsensitiveDictionary( $single_value_headers ),109 'headers' => new CaseInsensitiveDictionary( $single_value_headers ), 110 110 'body' => file_get_contents( DIR_TESTDATA . '/feed/wordpress-org-news.xml' ), 111 111 'response' => array(
Note: See TracChangeset
for help on using the changeset viewer.