26 * @since 2.7.0 |
26 * @since 2.7.0 |
27 */ |
27 */ |
28 class WP_Http { |
28 class WP_Http { |
29 |
29 |
30 // Aliases for HTTP response codes. |
30 // Aliases for HTTP response codes. |
31 const HTTP_CONTINUE = 100; |
31 const HTTP_CONTINUE = 100; |
32 const SWITCHING_PROTOCOLS = 101; |
32 const SWITCHING_PROTOCOLS = 101; |
33 const PROCESSING = 102; |
33 const PROCESSING = 102; |
34 |
34 const EARLY_HINTS = 103; |
35 const OK = 200; |
35 |
36 const CREATED = 201; |
36 const OK = 200; |
37 const ACCEPTED = 202; |
37 const CREATED = 201; |
38 const NON_AUTHORITATIVE_INFORMATION = 203; |
38 const ACCEPTED = 202; |
39 const NO_CONTENT = 204; |
39 const NON_AUTHORITATIVE_INFORMATION = 203; |
40 const RESET_CONTENT = 205; |
40 const NO_CONTENT = 204; |
41 const PARTIAL_CONTENT = 206; |
41 const RESET_CONTENT = 205; |
42 const MULTI_STATUS = 207; |
42 const PARTIAL_CONTENT = 206; |
43 const IM_USED = 226; |
43 const MULTI_STATUS = 207; |
44 |
44 const IM_USED = 226; |
45 const MULTIPLE_CHOICES = 300; |
45 |
46 const MOVED_PERMANENTLY = 301; |
46 const MULTIPLE_CHOICES = 300; |
47 const FOUND = 302; |
47 const MOVED_PERMANENTLY = 301; |
48 const SEE_OTHER = 303; |
48 const FOUND = 302; |
49 const NOT_MODIFIED = 304; |
49 const SEE_OTHER = 303; |
50 const USE_PROXY = 305; |
50 const NOT_MODIFIED = 304; |
51 const RESERVED = 306; |
51 const USE_PROXY = 305; |
52 const TEMPORARY_REDIRECT = 307; |
52 const RESERVED = 306; |
53 const PERMANENT_REDIRECT = 308; |
53 const TEMPORARY_REDIRECT = 307; |
|
54 const PERMANENT_REDIRECT = 308; |
54 |
55 |
55 const BAD_REQUEST = 400; |
56 const BAD_REQUEST = 400; |
56 const UNAUTHORIZED = 401; |
57 const UNAUTHORIZED = 401; |
57 const PAYMENT_REQUIRED = 402; |
58 const PAYMENT_REQUIRED = 402; |
58 const FORBIDDEN = 403; |
59 const FORBIDDEN = 403; |
144 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. |
146 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. |
145 * A WP_Error instance upon error. |
147 * A WP_Error instance upon error. |
146 */ |
148 */ |
147 public function request( $url, $args = array() ) { |
149 public function request( $url, $args = array() ) { |
148 $defaults = array( |
150 $defaults = array( |
149 'method' => 'GET', |
151 'method' => 'GET', |
150 /** |
152 /** |
151 * Filters the timeout value for an HTTP request. |
153 * Filters the timeout value for an HTTP request. |
152 * |
154 * |
153 * @since 2.7.0 |
155 * @since 2.7.0 |
154 * |
156 * @since 5.1.0 The `$url` parameter was added. |
155 * @param int $timeout_value Time in seconds until a request times out. |
157 * |
156 * Default 5. |
158 * @param int $timeout_value Time in seconds until a request times out. Default 5. |
|
159 * @param string $url The request URL. |
157 */ |
160 */ |
158 'timeout' => apply_filters( 'http_request_timeout', 5 ), |
161 'timeout' => apply_filters( 'http_request_timeout', 5, $url ), |
159 /** |
162 /** |
160 * Filters the number of redirects allowed during an HTTP request. |
163 * Filters the number of redirects allowed during an HTTP request. |
161 * |
164 * |
162 * @since 2.7.0 |
165 * @since 2.7.0 |
163 * |
166 * @since 5.1.0 The `$url` parameter was added. |
164 * @param int $redirect_count Number of redirects allowed. Default 5. |
167 * |
|
168 * @param int $redirect_count Number of redirects allowed. Default 5. |
|
169 * @param string $url The request URL. |
165 */ |
170 */ |
166 'redirection' => apply_filters( 'http_request_redirection_count', 5 ), |
171 'redirection' => apply_filters( 'http_request_redirection_count', 5, $url ), |
167 /** |
172 /** |
168 * Filters the version of the HTTP protocol used in a request. |
173 * Filters the version of the HTTP protocol used in a request. |
169 * |
174 * |
170 * @since 2.7.0 |
175 * @since 2.7.0 |
171 * |
176 * @since 5.1.0 The `$url` parameter was added. |
172 * @param string $version Version of HTTP used. Accepts '1.0' and '1.1'. |
177 * |
173 * Default '1.0'. |
178 * @param string $version Version of HTTP used. Accepts '1.0' and '1.1'. Default '1.0'. |
|
179 * @param string $url The request URL. |
174 */ |
180 */ |
175 'httpversion' => apply_filters( 'http_request_version', '1.0' ), |
181 'httpversion' => apply_filters( 'http_request_version', '1.0', $url ), |
176 /** |
182 /** |
177 * Filters the user agent value sent with an HTTP request. |
183 * Filters the user agent value sent with an HTTP request. |
178 * |
184 * |
179 * @since 2.7.0 |
185 * @since 2.7.0 |
|
186 * @since 5.1.0 The `$url` parameter was added. |
180 * |
187 * |
181 * @param string $user_agent WordPress user agent string. |
188 * @param string $user_agent WordPress user agent string. |
|
189 * @param string $url The request URL. |
182 */ |
190 */ |
183 'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ) ), |
191 'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ), $url ), |
184 /** |
192 /** |
185 * Filters whether to pass URLs through wp_http_validate_url() in an HTTP request. |
193 * Filters whether to pass URLs through wp_http_validate_url() in an HTTP request. |
186 * |
194 * |
187 * @since 3.6.0 |
195 * @since 3.6.0 |
188 * |
196 * @since 5.1.0 The `$url` parameter was added. |
189 * @param bool $pass_url Whether to pass URLs through wp_http_validate_url(). |
197 * |
190 * Default false. |
198 * @param bool $pass_url Whether to pass URLs through wp_http_validate_url(). Default false. |
|
199 * @param string $url The request URL. |
191 */ |
200 */ |
192 'reject_unsafe_urls' => apply_filters( 'http_request_reject_unsafe_urls', false ), |
201 'reject_unsafe_urls' => apply_filters( 'http_request_reject_unsafe_urls', false, $url ), |
193 'blocking' => true, |
202 'blocking' => true, |
194 'headers' => array(), |
203 'headers' => array(), |
195 'cookies' => array(), |
204 'cookies' => array(), |
196 'body' => null, |
205 'body' => null, |
197 'compress' => false, |
206 'compress' => false, |
198 'decompress' => true, |
207 'decompress' => true, |
199 'sslverify' => true, |
208 'sslverify' => true, |
200 'sslcertificates' => ABSPATH . WPINC . '/certificates/ca-bundle.crt', |
209 'sslcertificates' => ABSPATH . WPINC . '/certificates/ca-bundle.crt', |
201 'stream' => false, |
210 'stream' => false, |
202 'filename' => null, |
211 'filename' => null, |
203 'limit_response_size' => null, |
212 'limit_response_size' => null, |
204 ); |
213 ); |
205 |
214 |
206 // Pre-parse for the HEAD checks. |
215 // Pre-parse for the HEAD checks. |
207 $args = wp_parse_args( $args ); |
216 $args = wp_parse_args( $args ); |
208 |
217 |
209 // By default, Head requests do not cause redirections. |
218 // By default, Head requests do not cause redirections. |
210 if ( isset($args['method']) && 'HEAD' == $args['method'] ) |
219 if ( isset( $args['method'] ) && 'HEAD' == $args['method'] ) { |
211 $defaults['redirection'] = 0; |
220 $defaults['redirection'] = 0; |
|
221 } |
212 |
222 |
213 $r = wp_parse_args( $args, $defaults ); |
223 $r = wp_parse_args( $args, $defaults ); |
214 /** |
224 /** |
215 * Filters the arguments used in an HTTP request. |
225 * Filters the arguments used in an HTTP request. |
216 * |
226 * |
532 * Also caches the transport instance to be used later. |
544 * Also caches the transport instance to be used later. |
533 * |
545 * |
534 * The order for requests is cURL, and then PHP Streams. |
546 * The order for requests is cURL, and then PHP Streams. |
535 * |
547 * |
536 * @since 3.2.0 |
548 * @since 3.2.0 |
537 * |
549 * @deprecated 5.1.0 Use WP_Http::request() |
538 * @static |
550 * @see WP_Http::request() |
539 * |
551 * |
540 * @param string $url URL to Request |
552 * @param string $url URL to Request |
541 * @param array $args Request arguments |
553 * @param array $args Request arguments |
542 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error |
554 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error |
543 */ |
555 */ |
544 private function _dispatch_request( $url, $args ) { |
556 private function _dispatch_request( $url, $args ) { |
545 static $transports = array(); |
557 static $transports = array(); |
546 |
558 |
547 $class = $this->_get_first_available_transport( $args, $url ); |
559 $class = $this->_get_first_available_transport( $args, $url ); |
548 if ( !$class ) |
560 if ( ! $class ) { |
549 return new WP_Error( 'http_failure', __( 'There are no HTTP transports available which can complete the requested request.' ) ); |
561 return new WP_Error( 'http_failure', __( 'There are no HTTP transports available which can complete the requested request.' ) ); |
|
562 } |
550 |
563 |
551 // Transport claims to support request, instantiate it and give it a whirl. |
564 // Transport claims to support request, instantiate it and give it a whirl. |
552 if ( empty( $transports[$class] ) ) |
565 if ( empty( $transports[ $class ] ) ) { |
553 $transports[$class] = new $class; |
566 $transports[ $class ] = new $class; |
554 |
567 } |
555 $response = $transports[$class]->request( $url, $args ); |
568 |
|
569 $response = $transports[ $class ]->request( $url, $args ); |
556 |
570 |
557 /** This action is documented in wp-includes/class-http.php */ |
571 /** This action is documented in wp-includes/class-http.php */ |
558 do_action( 'http_api_debug', $response, 'response', $class, $args, $url ); |
572 do_action( 'http_api_debug', $response, 'response', $class, $args, $url ); |
559 |
573 |
560 if ( is_wp_error( $response ) ) |
574 if ( is_wp_error( $response ) ) { |
561 return $response; |
575 return $response; |
562 |
576 } |
563 /** |
577 |
564 * Filters the HTTP API response immediately before the response is returned. |
578 /** This filter is documented in wp-includes/class-http.php */ |
565 * |
|
566 * @since 2.9.0 |
|
567 * |
|
568 * @param array $response HTTP response. |
|
569 * @param array $args HTTP request arguments. |
|
570 * @param string $url The request URL. |
|
571 */ |
|
572 return apply_filters( 'http_response', $response, $args, $url ); |
579 return apply_filters( 'http_response', $response, $args, $url ); |
573 } |
580 } |
574 |
581 |
575 /** |
582 /** |
576 * Uses the POST HTTP method. |
583 * Uses the POST HTTP method. |
615 * |
622 * |
616 * @param string $url The request URL. |
623 * @param string $url The request URL. |
617 * @param string|array $args Optional. Override the defaults. |
624 * @param string|array $args Optional. Override the defaults. |
618 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error |
625 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error |
619 */ |
626 */ |
620 public function head($url, $args = array()) { |
627 public function head( $url, $args = array() ) { |
621 $defaults = array('method' => 'HEAD'); |
628 $defaults = array( 'method' => 'HEAD' ); |
622 $r = wp_parse_args( $args, $defaults ); |
629 $r = wp_parse_args( $args, $defaults ); |
623 return $this->request($url, $r); |
630 return $this->request( $url, $r ); |
624 } |
631 } |
625 |
632 |
626 /** |
633 /** |
627 * Parses the responses and splits the parts into headers and body. |
634 * Parses the responses and splits the parts into headers and body. |
628 * |
635 * |
629 * @static |
|
630 * @since 2.7.0 |
636 * @since 2.7.0 |
631 * |
637 * |
632 * @param string $strResponse The full response string |
638 * @param string $strResponse The full response string |
633 * @return array Array with 'headers' and 'body' keys. |
639 * @return array Array with 'headers' and 'body' keys. |
634 */ |
640 */ |
635 public static function processResponse($strResponse) { |
641 public static function processResponse( $strResponse ) { |
636 $res = explode("\r\n\r\n", $strResponse, 2); |
642 $res = explode( "\r\n\r\n", $strResponse, 2 ); |
637 |
643 |
638 return array('headers' => $res[0], 'body' => isset($res[1]) ? $res[1] : ''); |
644 return array( |
|
645 'headers' => $res[0], |
|
646 'body' => isset( $res[1] ) ? $res[1] : '', |
|
647 ); |
639 } |
648 } |
640 |
649 |
641 /** |
650 /** |
642 * Transform header string into an array. |
651 * Transform header string into an array. |
643 * |
652 * |
644 * If an array is given then it is assumed to be raw header data with numeric keys with the |
653 * If an array is given then it is assumed to be raw header data with numeric keys with the |
645 * headers as the values. No headers must be passed that were already processed. |
654 * headers as the values. No headers must be passed that were already processed. |
646 * |
655 * |
647 * @static |
|
648 * @since 2.7.0 |
656 * @since 2.7.0 |
649 * |
657 * |
650 * @param string|array $headers |
658 * @param string|array $headers |
651 * @param string $url The URL that was requested |
659 * @param string $url The URL that was requested |
652 * @return array Processed string headers. If duplicate headers are encountered, |
660 * @return array Processed string headers. If duplicate headers are encountered, |
653 * Then a numbered array is returned as the value of that header-key. |
661 * Then a numbered array is returned as the value of that header-key. |
654 */ |
662 */ |
655 public static function processHeaders( $headers, $url = '' ) { |
663 public static function processHeaders( $headers, $url = '' ) { |
656 // Split headers, one per array element. |
664 // Split headers, one per array element. |
657 if ( is_string($headers) ) { |
665 if ( is_string( $headers ) ) { |
658 // Tolerate line terminator: CRLF = LF (RFC 2616 19.3). |
666 // Tolerate line terminator: CRLF = LF (RFC 2616 19.3). |
659 $headers = str_replace("\r\n", "\n", $headers); |
667 $headers = str_replace( "\r\n", "\n", $headers ); |
660 /* |
668 /* |
661 * Unfold folded header fields. LWS = [CRLF] 1*( SP | HT ) <US-ASCII SP, space (32)>, |
669 * Unfold folded header fields. LWS = [CRLF] 1*( SP | HT ) <US-ASCII SP, space (32)>, |
662 * <US-ASCII HT, horizontal-tab (9)> (RFC 2616 2.2). |
670 * <US-ASCII HT, horizontal-tab (9)> (RFC 2616 2.2). |
663 */ |
671 */ |
664 $headers = preg_replace('/\n[ \t]/', ' ', $headers); |
672 $headers = preg_replace( '/\n[ \t]/', ' ', $headers ); |
665 // Create the headers array. |
673 // Create the headers array. |
666 $headers = explode("\n", $headers); |
674 $headers = explode( "\n", $headers ); |
667 } |
675 } |
668 |
676 |
669 $response = array('code' => 0, 'message' => ''); |
677 $response = array( |
|
678 'code' => 0, |
|
679 'message' => '', |
|
680 ); |
670 |
681 |
671 /* |
682 /* |
672 * If a redirection has taken place, The headers for each page request may have been passed. |
683 * If a redirection has taken place, The headers for each page request may have been passed. |
673 * In this case, determine the final HTTP header and parse from there. |
684 * In this case, determine the final HTTP header and parse from there. |
674 */ |
685 */ |
675 for ( $i = count($headers)-1; $i >= 0; $i-- ) { |
686 for ( $i = count( $headers ) - 1; $i >= 0; $i-- ) { |
676 if ( !empty($headers[$i]) && false === strpos($headers[$i], ':') ) { |
687 if ( ! empty( $headers[ $i ] ) && false === strpos( $headers[ $i ], ':' ) ) { |
677 $headers = array_splice($headers, $i); |
688 $headers = array_splice( $headers, $i ); |
678 break; |
689 break; |
679 } |
690 } |
680 } |
691 } |
681 |
692 |
682 $cookies = array(); |
693 $cookies = array(); |
683 $newheaders = array(); |
694 $newheaders = array(); |
684 foreach ( (array) $headers as $tempheader ) { |
695 foreach ( (array) $headers as $tempheader ) { |
685 if ( empty($tempheader) ) |
696 if ( empty( $tempheader ) ) { |
686 continue; |
697 continue; |
687 |
698 } |
688 if ( false === strpos($tempheader, ':') ) { |
699 |
689 $stack = explode(' ', $tempheader, 3); |
700 if ( false === strpos( $tempheader, ':' ) ) { |
|
701 $stack = explode( ' ', $tempheader, 3 ); |
690 $stack[] = ''; |
702 $stack[] = ''; |
691 list( , $response['code'], $response['message']) = $stack; |
703 list( , $response['code'], $response['message']) = $stack; |
692 continue; |
704 continue; |
693 } |
705 } |
694 |
706 |
695 list($key, $value) = explode(':', $tempheader, 2); |
707 list($key, $value) = explode( ':', $tempheader, 2 ); |
696 |
708 |
697 $key = strtolower( $key ); |
709 $key = strtolower( $key ); |
698 $value = trim( $value ); |
710 $value = trim( $value ); |
699 |
711 |
700 if ( isset( $newheaders[ $key ] ) ) { |
712 if ( isset( $newheaders[ $key ] ) ) { |
701 if ( ! is_array( $newheaders[ $key ] ) ) |
713 if ( ! is_array( $newheaders[ $key ] ) ) { |
702 $newheaders[$key] = array( $newheaders[ $key ] ); |
714 $newheaders[ $key ] = array( $newheaders[ $key ] ); |
|
715 } |
703 $newheaders[ $key ][] = $value; |
716 $newheaders[ $key ][] = $value; |
704 } else { |
717 } else { |
705 $newheaders[ $key ] = $value; |
718 $newheaders[ $key ] = $value; |
706 } |
719 } |
707 if ( 'set-cookie' == $key ) |
720 if ( 'set-cookie' == $key ) { |
708 $cookies[] = new WP_Http_Cookie( $value, $url ); |
721 $cookies[] = new WP_Http_Cookie( $value, $url ); |
|
722 } |
709 } |
723 } |
710 |
724 |
711 // Cast the Response Code to an int |
725 // Cast the Response Code to an int |
712 $response['code'] = intval( $response['code'] ); |
726 $response['code'] = intval( $response['code'] ); |
713 |
727 |
714 return array('response' => $response, 'headers' => $newheaders, 'cookies' => $cookies); |
728 return array( |
|
729 'response' => $response, |
|
730 'headers' => $newheaders, |
|
731 'cookies' => $cookies, |
|
732 ); |
715 } |
733 } |
716 |
734 |
717 /** |
735 /** |
718 * Takes the arguments for a ::request() and checks for the cookie array. |
736 * Takes the arguments for a ::request() and checks for the cookie array. |
719 * |
737 * |
720 * If it's found, then it upgrades any basic name => value pairs to WP_Http_Cookie instances, |
738 * If it's found, then it upgrades any basic name => value pairs to WP_Http_Cookie instances, |
721 * which are each parsed into strings and added to the Cookie: header (within the arguments array). |
739 * which are each parsed into strings and added to the Cookie: header (within the arguments array). |
722 * Edits the array by reference. |
740 * Edits the array by reference. |
723 * |
741 * |
724 * @since 2.8.0 |
742 * @since 2.8.0 |
725 * @static |
|
726 * |
743 * |
727 * @param array $r Full array of args passed into ::request() |
744 * @param array $r Full array of args passed into ::request() |
728 */ |
745 */ |
729 public static function buildCookieHeader( &$r ) { |
746 public static function buildCookieHeader( &$r ) { |
730 if ( ! empty($r['cookies']) ) { |
747 if ( ! empty( $r['cookies'] ) ) { |
731 // Upgrade any name => value cookie pairs to WP_HTTP_Cookie instances. |
748 // Upgrade any name => value cookie pairs to WP_HTTP_Cookie instances. |
732 foreach ( $r['cookies'] as $name => $value ) { |
749 foreach ( $r['cookies'] as $name => $value ) { |
733 if ( ! is_object( $value ) ) |
750 if ( ! is_object( $value ) ) { |
734 $r['cookies'][ $name ] = new WP_Http_Cookie( array( 'name' => $name, 'value' => $value ) ); |
751 $r['cookies'][ $name ] = new WP_Http_Cookie( |
|
752 array( |
|
753 'name' => $name, |
|
754 'value' => $value, |
|
755 ) |
|
756 ); |
|
757 } |
735 } |
758 } |
736 |
759 |
737 $cookies_header = ''; |
760 $cookies_header = ''; |
738 foreach ( (array) $r['cookies'] as $cookie ) { |
761 foreach ( (array) $r['cookies'] as $cookie ) { |
739 $cookies_header .= $cookie->getHeaderValue() . '; '; |
762 $cookies_header .= $cookie->getHeaderValue() . '; '; |
740 } |
763 } |
741 |
764 |
742 $cookies_header = substr( $cookies_header, 0, -2 ); |
765 $cookies_header = substr( $cookies_header, 0, -2 ); |
743 $r['headers']['cookie'] = $cookies_header; |
766 $r['headers']['cookie'] = $cookies_header; |
744 } |
767 } |
745 } |
768 } |
746 |
769 |
747 /** |
770 /** |
750 * Based off the HTTP http_encoding_dechunk function. |
773 * Based off the HTTP http_encoding_dechunk function. |
751 * |
774 * |
752 * @link https://tools.ietf.org/html/rfc2616#section-19.4.6 Process for chunked decoding. |
775 * @link https://tools.ietf.org/html/rfc2616#section-19.4.6 Process for chunked decoding. |
753 * |
776 * |
754 * @since 2.7.0 |
777 * @since 2.7.0 |
755 * @static |
|
756 * |
778 * |
757 * @param string $body Body content |
779 * @param string $body Body content |
758 * @return string Chunked decoded body on success or raw body on failure. |
780 * @return string Chunked decoded body on success or raw body on failure. |
759 */ |
781 */ |
760 public static function chunkTransferDecode( $body ) { |
782 public static function chunkTransferDecode( $body ) { |
761 // The body is not chunked encoded or is malformed. |
783 // The body is not chunked encoded or is malformed. |
762 if ( ! preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', trim( $body ) ) ) |
784 if ( ! preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', trim( $body ) ) ) { |
763 return $body; |
785 return $body; |
|
786 } |
764 |
787 |
765 $parsed_body = ''; |
788 $parsed_body = ''; |
766 |
789 |
767 // We'll be altering $body, so need a backup in case of error. |
790 // We'll be altering $body, so need a backup in case of error. |
768 $body_original = $body; |
791 $body_original = $body; |
769 |
792 |
770 while ( true ) { |
793 while ( true ) { |
771 $has_chunk = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $body, $match ); |
794 $has_chunk = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $body, $match ); |
772 if ( ! $has_chunk || empty( $match[1] ) ) |
795 if ( ! $has_chunk || empty( $match[1] ) ) { |
773 return $body_original; |
796 return $body_original; |
774 |
797 } |
775 $length = hexdec( $match[1] ); |
798 |
|
799 $length = hexdec( $match[1] ); |
776 $chunk_length = strlen( $match[0] ); |
800 $chunk_length = strlen( $match[0] ); |
777 |
801 |
778 // Parse out the chunk of data. |
802 // Parse out the chunk of data. |
779 $parsed_body .= substr( $body, $chunk_length, $length ); |
803 $parsed_body .= substr( $body, $chunk_length, $length ); |
780 |
804 |
781 // Remove the chunk from the raw data. |
805 // Remove the chunk from the raw data. |
782 $body = substr( $body, $length + $chunk_length ); |
806 $body = substr( $body, $length + $chunk_length ); |
783 |
807 |
784 // End of the document. |
808 // End of the document. |
785 if ( '0' === trim( $body ) ) |
809 if ( '0' === trim( $body ) ) { |
786 return $parsed_body; |
810 return $parsed_body; |
|
811 } |
787 } |
812 } |
788 } |
813 } |
789 |
814 |
790 /** |
815 /** |
791 * Block requests through the proxy. |
816 * Block requests through the proxy. |
831 * Default false. |
858 * Default false. |
832 */ |
859 */ |
833 return apply_filters( 'block_local_requests', false ); |
860 return apply_filters( 'block_local_requests', false ); |
834 } |
861 } |
835 |
862 |
836 if ( !defined('WP_ACCESSIBLE_HOSTS') ) |
863 if ( ! defined( 'WP_ACCESSIBLE_HOSTS' ) ) { |
837 return true; |
864 return true; |
|
865 } |
838 |
866 |
839 static $accessible_hosts = null; |
867 static $accessible_hosts = null; |
840 static $wildcard_regex = array(); |
868 static $wildcard_regex = array(); |
841 if ( null === $accessible_hosts ) { |
869 if ( null === $accessible_hosts ) { |
842 $accessible_hosts = preg_split('|,\s*|', WP_ACCESSIBLE_HOSTS); |
870 $accessible_hosts = preg_split( '|,\s*|', WP_ACCESSIBLE_HOSTS ); |
843 |
871 |
844 if ( false !== strpos(WP_ACCESSIBLE_HOSTS, '*') ) { |
872 if ( false !== strpos( WP_ACCESSIBLE_HOSTS, '*' ) ) { |
845 $wildcard_regex = array(); |
873 $wildcard_regex = array(); |
846 foreach ( $accessible_hosts as $host ) |
874 foreach ( $accessible_hosts as $host ) { |
847 $wildcard_regex[] = str_replace( '\*', '.+', preg_quote( $host, '/' ) ); |
875 $wildcard_regex[] = str_replace( '\*', '.+', preg_quote( $host, '/' ) ); |
848 $wildcard_regex = '/^(' . implode('|', $wildcard_regex) . ')$/i'; |
876 } |
849 } |
877 $wildcard_regex = '/^(' . implode( '|', $wildcard_regex ) . ')$/i'; |
850 } |
878 } |
851 |
879 } |
852 if ( !empty($wildcard_regex) ) |
880 |
853 return !preg_match($wildcard_regex, $check['host']); |
881 if ( ! empty( $wildcard_regex ) ) { |
854 else |
882 return ! preg_match( $wildcard_regex, $check['host'] ); |
855 return !in_array( $check['host'], $accessible_hosts ); //Inverse logic, If it's in the array, then we can't access it. |
883 } else { |
|
884 return ! in_array( $check['host'], $accessible_hosts ); //Inverse logic, If it's in the array, then we can't access it. |
|
885 } |
856 |
886 |
857 } |
887 } |
858 |
888 |
859 /** |
889 /** |
860 * Used as a wrapper for PHP's parse_url() function that handles edgecases in < PHP 5.4.7. |
890 * Used as a wrapper for PHP's parse_url() function that handles edgecases in < PHP 5.4.7. |
904 $absolute_path = $url_parts['scheme'] . '://'; |
933 $absolute_path = $url_parts['scheme'] . '://'; |
905 |
934 |
906 // Schemeless URL's will make it this far, so we check for a host in the relative url and convert it to a protocol-url |
935 // Schemeless URL's will make it this far, so we check for a host in the relative url and convert it to a protocol-url |
907 if ( isset( $relative_url_parts['host'] ) ) { |
936 if ( isset( $relative_url_parts['host'] ) ) { |
908 $absolute_path .= $relative_url_parts['host']; |
937 $absolute_path .= $relative_url_parts['host']; |
909 if ( isset( $relative_url_parts['port'] ) ) |
938 if ( isset( $relative_url_parts['port'] ) ) { |
910 $absolute_path .= ':' . $relative_url_parts['port']; |
939 $absolute_path .= ':' . $relative_url_parts['port']; |
|
940 } |
911 } else { |
941 } else { |
912 $absolute_path .= $url_parts['host']; |
942 $absolute_path .= $url_parts['host']; |
913 if ( isset( $url_parts['port'] ) ) |
943 if ( isset( $url_parts['port'] ) ) { |
914 $absolute_path .= ':' . $url_parts['port']; |
944 $absolute_path .= ':' . $url_parts['port']; |
|
945 } |
915 } |
946 } |
916 |
947 |
917 // Start off with the Absolute URL path. |
948 // Start off with the Absolute URL path. |
918 $path = ! empty( $url_parts['path'] ) ? $url_parts['path'] : '/'; |
949 $path = ! empty( $url_parts['path'] ) ? $url_parts['path'] : '/'; |
919 |
950 |
920 // If it's a root-relative path, then great. |
951 // If it's a root-relative path, then great. |
921 if ( ! empty( $relative_url_parts['path'] ) && '/' == $relative_url_parts['path'][0] ) { |
952 if ( ! empty( $relative_url_parts['path'] ) && '/' == $relative_url_parts['path'][0] ) { |
922 $path = $relative_url_parts['path']; |
953 $path = $relative_url_parts['path']; |
923 |
954 |
924 // Else it's a relative path. |
955 // Else it's a relative path. |
925 } elseif ( ! empty( $relative_url_parts['path'] ) ) { |
956 } elseif ( ! empty( $relative_url_parts['path'] ) ) { |
926 // Strip off any file components from the absolute path. |
957 // Strip off any file components from the absolute path. |
927 $path = substr( $path, 0, strrpos( $path, '/' ) + 1 ); |
958 $path = substr( $path, 0, strrpos( $path, '/' ) + 1 ); |
928 |
959 |
929 // Build the new path. |
960 // Build the new path. |
937 // Strip any final leading ../ from the path. |
968 // Strip any final leading ../ from the path. |
938 $path = preg_replace( '!^/(\.\./)+!', '', $path ); |
969 $path = preg_replace( '!^/(\.\./)+!', '', $path ); |
939 } |
970 } |
940 |
971 |
941 // Add the Query string. |
972 // Add the Query string. |
942 if ( ! empty( $relative_url_parts['query'] ) ) |
973 if ( ! empty( $relative_url_parts['query'] ) ) { |
943 $path .= '?' . $relative_url_parts['query']; |
974 $path .= '?' . $relative_url_parts['query']; |
|
975 } |
944 |
976 |
945 return $absolute_path . '/' . ltrim( $path, '/' ); |
977 return $absolute_path . '/' . ltrim( $path, '/' ); |
946 } |
978 } |
947 |
979 |
948 /** |
980 /** |
949 * Handles HTTP Redirects and follows them if appropriate. |
981 * Handles HTTP Redirects and follows them if appropriate. |
950 * |
982 * |
951 * @since 3.7.0 |
983 * @since 3.7.0 |
952 * @static |
|
953 * |
984 * |
954 * @param string $url The URL which was requested. |
985 * @param string $url The URL which was requested. |
955 * @param array $args The Arguments which were used to make the request. |
986 * @param array $args The Arguments which were used to make the request. |
956 * @param array $response The Response of the HTTP request. |
987 * @param array $response The Response of the HTTP request. |
957 * @return false|object False if no redirect is present, a WP_HTTP or WP_Error result otherwise. |
988 * @return false|object False if no redirect is present, a WP_HTTP or WP_Error result otherwise. |
958 */ |
989 */ |
959 public static function handle_redirects( $url, $args, $response ) { |
990 public static function handle_redirects( $url, $args, $response ) { |
960 // If no redirects are present, or, redirects were not requested, perform no action. |
991 // If no redirects are present, or, redirects were not requested, perform no action. |
961 if ( ! isset( $response['headers']['location'] ) || 0 === $args['_redirection'] ) |
992 if ( ! isset( $response['headers']['location'] ) || 0 === $args['_redirection'] ) { |
962 return false; |
993 return false; |
|
994 } |
963 |
995 |
964 // Only perform redirections on redirection http codes. |
996 // Only perform redirections on redirection http codes. |
965 if ( $response['response']['code'] > 399 || $response['response']['code'] < 300 ) |
997 if ( $response['response']['code'] > 399 || $response['response']['code'] < 300 ) { |
966 return false; |
998 return false; |
|
999 } |
967 |
1000 |
968 // Don't redirect if we've run out of redirects. |
1001 // Don't redirect if we've run out of redirects. |
969 if ( $args['redirection']-- <= 0 ) |
1002 if ( $args['redirection']-- <= 0 ) { |
970 return new WP_Error( 'http_request_failed', __('Too many redirects.') ); |
1003 return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); |
|
1004 } |
971 |
1005 |
972 $redirect_location = $response['headers']['location']; |
1006 $redirect_location = $response['headers']['location']; |
973 |
1007 |
974 // If there were multiple Location headers, use the last header specified. |
1008 // If there were multiple Location headers, use the last header specified. |
975 if ( is_array( $redirect_location ) ) |
1009 if ( is_array( $redirect_location ) ) { |
976 $redirect_location = array_pop( $redirect_location ); |
1010 $redirect_location = array_pop( $redirect_location ); |
|
1011 } |
977 |
1012 |
978 $redirect_location = WP_Http::make_absolute_url( $redirect_location, $url ); |
1013 $redirect_location = WP_Http::make_absolute_url( $redirect_location, $url ); |
979 |
1014 |
980 // POST requests should not POST to a redirected location. |
1015 // POST requests should not POST to a redirected location. |
981 if ( 'POST' == $args['method'] ) { |
1016 if ( 'POST' == $args['method'] ) { |
982 if ( in_array( $response['response']['code'], array( 302, 303 ) ) ) |
1017 if ( in_array( $response['response']['code'], array( 302, 303 ) ) ) { |
983 $args['method'] = 'GET'; |
1018 $args['method'] = 'GET'; |
|
1019 } |
984 } |
1020 } |
985 |
1021 |
986 // Include valid cookies in the redirect process. |
1022 // Include valid cookies in the redirect process. |
987 if ( ! empty( $response['cookies'] ) ) { |
1023 if ( ! empty( $response['cookies'] ) ) { |
988 foreach ( $response['cookies'] as $cookie ) { |
1024 foreach ( $response['cookies'] as $cookie ) { |
989 if ( $cookie->test( $redirect_location ) ) |
1025 if ( $cookie->test( $redirect_location ) ) { |
990 $args['cookies'][] = $cookie; |
1026 $args['cookies'][] = $cookie; |
|
1027 } |
991 } |
1028 } |
992 } |
1029 } |
993 |
1030 |
994 return wp_remote_request( $redirect_location, $args ); |
1031 return wp_remote_request( $redirect_location, $args ); |
995 } |
1032 } |