26 * @since 2.7.0 |
26 * @since 2.7.0 |
27 */ |
27 */ |
28 class WP_Http { |
28 class WP_Http { |
29 |
29 |
30 /** |
30 /** |
31 * Send a HTTP request to a URI. |
31 * Send an HTTP request to a URI. |
32 * |
32 * |
33 * The body and headers are part of the arguments. The 'body' argument is for the body and will |
33 * Please note: The only URI that are supported in the HTTP Transport implementation |
34 * accept either a string or an array. The 'headers' argument should be an array, but a string |
34 * are the HTTP and HTTPS protocols. |
35 * is acceptable. If the 'body' argument is an array, then it will automatically be escaped |
|
36 * using http_build_query(). |
|
37 * |
|
38 * The only URI that are supported in the HTTP Transport implementation are the HTTP and HTTPS |
|
39 * protocols. |
|
40 * |
|
41 * The defaults are 'method', 'timeout', 'redirection', 'httpversion', 'blocking' and |
|
42 * 'user-agent'. |
|
43 * |
|
44 * Accepted 'method' values are 'GET', 'POST', and 'HEAD', some transports technically allow |
|
45 * others, but should not be assumed. The 'timeout' is used to sent how long the connection |
|
46 * should stay open before failing when no response. 'redirection' is used to track how many |
|
47 * redirects were taken and used to sent the amount for other transports, but not all transports |
|
48 * accept setting that value. |
|
49 * |
|
50 * The 'httpversion' option is used to sent the HTTP version and accepted values are '1.0', and |
|
51 * '1.1' and should be a string. The 'user-agent' option is the user-agent and is used to |
|
52 * replace the default user-agent, which is 'WordPress/WP_Version', where WP_Version is the |
|
53 * value from $wp_version. |
|
54 * |
|
55 * The 'blocking' parameter can be used to specify if the calling code requires the result of |
|
56 * the HTTP request. If set to false, the request will be sent to the remote server, and |
|
57 * processing returned to the calling code immediately, the caller will know if the request |
|
58 * suceeded or failed, but will not receive any response from the remote server. |
|
59 * |
35 * |
60 * @access public |
36 * @access public |
61 * @since 2.7.0 |
37 * @since 2.7.0 |
62 * |
38 * |
63 * @param string $url URI resource. |
39 * @param string $url The request URL. |
64 * @param str|array $args Optional. Override the defaults. |
40 * @param string|array $args { |
65 * @return array|object Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error |
41 * Optional. Array or string of HTTP request arguments. |
66 */ |
42 * |
67 function request( $url, $args = array() ) { |
43 * @type string $method Request method. Accepts 'GET', 'POST', 'HEAD', or 'PUT'. |
|
44 * Some transports technically allow others, but should not be |
|
45 * assumed. Default 'GET'. |
|
46 * @type int $timeout How long the connection should stay open in seconds. Default 5. |
|
47 * @type int $redirection Number of allowed redirects. Not supported by all transports |
|
48 * Default 5. |
|
49 * @type string $httpversion Version of the HTTP protocol to use. Accepts '1.0' and '1.1'. |
|
50 * Default '1.0'. |
|
51 * @type string $user-agent User-agent value sent. |
|
52 * Default WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ). |
|
53 * @type bool $reject_unsafe_urls Whether to pass URLs through {@see wp_http_validate_url()}. |
|
54 * Default false. |
|
55 * @type bool $blocking Whether the calling code requires the result of the request. |
|
56 * If set to false, the request will be sent to the remote server, |
|
57 * and processing returned to the calling code immediately, the caller |
|
58 * will know if the request succeeded or failed, but will not receive |
|
59 * any response from the remote server. Default true. |
|
60 * @type string|array $headers Array or string of headers to send with the request. |
|
61 * Default empty array. |
|
62 * @type array $cookies List of cookies to send with the request. Default empty array. |
|
63 * @type string|array $body Body to send with the request. Default null. |
|
64 * @type bool $compress Whether to compress the $body when sending the request. |
|
65 * Default false. |
|
66 * @type bool $decompress Whether to decompress a compressed response. If set to false and |
|
67 * compressed content is returned in the response anyway, it will |
|
68 * need to be separately decompressed. Default true. |
|
69 * @type bool $sslverify Whether to verify SSL for the request. Default true. |
|
70 * @type string sslcertificates Absolute path to an SSL certificate .crt file. |
|
71 * Default ABSPATH . WPINC . '/certificates/ca-bundle.crt'. |
|
72 * @type bool $stream Whether to stream to a file. If set to true and no filename was |
|
73 * given, it will be droped it in the WP temp dir and its name will |
|
74 * be set using the basename of the URL. Default false. |
|
75 * @type string $filename Filename of the file to write to when streaming. $stream must be |
|
76 * set to true. Default null. |
|
77 * @type int $limit_response_size Size in bytes to limit the response to. Default null. |
|
78 * |
|
79 * } |
|
80 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. |
|
81 * A WP_Error instance upon error. |
|
82 */ |
|
83 public function request( $url, $args = array() ) { |
68 global $wp_version; |
84 global $wp_version; |
69 |
85 |
70 $defaults = array( |
86 $defaults = array( |
71 'method' => 'GET', |
87 'method' => 'GET', |
72 'timeout' => apply_filters( 'http_request_timeout', 5), |
88 /** |
73 'redirection' => apply_filters( 'http_request_redirection_count', 5), |
89 * Filter the timeout value for an HTTP request. |
74 'httpversion' => apply_filters( 'http_request_version', '1.0'), |
90 * |
|
91 * @since 2.7.0 |
|
92 * |
|
93 * @param int $timeout_value Time in seconds until a request times out. |
|
94 * Default 5. |
|
95 */ |
|
96 'timeout' => apply_filters( 'http_request_timeout', 5 ), |
|
97 /** |
|
98 * Filter the number of redirects allowed during an HTTP request. |
|
99 * |
|
100 * @since 2.7.0 |
|
101 * |
|
102 * @param int $redirect_count Number of redirects allowed. Default 5. |
|
103 */ |
|
104 'redirection' => apply_filters( 'http_request_redirection_count', 5 ), |
|
105 /** |
|
106 * Filter the version of the HTTP protocol used in a request. |
|
107 * |
|
108 * @since 2.7.0 |
|
109 * |
|
110 * @param string $version Version of HTTP used. Accepts '1.0' and '1.1'. |
|
111 * Default '1.0'. |
|
112 */ |
|
113 'httpversion' => apply_filters( 'http_request_version', '1.0' ), |
|
114 /** |
|
115 * Filter the user agent value sent with an HTTP request. |
|
116 * |
|
117 * @since 2.7.0 |
|
118 * |
|
119 * @param string $user_agent WordPress user agent string. |
|
120 */ |
75 'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ) ), |
121 'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ) ), |
|
122 /** |
|
123 * Filter whether to pass URLs through wp_http_validate_url() in an HTTP request. |
|
124 * |
|
125 * @since 3.6.0 |
|
126 * |
|
127 * @param bool $pass_url Whether to pass URLs through wp_http_validate_url(). |
|
128 * Default false. |
|
129 */ |
76 'reject_unsafe_urls' => apply_filters( 'http_request_reject_unsafe_urls', false ), |
130 'reject_unsafe_urls' => apply_filters( 'http_request_reject_unsafe_urls', false ), |
77 'blocking' => true, |
131 'blocking' => true, |
78 'headers' => array(), |
132 'headers' => array(), |
79 'cookies' => array(), |
133 'cookies' => array(), |
80 'body' => null, |
134 'body' => null, |
93 // By default, Head requests do not cause redirections. |
147 // By default, Head requests do not cause redirections. |
94 if ( isset($args['method']) && 'HEAD' == $args['method'] ) |
148 if ( isset($args['method']) && 'HEAD' == $args['method'] ) |
95 $defaults['redirection'] = 0; |
149 $defaults['redirection'] = 0; |
96 |
150 |
97 $r = wp_parse_args( $args, $defaults ); |
151 $r = wp_parse_args( $args, $defaults ); |
|
152 /** |
|
153 * Filter the arguments used in an HTTP request. |
|
154 * |
|
155 * @since 2.7.0 |
|
156 * |
|
157 * @param array $r An array of HTTP request arguments. |
|
158 * @param string $url The request URL. |
|
159 */ |
98 $r = apply_filters( 'http_request_args', $r, $url ); |
160 $r = apply_filters( 'http_request_args', $r, $url ); |
99 |
161 |
100 // The transports decrement this, store a copy of the original value for loop purposes. |
162 // The transports decrement this, store a copy of the original value for loop purposes. |
101 if ( ! isset( $r['_redirection'] ) ) |
163 if ( ! isset( $r['_redirection'] ) ) |
102 $r['_redirection'] = $r['redirection']; |
164 $r['_redirection'] = $r['redirection']; |
103 |
165 |
104 // Allow plugins to short-circuit the request |
166 /** |
|
167 * Filter whether to preempt an HTTP request's return. |
|
168 * |
|
169 * Returning a truthy value to the filter will short-circuit |
|
170 * the HTTP request and return early with that value. |
|
171 * |
|
172 * @since 2.9.0 |
|
173 * |
|
174 * @param bool $preempt Whether to preempt an HTTP request return. Default false. |
|
175 * @param array $r HTTP request arguments. |
|
176 * @param string $url The request URL. |
|
177 */ |
105 $pre = apply_filters( 'pre_http_request', false, $r, $url ); |
178 $pre = apply_filters( 'pre_http_request', false, $r, $url ); |
106 if ( false !== $pre ) |
179 if ( false !== $pre ) |
107 return $pre; |
180 return $pre; |
108 |
181 |
109 if ( function_exists( 'wp_kses_bad_protocol' ) ) { |
182 if ( function_exists( 'wp_kses_bad_protocol' ) ) { |
110 if ( $r['reject_unsafe_urls'] ) |
183 if ( $r['reject_unsafe_urls'] ) |
111 $url = wp_http_validate_url( $url ); |
184 $url = wp_http_validate_url( $url ); |
112 $url = wp_kses_bad_protocol( $url, array( 'http', 'https', 'ssl' ) ); |
185 if ( $url ) { |
|
186 $url = wp_kses_bad_protocol( $url, array( 'http', 'https', 'ssl' ) ); |
|
187 } |
113 } |
188 } |
114 |
189 |
115 $arrURL = @parse_url( $url ); |
190 $arrURL = @parse_url( $url ); |
116 |
191 |
117 if ( empty( $url ) || empty( $arrURL['scheme'] ) ) |
192 if ( empty( $url ) || empty( $arrURL['scheme'] ) ) |
118 return new WP_Error('http_request_failed', __('A valid URL was not provided.')); |
193 return new WP_Error('http_request_failed', __('A valid URL was not provided.')); |
119 |
194 |
120 if ( $this->block_request( $url ) ) |
195 if ( $this->block_request( $url ) ) |
121 return new WP_Error( 'http_request_failed', __( 'User has blocked requests through HTTP.' ) ); |
196 return new WP_Error( 'http_request_failed', __( 'User has blocked requests through HTTP.' ) ); |
122 |
197 |
123 // Determine if this is a https call and pass that on to the transport functions |
198 /* |
124 // so that we can blacklist the transports that do not support ssl verification |
199 * Determine if this is a https call and pass that on to the transport functions |
|
200 * so that we can blacklist the transports that do not support ssl verification |
|
201 */ |
125 $r['ssl'] = $arrURL['scheme'] == 'https' || $arrURL['scheme'] == 'ssl'; |
202 $r['ssl'] = $arrURL['scheme'] == 'https' || $arrURL['scheme'] == 'ssl'; |
126 |
203 |
127 // Determine if this request is to OUR install of WordPress |
204 // Determine if this request is to OUR install of WordPress. |
128 $homeURL = parse_url( get_bloginfo( 'url' ) ); |
205 $homeURL = parse_url( get_bloginfo( 'url' ) ); |
129 $r['local'] = $homeURL['host'] == $arrURL['host'] || 'localhost' == $arrURL['host']; |
206 $r['local'] = 'localhost' == $arrURL['host'] || ( isset( $homeURL['host'] ) && $homeURL['host'] == $arrURL['host'] ); |
130 unset( $homeURL ); |
207 unset( $homeURL ); |
131 |
208 |
132 // If we are streaming to a file but no filename was given drop it in the WP temp dir |
209 /* |
133 // and pick its name using the basename of the $url |
210 * If we are streaming to a file but no filename was given drop it in the WP temp dir |
134 if ( $r['stream'] && empty( $r['filename'] ) ) |
211 * and pick its name using the basename of the $url. |
135 $r['filename'] = get_temp_dir() . basename( $url ); |
212 */ |
136 |
213 if ( $r['stream'] && empty( $r['filename'] ) ) { |
137 // Force some settings if we are streaming to a file and check for existence and perms of destination directory |
214 $r['filename'] = wp_unique_filename( get_temp_dir(), basename( $url ) ); |
|
215 } |
|
216 |
|
217 /* |
|
218 * Force some settings if we are streaming to a file and check for existence and perms |
|
219 * of destination directory. |
|
220 */ |
138 if ( $r['stream'] ) { |
221 if ( $r['stream'] ) { |
139 $r['blocking'] = true; |
222 $r['blocking'] = true; |
140 if ( ! wp_is_writable( dirname( $r['filename'] ) ) ) |
223 if ( ! wp_is_writable( dirname( $r['filename'] ) ) ) |
141 return new WP_Error( 'http_request_failed', __( 'Destination directory for file streaming does not exist or is not writable.' ) ); |
224 return new WP_Error( 'http_request_failed', __( 'Destination directory for file streaming does not exist or is not writable.' ) ); |
142 } |
225 } |
143 |
226 |
144 if ( is_null( $r['headers'] ) ) |
227 if ( is_null( $r['headers'] ) ) |
145 $r['headers'] = array(); |
228 $r['headers'] = array(); |
146 |
229 |
147 if ( ! is_array( $r['headers'] ) ) { |
230 if ( ! is_array( $r['headers'] ) ) { |
148 $processedHeaders = WP_Http::processHeaders( $r['headers'], $url ); |
231 $processedHeaders = self::processHeaders( $r['headers'], $url ); |
149 $r['headers'] = $processedHeaders['headers']; |
232 $r['headers'] = $processedHeaders['headers']; |
150 } |
233 } |
151 |
234 |
152 if ( isset( $r['headers']['User-Agent'] ) ) { |
235 if ( isset( $r['headers']['User-Agent'] ) ) { |
153 $r['user-agent'] = $r['headers']['User-Agent']; |
236 $r['user-agent'] = $r['headers']['User-Agent']; |
216 * @access private |
299 * @access private |
217 * |
300 * |
218 * @param array $args Request arguments |
301 * @param array $args Request arguments |
219 * @param string $url URL to Request |
302 * @param string $url URL to Request |
220 * |
303 * |
221 * @return string|bool Class name for the first transport that claims to support the request. False if no transport claims to support the request. |
304 * @return string|false Class name for the first transport that claims to support the request. False if no transport claims to support the request. |
222 */ |
305 */ |
223 public function _get_first_available_transport( $args, $url = null ) { |
306 public function _get_first_available_transport( $args, $url = null ) { |
|
307 /** |
|
308 * Filter which HTTP transports are available and in what order. |
|
309 * |
|
310 * @since 3.7.0 |
|
311 * |
|
312 * @param array $value Array of HTTP transports to check. Default array contains |
|
313 * 'curl', and 'streams', in that order. |
|
314 * @param array $args HTTP request arguments. |
|
315 * @param string $url The URL to request. |
|
316 */ |
224 $request_order = apply_filters( 'http_api_transports', array( 'curl', 'streams' ), $args, $url ); |
317 $request_order = apply_filters( 'http_api_transports', array( 'curl', 'streams' ), $args, $url ); |
225 |
318 |
226 // Loop over each transport on each HTTP request looking for one which will serve this request's needs |
319 // Loop over each transport on each HTTP request looking for one which will serve this request's needs. |
227 foreach ( $request_order as $transport ) { |
320 foreach ( $request_order as $transport ) { |
228 $class = 'WP_HTTP_' . $transport; |
321 $class = 'WP_HTTP_' . $transport; |
229 |
322 |
230 // Check to see if this transport is a possibility, calls the transport statically |
323 // Check to see if this transport is a possibility, calls the transport statically. |
231 if ( !call_user_func( array( $class, 'test' ), $args, $url ) ) |
324 if ( !call_user_func( array( $class, 'test' ), $args, $url ) ) |
232 continue; |
325 continue; |
233 |
326 |
234 return $class; |
327 return $class; |
235 } |
328 } |
263 if ( empty( $transports[$class] ) ) |
356 if ( empty( $transports[$class] ) ) |
264 $transports[$class] = new $class; |
357 $transports[$class] = new $class; |
265 |
358 |
266 $response = $transports[$class]->request( $url, $args ); |
359 $response = $transports[$class]->request( $url, $args ); |
267 |
360 |
|
361 /** |
|
362 * Fires after an HTTP API response is received and before the response is returned. |
|
363 * |
|
364 * @since 2.8.0 |
|
365 * |
|
366 * @param array|WP_Error $response HTTP response or WP_Error object. |
|
367 * @param string $context Context under which the hook is fired. |
|
368 * @param string $class HTTP transport used. |
|
369 * @param array $args HTTP request arguments. |
|
370 * @param string $url The request URL. |
|
371 */ |
268 do_action( 'http_api_debug', $response, 'response', $class, $args, $url ); |
372 do_action( 'http_api_debug', $response, 'response', $class, $args, $url ); |
269 |
373 |
270 if ( is_wp_error( $response ) ) |
374 if ( is_wp_error( $response ) ) |
271 return $response; |
375 return $response; |
272 |
376 |
|
377 /** |
|
378 * Filter the HTTP API response immediately before the response is returned. |
|
379 * |
|
380 * @since 2.9.0 |
|
381 * |
|
382 * @param array $response HTTP response. |
|
383 * @param array $args HTTP request arguments. |
|
384 * @param string $url The request URL. |
|
385 */ |
273 return apply_filters( 'http_response', $response, $args, $url ); |
386 return apply_filters( 'http_response', $response, $args, $url ); |
274 } |
387 } |
275 |
388 |
276 /** |
389 /** |
277 * Uses the POST HTTP method. |
390 * Uses the POST HTTP method. |
357 * @param string $url The URL that was requested |
470 * @param string $url The URL that was requested |
358 * @return array Processed string headers. If duplicate headers are encountered, |
471 * @return array Processed string headers. If duplicate headers are encountered, |
359 * Then a numbered array is returned as the value of that header-key. |
472 * Then a numbered array is returned as the value of that header-key. |
360 */ |
473 */ |
361 public static function processHeaders( $headers, $url = '' ) { |
474 public static function processHeaders( $headers, $url = '' ) { |
362 // split headers, one per array element |
475 // Split headers, one per array element. |
363 if ( is_string($headers) ) { |
476 if ( is_string($headers) ) { |
364 // tolerate line terminator: CRLF = LF (RFC 2616 19.3) |
477 // Tolerate line terminator: CRLF = LF (RFC 2616 19.3). |
365 $headers = str_replace("\r\n", "\n", $headers); |
478 $headers = str_replace("\r\n", "\n", $headers); |
366 // unfold folded header fields. LWS = [CRLF] 1*( SP | HT ) <US-ASCII SP, space (32)>, <US-ASCII HT, horizontal-tab (9)> (RFC 2616 2.2) |
479 /* |
|
480 * Unfold folded header fields. LWS = [CRLF] 1*( SP | HT ) <US-ASCII SP, space (32)>, |
|
481 * <US-ASCII HT, horizontal-tab (9)> (RFC 2616 2.2). |
|
482 */ |
367 $headers = preg_replace('/\n[ \t]/', ' ', $headers); |
483 $headers = preg_replace('/\n[ \t]/', ' ', $headers); |
368 // create the headers array |
484 // Create the headers array. |
369 $headers = explode("\n", $headers); |
485 $headers = explode("\n", $headers); |
370 } |
486 } |
371 |
487 |
372 $response = array('code' => 0, 'message' => ''); |
488 $response = array('code' => 0, 'message' => ''); |
373 |
489 |
374 // If a redirection has taken place, The headers for each page request may have been passed. |
490 /* |
375 // In this case, determine the final HTTP header and parse from there. |
491 * If a redirection has taken place, The headers for each page request may have been passed. |
|
492 * In this case, determine the final HTTP header and parse from there. |
|
493 */ |
376 for ( $i = count($headers)-1; $i >= 0; $i-- ) { |
494 for ( $i = count($headers)-1; $i >= 0; $i-- ) { |
377 if ( !empty($headers[$i]) && false === strpos($headers[$i], ':') ) { |
495 if ( !empty($headers[$i]) && false === strpos($headers[$i], ':') ) { |
378 $headers = array_splice($headers, $i); |
496 $headers = array_splice($headers, $i); |
379 break; |
497 break; |
380 } |
498 } |
461 // The body is not chunked encoded or is malformed. |
582 // The body is not chunked encoded or is malformed. |
462 if ( ! preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', trim( $body ) ) ) |
583 if ( ! preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', trim( $body ) ) ) |
463 return $body; |
584 return $body; |
464 |
585 |
465 $parsed_body = ''; |
586 $parsed_body = ''; |
466 $body_original = $body; // We'll be altering $body, so need a backup in case of error |
587 |
|
588 // We'll be altering $body, so need a backup in case of error. |
|
589 $body_original = $body; |
467 |
590 |
468 while ( true ) { |
591 while ( true ) { |
469 $has_chunk = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $body, $match ); |
592 $has_chunk = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $body, $match ); |
470 if ( ! $has_chunk || empty( $match[1] ) ) |
593 if ( ! $has_chunk || empty( $match[1] ) ) |
471 return $body_original; |
594 return $body_original; |
472 |
595 |
473 $length = hexdec( $match[1] ); |
596 $length = hexdec( $match[1] ); |
474 $chunk_length = strlen( $match[0] ); |
597 $chunk_length = strlen( $match[0] ); |
475 |
598 |
476 // Parse out the chunk of data |
599 // Parse out the chunk of data. |
477 $parsed_body .= substr( $body, $chunk_length, $length ); |
600 $parsed_body .= substr( $body, $chunk_length, $length ); |
478 |
601 |
479 // Remove the chunk from the raw data |
602 // Remove the chunk from the raw data. |
480 $body = substr( $body, $length + $chunk_length ); |
603 $body = substr( $body, $length + $chunk_length ); |
481 |
604 |
482 // End of document |
605 // End of the document. |
483 if ( '0' === trim( $body ) ) |
606 if ( '0' === trim( $body ) ) |
484 return $parsed_body; |
607 return $parsed_body; |
485 } |
608 } |
486 } |
609 } |
487 |
610 |
496 * WP_ACCESSIBLE_HOSTS will allow additional hosts to go through for requests. The format of the |
619 * WP_ACCESSIBLE_HOSTS will allow additional hosts to go through for requests. The format of the |
497 * WP_ACCESSIBLE_HOSTS constant is a comma separated list of hostnames to allow, wildcard domains |
620 * WP_ACCESSIBLE_HOSTS constant is a comma separated list of hostnames to allow, wildcard domains |
498 * are supported, eg *.wordpress.org will allow for all subdomains of wordpress.org to be contacted. |
621 * are supported, eg *.wordpress.org will allow for all subdomains of wordpress.org to be contacted. |
499 * |
622 * |
500 * @since 2.8.0 |
623 * @since 2.8.0 |
501 * @link http://core.trac.wordpress.org/ticket/8927 Allow preventing external requests. |
624 * @link https://core.trac.wordpress.org/ticket/8927 Allow preventing external requests. |
502 * @link http://core.trac.wordpress.org/ticket/14636 Allow wildcard domains in WP_ACCESSIBLE_HOSTS |
625 * @link https://core.trac.wordpress.org/ticket/14636 Allow wildcard domains in WP_ACCESSIBLE_HOSTS |
503 * |
626 * |
504 * @param string $uri URI of url. |
627 * @param string $uri URI of url. |
505 * @return bool True to block, false to allow. |
628 * @return bool True to block, false to allow. |
506 */ |
629 */ |
507 function block_request($uri) { |
630 public function block_request($uri) { |
508 // We don't need to block requests, because nothing is blocked. |
631 // We don't need to block requests, because nothing is blocked. |
509 if ( ! defined( 'WP_HTTP_BLOCK_EXTERNAL' ) || ! WP_HTTP_BLOCK_EXTERNAL ) |
632 if ( ! defined( 'WP_HTTP_BLOCK_EXTERNAL' ) || ! WP_HTTP_BLOCK_EXTERNAL ) |
510 return false; |
633 return false; |
511 |
634 |
512 $check = parse_url($uri); |
635 $check = parse_url($uri); |
513 if ( ! $check ) |
636 if ( ! $check ) |
514 return true; |
637 return true; |
515 |
638 |
516 $home = parse_url( get_option('siteurl') ); |
639 $home = parse_url( get_option('siteurl') ); |
517 |
640 |
518 // Don't block requests back to ourselves by default |
641 // Don't block requests back to ourselves by default. |
519 if ( $check['host'] == 'localhost' || $check['host'] == $home['host'] ) |
642 if ( 'localhost' == $check['host'] || ( isset( $home['host'] ) && $home['host'] == $check['host'] ) ) { |
520 return apply_filters('block_local_requests', false); |
643 /** |
|
644 * Filter whether to block local requests through the proxy. |
|
645 * |
|
646 * @since 2.8.0 |
|
647 * |
|
648 * @param bool $block Whether to block local requests through proxy. |
|
649 * Default false. |
|
650 */ |
|
651 return apply_filters( 'block_local_requests', false ); |
|
652 } |
521 |
653 |
522 if ( !defined('WP_ACCESSIBLE_HOSTS') ) |
654 if ( !defined('WP_ACCESSIBLE_HOSTS') ) |
523 return true; |
655 return true; |
524 |
656 |
525 static $accessible_hosts; |
657 static $accessible_hosts; |
540 else |
672 else |
541 return !in_array( $check['host'], $accessible_hosts ); //Inverse logic, If it's in the array, then we can't access it. |
673 return !in_array( $check['host'], $accessible_hosts ); //Inverse logic, If it's in the array, then we can't access it. |
542 |
674 |
543 } |
675 } |
544 |
676 |
545 static function make_absolute_url( $maybe_relative_path, $url ) { |
677 /** |
|
678 * A wrapper for PHP's parse_url() function that handles edgecases in < PHP 5.4.7 |
|
679 * |
|
680 * PHP 5.4.7 expanded parse_url()'s ability to handle non-absolute url's, including |
|
681 * schemeless and relative url's with :// in the path, this works around those |
|
682 * limitations providing a standard output on PHP 5.2~5.4+. |
|
683 * |
|
684 * Error suppression is used as prior to PHP 5.3.3, an E_WARNING would be generated |
|
685 * when URL parsing failed. |
|
686 * |
|
687 * @since 4.1.0 |
|
688 * @access protected |
|
689 * |
|
690 * @param string $url The URL to parse. |
|
691 * @return bool|array False on failure; Array of URL components on success; |
|
692 * See parse_url()'s return values. |
|
693 */ |
|
694 protected static function parse_url( $url ) { |
|
695 $parts = @parse_url( $url ); |
|
696 if ( ! $parts ) { |
|
697 // < PHP 5.4.7 compat, trouble with relative paths including a scheme break in the path |
|
698 if ( '/' == $url[0] && false !== strpos( $url, '://' ) ) { |
|
699 // Since we know it's a relative path, prefix with a scheme/host placeholder and try again |
|
700 if ( ! $parts = @parse_url( 'placeholder://placeholder' . $url ) ) { |
|
701 return $parts; |
|
702 } |
|
703 // Remove the placeholder values |
|
704 unset( $parts['scheme'], $parts['host'] ); |
|
705 } else { |
|
706 return $parts; |
|
707 } |
|
708 } |
|
709 |
|
710 // < PHP 5.4.7 compat, doesn't detect schemeless URL's host field |
|
711 if ( '//' == substr( $url, 0, 2 ) && ! isset( $parts['host'] ) ) { |
|
712 list( $parts['host'], $slashless_path ) = explode( '/', substr( $parts['path'], 2 ), 2 ); |
|
713 $parts['path'] = "/{$slashless_path}"; |
|
714 } |
|
715 |
|
716 return $parts; |
|
717 } |
|
718 |
|
719 /** |
|
720 * Converts a relative URL to an absolute URL relative to a given URL. |
|
721 * |
|
722 * If an Absolute URL is provided, no processing of that URL is done. |
|
723 * |
|
724 * @since 3.4.0 |
|
725 * |
|
726 * @access public |
|
727 * @param string $maybe_relative_path The URL which might be relative |
|
728 * @param string $url The URL which $maybe_relative_path is relative to |
|
729 * @return string An Absolute URL, in a failure condition where the URL cannot be parsed, the relative URL will be returned. |
|
730 */ |
|
731 public static function make_absolute_url( $maybe_relative_path, $url ) { |
546 if ( empty( $url ) ) |
732 if ( empty( $url ) ) |
547 return $maybe_relative_path; |
733 return $maybe_relative_path; |
548 |
734 |
549 // Check for a scheme |
735 if ( ! $url_parts = WP_HTTP::parse_url( $url ) ) { |
550 if ( false !== strpos( $maybe_relative_path, '://' ) ) |
|
551 return $maybe_relative_path; |
736 return $maybe_relative_path; |
552 |
737 } |
553 if ( ! $url_parts = @parse_url( $url ) ) |
738 |
|
739 if ( ! $relative_url_parts = WP_HTTP::parse_url( $maybe_relative_path ) ) { |
554 return $maybe_relative_path; |
740 return $maybe_relative_path; |
555 |
741 } |
556 if ( ! $relative_url_parts = @parse_url( $maybe_relative_path ) ) |
742 |
|
743 // Check for a scheme on the 'relative' url |
|
744 if ( ! empty( $relative_url_parts['scheme'] ) ) { |
557 return $maybe_relative_path; |
745 return $maybe_relative_path; |
558 |
746 } |
559 $absolute_path = $url_parts['scheme'] . '://' . $url_parts['host']; |
747 |
560 if ( isset( $url_parts['port'] ) ) |
748 $absolute_path = $url_parts['scheme'] . '://'; |
561 $absolute_path .= ':' . $url_parts['port']; |
749 |
562 |
750 // 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 |
563 // Start off with the Absolute URL path |
751 if ( isset( $relative_url_parts['host'] ) ) { |
|
752 $absolute_path .= $relative_url_parts['host']; |
|
753 if ( isset( $relative_url_parts['port'] ) ) |
|
754 $absolute_path .= ':' . $relative_url_parts['port']; |
|
755 } else { |
|
756 $absolute_path .= $url_parts['host']; |
|
757 if ( isset( $url_parts['port'] ) ) |
|
758 $absolute_path .= ':' . $url_parts['port']; |
|
759 } |
|
760 |
|
761 // Start off with the Absolute URL path. |
564 $path = ! empty( $url_parts['path'] ) ? $url_parts['path'] : '/'; |
762 $path = ! empty( $url_parts['path'] ) ? $url_parts['path'] : '/'; |
565 |
763 |
566 // If it's a root-relative path, then great |
764 // If it's a root-relative path, then great. |
567 if ( ! empty( $relative_url_parts['path'] ) && '/' == $relative_url_parts['path'][0] ) { |
765 if ( ! empty( $relative_url_parts['path'] ) && '/' == $relative_url_parts['path'][0] ) { |
568 $path = $relative_url_parts['path']; |
766 $path = $relative_url_parts['path']; |
569 |
767 |
570 // Else it's a relative path |
768 // Else it's a relative path. |
571 } elseif ( ! empty( $relative_url_parts['path'] ) ) { |
769 } elseif ( ! empty( $relative_url_parts['path'] ) ) { |
572 // Strip off any file components from the absolute path |
770 // Strip off any file components from the absolute path. |
573 $path = substr( $path, 0, strrpos( $path, '/' ) + 1 ); |
771 $path = substr( $path, 0, strrpos( $path, '/' ) + 1 ); |
574 |
772 |
575 // Build the new path |
773 // Build the new path. |
576 $path .= $relative_url_parts['path']; |
774 $path .= $relative_url_parts['path']; |
577 |
775 |
578 // Strip all /path/../ out of the path |
776 // Strip all /path/../ out of the path. |
579 while ( strpos( $path, '../' ) > 1 ) { |
777 while ( strpos( $path, '../' ) > 1 ) { |
580 $path = preg_replace( '![^/]+/\.\./!', '', $path ); |
778 $path = preg_replace( '![^/]+/\.\./!', '', $path ); |
581 } |
779 } |
582 |
780 |
583 // Strip any final leading ../ from the path |
781 // Strip any final leading ../ from the path. |
584 $path = preg_replace( '!^/(\.\./)+!', '', $path ); |
782 $path = preg_replace( '!^/(\.\./)+!', '', $path ); |
585 } |
783 } |
586 |
784 |
587 // Add the Query string |
785 // Add the Query string. |
588 if ( ! empty( $relative_url_parts['query'] ) ) |
786 if ( ! empty( $relative_url_parts['query'] ) ) |
589 $path .= '?' . $relative_url_parts['query']; |
787 $path .= '?' . $relative_url_parts['query']; |
590 |
788 |
591 return $absolute_path . '/' . ltrim( $path, '/' ); |
789 return $absolute_path . '/' . ltrim( $path, '/' ); |
592 } |
790 } |
595 * Handles HTTP Redirects and follows them if appropriate. |
793 * Handles HTTP Redirects and follows them if appropriate. |
596 * |
794 * |
597 * @since 3.7.0 |
795 * @since 3.7.0 |
598 * |
796 * |
599 * @param string $url The URL which was requested. |
797 * @param string $url The URL which was requested. |
600 * @param array $args The Arguements which were used to make the request. |
798 * @param array $args The Arguments which were used to make the request. |
601 * @param array $response The Response of the HTTP request. |
799 * @param array $response The Response of the HTTP request. |
602 * @return false|object False if no redirect is present, a WP_HTTP or WP_Error result otherwise. |
800 * @return false|object False if no redirect is present, a WP_HTTP or WP_Error result otherwise. |
603 */ |
801 */ |
604 static function handle_redirects( $url, $args, $response ) { |
802 public static function handle_redirects( $url, $args, $response ) { |
605 // If no redirects are present, or, redirects were not requested, perform no action. |
803 // If no redirects are present, or, redirects were not requested, perform no action. |
606 if ( ! isset( $response['headers']['location'] ) || 0 === $args['_redirection'] ) |
804 if ( ! isset( $response['headers']['location'] ) || 0 === $args['_redirection'] ) |
607 return false; |
805 return false; |
608 |
806 |
609 // Only perform redirections on redirection http codes |
807 // Only perform redirections on redirection http codes. |
610 if ( $response['response']['code'] > 399 || $response['response']['code'] < 300 ) |
808 if ( $response['response']['code'] > 399 || $response['response']['code'] < 300 ) |
611 return false; |
809 return false; |
612 |
810 |
613 // Don't redirect if we've run out of redirects |
811 // Don't redirect if we've run out of redirects. |
614 if ( $args['redirection']-- <= 0 ) |
812 if ( $args['redirection']-- <= 0 ) |
615 return new WP_Error( 'http_request_failed', __('Too many redirects.') ); |
813 return new WP_Error( 'http_request_failed', __('Too many redirects.') ); |
616 |
814 |
617 $redirect_location = $response['headers']['location']; |
815 $redirect_location = $response['headers']['location']; |
618 |
816 |
619 // If there were multiple Location headers, use the last header specified |
817 // If there were multiple Location headers, use the last header specified. |
620 if ( is_array( $redirect_location ) ) |
818 if ( is_array( $redirect_location ) ) |
621 $redirect_location = array_pop( $redirect_location ); |
819 $redirect_location = array_pop( $redirect_location ); |
622 |
820 |
623 $redirect_location = WP_HTTP::make_absolute_url( $redirect_location, $url ); |
821 $redirect_location = WP_HTTP::make_absolute_url( $redirect_location, $url ); |
624 |
822 |
625 // POST requests should not POST to a redirected location |
823 // POST requests should not POST to a redirected location. |
626 if ( 'POST' == $args['method'] ) { |
824 if ( 'POST' == $args['method'] ) { |
627 if ( in_array( $response['response']['code'], array( 302, 303 ) ) ) |
825 if ( in_array( $response['response']['code'], array( 302, 303 ) ) ) |
628 $args['method'] = 'GET'; |
826 $args['method'] = 'GET'; |
629 } |
827 } |
630 |
828 |
631 // Include valid cookies in the redirect process |
829 // Include valid cookies in the redirect process. |
632 if ( ! empty( $response['cookies'] ) ) { |
830 if ( ! empty( $response['cookies'] ) ) { |
633 foreach ( $response['cookies'] as $cookie ) { |
831 foreach ( $response['cookies'] as $cookie ) { |
634 if ( $cookie->test( $redirect_location ) ) |
832 if ( $cookie->test( $redirect_location ) ) |
635 $args['cookies'][] = $cookie; |
833 $args['cookies'][] = $cookie; |
636 } |
834 } |
684 * |
879 * |
685 * @since 2.7.0 |
880 * @since 2.7.0 |
686 * @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client(). |
881 * @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client(). |
687 * |
882 * |
688 * @access public |
883 * @access public |
689 * @param string $url URI resource. |
884 * @param string $url The request URL. |
690 * @param string|array $args Optional. Override the defaults. |
885 * @param string|array $args Optional. Override the defaults. |
691 * @return array 'headers', 'body', 'response', 'cookies' and 'filename' keys. |
886 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error |
692 */ |
887 */ |
693 function request($url, $args = array()) { |
888 public function request($url, $args = array()) { |
694 $defaults = array( |
889 $defaults = array( |
695 'method' => 'GET', 'timeout' => 5, |
890 'method' => 'GET', 'timeout' => 5, |
696 'redirection' => 5, 'httpversion' => '1.0', |
891 'redirection' => 5, 'httpversion' => '1.0', |
697 'blocking' => true, |
892 'blocking' => true, |
698 'headers' => array(), 'body' => null, 'cookies' => array() |
893 'headers' => array(), 'body' => null, 'cookies' => array() |
699 ); |
894 ); |
700 |
895 |
701 $r = wp_parse_args( $args, $defaults ); |
896 $r = wp_parse_args( $args, $defaults ); |
702 |
897 |
703 if ( isset($r['headers']['User-Agent']) ) { |
898 if ( isset( $r['headers']['User-Agent'] ) ) { |
704 $r['user-agent'] = $r['headers']['User-Agent']; |
899 $r['user-agent'] = $r['headers']['User-Agent']; |
705 unset($r['headers']['User-Agent']); |
900 unset( $r['headers']['User-Agent'] ); |
706 } else if ( isset($r['headers']['user-agent']) ) { |
901 } elseif ( isset( $r['headers']['user-agent'] ) ) { |
707 $r['user-agent'] = $r['headers']['user-agent']; |
902 $r['user-agent'] = $r['headers']['user-agent']; |
708 unset($r['headers']['user-agent']); |
903 unset( $r['headers']['user-agent'] ); |
709 } |
904 } |
710 |
905 |
711 // Construct Cookie: header if any cookies are set |
906 // Construct Cookie: header if any cookies are set. |
712 WP_Http::buildCookieHeader( $r ); |
907 WP_Http::buildCookieHeader( $r ); |
713 |
908 |
714 $arrURL = parse_url($url); |
909 $arrURL = parse_url($url); |
715 |
910 |
716 $connect_host = $arrURL['host']; |
911 $connect_host = $arrURL['host']; |
723 } else { |
918 } else { |
724 $arrURL['port'] = 80; |
919 $arrURL['port'] = 80; |
725 } |
920 } |
726 } |
921 } |
727 |
922 |
|
923 // Always pass a Path, defaulting to the root in cases such as http://example.com |
|
924 if ( ! isset( $arrURL['path'] ) ) { |
|
925 $arrURL['path'] = '/'; |
|
926 } |
|
927 |
728 if ( isset( $r['headers']['Host'] ) || isset( $r['headers']['host'] ) ) { |
928 if ( isset( $r['headers']['Host'] ) || isset( $r['headers']['host'] ) ) { |
729 if ( isset( $r['headers']['Host'] ) ) |
929 if ( isset( $r['headers']['Host'] ) ) |
730 $arrURL['host'] = $r['headers']['Host']; |
930 $arrURL['host'] = $r['headers']['Host']; |
731 else |
931 else |
732 $arrURL['host'] = $r['headers']['host']; |
932 $arrURL['host'] = $r['headers']['host']; |
733 unset( $r['headers']['Host'], $r['headers']['host'] ); |
933 unset( $r['headers']['Host'], $r['headers']['host'] ); |
734 } |
934 } |
735 |
935 |
736 // Certain versions of PHP have issues with 'localhost' and IPv6, It attempts to connect to ::1, |
936 /* |
737 // which fails when the server is not set up for it. For compatibility, always connect to the IPv4 address. |
937 * Certain versions of PHP have issues with 'localhost' and IPv6, It attempts to connect |
|
938 * to ::1, which fails when the server is not set up for it. For compatibility, always |
|
939 * connect to the IPv4 address. |
|
940 */ |
738 if ( 'localhost' == strtolower( $connect_host ) ) |
941 if ( 'localhost' == strtolower( $connect_host ) ) |
739 $connect_host = '127.0.0.1'; |
942 $connect_host = '127.0.0.1'; |
740 |
943 |
741 $connect_host = $secure_transport ? 'ssl://' . $connect_host : 'tcp://' . $connect_host; |
944 $connect_host = $secure_transport ? 'ssl://' . $connect_host : 'tcp://' . $connect_host; |
742 |
945 |
743 $is_local = isset( $r['local'] ) && $r['local']; |
946 $is_local = isset( $r['local'] ) && $r['local']; |
744 $ssl_verify = isset( $r['sslverify'] ) && $r['sslverify']; |
947 $ssl_verify = isset( $r['sslverify'] ) && $r['sslverify']; |
745 if ( $is_local ) |
948 if ( $is_local ) { |
|
949 /** |
|
950 * Filter whether SSL should be verified for local requests. |
|
951 * |
|
952 * @since 2.8.0 |
|
953 * |
|
954 * @param bool $ssl_verify Whether to verify the SSL connection. Default true. |
|
955 */ |
746 $ssl_verify = apply_filters( 'https_local_ssl_verify', $ssl_verify ); |
956 $ssl_verify = apply_filters( 'https_local_ssl_verify', $ssl_verify ); |
747 elseif ( ! $is_local ) |
957 } elseif ( ! $is_local ) { |
|
958 /** |
|
959 * Filter whether SSL should be verified for non-local requests. |
|
960 * |
|
961 * @since 2.8.0 |
|
962 * |
|
963 * @param bool $ssl_verify Whether to verify the SSL connection. Default true. |
|
964 */ |
748 $ssl_verify = apply_filters( 'https_ssl_verify', $ssl_verify ); |
965 $ssl_verify = apply_filters( 'https_ssl_verify', $ssl_verify ); |
|
966 } |
749 |
967 |
750 $proxy = new WP_HTTP_Proxy(); |
968 $proxy = new WP_HTTP_Proxy(); |
751 |
969 |
752 $context = stream_context_create( array( |
970 $context = stream_context_create( array( |
753 'ssl' => array( |
971 'ssl' => array( |
762 |
980 |
763 $timeout = (int) floor( $r['timeout'] ); |
981 $timeout = (int) floor( $r['timeout'] ); |
764 $utimeout = $timeout == $r['timeout'] ? 0 : 1000000 * $r['timeout'] % 1000000; |
982 $utimeout = $timeout == $r['timeout'] ? 0 : 1000000 * $r['timeout'] % 1000000; |
765 $connect_timeout = max( $timeout, 1 ); |
983 $connect_timeout = max( $timeout, 1 ); |
766 |
984 |
767 $connection_error = null; // Store error number |
985 // Store error number. |
768 $connection_error_str = null; // Store error string |
986 $connection_error = null; |
|
987 |
|
988 // Store error string. |
|
989 $connection_error_str = null; |
769 |
990 |
770 if ( !WP_DEBUG ) { |
991 if ( !WP_DEBUG ) { |
771 // In the event that the SSL connection fails, silence the many PHP Warnings |
992 // In the event that the SSL connection fails, silence the many PHP Warnings. |
772 if ( $secure_transport ) |
993 if ( $secure_transport ) |
773 $error_reporting = error_reporting(0); |
994 $error_reporting = error_reporting(0); |
774 |
995 |
775 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) |
996 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) |
776 $handle = @stream_socket_client( 'tcp://' . $proxy->host() . ':' . $proxy->port(), $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); |
997 $handle = @stream_socket_client( 'tcp://' . $proxy->host() . ':' . $proxy->port(), $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); |
786 else |
1007 else |
787 $handle = stream_socket_client( $connect_host . ':' . $arrURL['port'], $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); |
1008 $handle = stream_socket_client( $connect_host . ':' . $arrURL['port'], $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); |
788 } |
1009 } |
789 |
1010 |
790 if ( false === $handle ) { |
1011 if ( false === $handle ) { |
791 // SSL connection failed due to expired/invalid cert, or, OpenSSL configuration is broken |
1012 // SSL connection failed due to expired/invalid cert, or, OpenSSL configuration is broken. |
792 if ( $secure_transport && 0 === $connection_error && '' === $connection_error_str ) |
1013 if ( $secure_transport && 0 === $connection_error && '' === $connection_error_str ) |
793 return new WP_Error( 'http_request_failed', __( 'The SSL certificate for the host could not be verified.' ) ); |
1014 return new WP_Error( 'http_request_failed', __( 'The SSL certificate for the host could not be verified.' ) ); |
794 |
1015 |
795 return new WP_Error('http_request_failed', $connection_error . ': ' . $connection_error_str ); |
1016 return new WP_Error('http_request_failed', $connection_error . ': ' . $connection_error_str ); |
796 } |
1017 } |
797 |
1018 |
798 // Verify that the SSL certificate is valid for this request |
1019 // Verify that the SSL certificate is valid for this request. |
799 if ( $secure_transport && $ssl_verify && ! $proxy->is_enabled() ) { |
1020 if ( $secure_transport && $ssl_verify && ! $proxy->is_enabled() ) { |
800 if ( ! self::verify_ssl_certificate( $handle, $arrURL['host'] ) ) |
1021 if ( ! self::verify_ssl_certificate( $handle, $arrURL['host'] ) ) |
801 return new WP_Error( 'http_request_failed', __( 'The SSL certificate for the host could not be verified.' ) ); |
1022 return new WP_Error( 'http_request_failed', __( 'The SSL certificate for the host could not be verified.' ) ); |
802 } |
1023 } |
803 |
1024 |
915 |
1142 |
916 $arrHeaders = WP_Http::processHeaders( $process['headers'], $url ); |
1143 $arrHeaders = WP_Http::processHeaders( $process['headers'], $url ); |
917 |
1144 |
918 $response = array( |
1145 $response = array( |
919 'headers' => $arrHeaders['headers'], |
1146 'headers' => $arrHeaders['headers'], |
920 'body' => null, // Not yet processed |
1147 // Not yet processed. |
|
1148 'body' => null, |
921 'response' => $arrHeaders['response'], |
1149 'response' => $arrHeaders['response'], |
922 'cookies' => $arrHeaders['cookies'], |
1150 'cookies' => $arrHeaders['cookies'], |
923 'filename' => $r['filename'] |
1151 'filename' => $r['filename'] |
924 ); |
1152 ); |
925 |
1153 |
926 // Handle redirects |
1154 // Handle redirects. |
927 if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) ) |
1155 if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) ) |
928 return $redirect_response; |
1156 return $redirect_response; |
929 |
1157 |
930 // If the body was chunk encoded, then decode it. |
1158 // If the body was chunk encoded, then decode it. |
931 if ( ! empty( $process['body'] ) && isset( $arrHeaders['headers']['transfer-encoding'] ) && 'chunked' == $arrHeaders['headers']['transfer-encoding'] ) |
1159 if ( ! empty( $process['body'] ) && isset( $arrHeaders['headers']['transfer-encoding'] ) && 'chunked' == $arrHeaders['headers']['transfer-encoding'] ) |
957 * |
1185 * |
958 * @param stream $stream The PHP Stream which the SSL request is being made over |
1186 * @param stream $stream The PHP Stream which the SSL request is being made over |
959 * @param string $host The hostname being requested |
1187 * @param string $host The hostname being requested |
960 * @return bool If the cerficiate presented in $stream is valid for $host |
1188 * @return bool If the cerficiate presented in $stream is valid for $host |
961 */ |
1189 */ |
962 static function verify_ssl_certificate( $stream, $host ) { |
1190 public static function verify_ssl_certificate( $stream, $host ) { |
963 $context_options = stream_context_get_options( $stream ); |
1191 $context_options = stream_context_get_options( $stream ); |
964 |
1192 |
965 if ( empty( $context_options['ssl']['peer_certificate'] ) ) |
1193 if ( empty( $context_options['ssl']['peer_certificate'] ) ) |
966 return false; |
1194 return false; |
967 |
1195 |
968 $cert = openssl_x509_parse( $context_options['ssl']['peer_certificate'] ); |
1196 $cert = openssl_x509_parse( $context_options['ssl']['peer_certificate'] ); |
969 if ( ! $cert ) |
1197 if ( ! $cert ) |
970 return false; |
1198 return false; |
971 |
1199 |
972 // If the request is being made to an IP address, we'll validate against IP fields in the cert (if they exist) |
1200 /* |
|
1201 * If the request is being made to an IP address, we'll validate against IP fields |
|
1202 * in the cert (if they exist) |
|
1203 */ |
973 $host_type = ( WP_HTTP::is_ip_address( $host ) ? 'ip' : 'dns' ); |
1204 $host_type = ( WP_HTTP::is_ip_address( $host ) ? 'ip' : 'dns' ); |
974 |
1205 |
975 $certificate_hostnames = array(); |
1206 $certificate_hostnames = array(); |
976 if ( ! empty( $cert['extensions']['subjectAltName'] ) ) { |
1207 if ( ! empty( $cert['extensions']['subjectAltName'] ) ) { |
977 $match_against = preg_split( '/,\s*/', $cert['extensions']['subjectAltName'] ); |
1208 $match_against = preg_split( '/,\s*/', $cert['extensions']['subjectAltName'] ); |
979 list( $match_type, $match_host ) = explode( ':', $match ); |
1210 list( $match_type, $match_host ) = explode( ':', $match ); |
980 if ( $host_type == strtolower( trim( $match_type ) ) ) // IP: or DNS: |
1211 if ( $host_type == strtolower( trim( $match_type ) ) ) // IP: or DNS: |
981 $certificate_hostnames[] = strtolower( trim( $match_host ) ); |
1212 $certificate_hostnames[] = strtolower( trim( $match_host ) ); |
982 } |
1213 } |
983 } elseif ( !empty( $cert['subject']['CN'] ) ) { |
1214 } elseif ( !empty( $cert['subject']['CN'] ) ) { |
984 // Only use the CN when the certificate includes no subjectAltName extension |
1215 // Only use the CN when the certificate includes no subjectAltName extension. |
985 $certificate_hostnames[] = strtolower( $cert['subject']['CN'] ); |
1216 $certificate_hostnames[] = strtolower( $cert['subject']['CN'] ); |
986 } |
1217 } |
987 |
1218 |
988 // Exact hostname/IP matches |
1219 // Exact hostname/IP matches. |
989 if ( in_array( strtolower( $host ), $certificate_hostnames ) ) |
1220 if ( in_array( strtolower( $host ), $certificate_hostnames ) ) |
990 return true; |
1221 return true; |
991 |
1222 |
992 // IP's can't be wildcards, Stop processing |
1223 // IP's can't be wildcards, Stop processing. |
993 if ( 'ip' == $host_type ) |
1224 if ( 'ip' == $host_type ) |
994 return false; |
1225 return false; |
995 |
1226 |
996 // Test to see if the domain is at least 2 deep for wildcard support |
1227 // Test to see if the domain is at least 2 deep for wildcard support. |
997 if ( substr_count( $host, '.' ) < 2 ) |
1228 if ( substr_count( $host, '.' ) < 2 ) |
998 return false; |
1229 return false; |
999 |
1230 |
1000 // Wildcard subdomains certs (*.example.com) are valid for a.example.com but not a.b.example.com |
1231 // Wildcard subdomains certs (*.example.com) are valid for a.example.com but not a.b.example.com. |
1001 $wildcard_host = preg_replace( '/^[^.]+\./', '*.', $host ); |
1232 $wildcard_host = preg_replace( '/^[^.]+\./', '*.', $host ); |
1002 |
1233 |
1003 return in_array( strtolower( $wildcard_host ), $certificate_hostnames ); |
1234 return in_array( strtolower( $wildcard_host ), $certificate_hostnames ); |
1004 } |
1235 } |
1005 |
1236 |
1006 /** |
1237 /** |
1007 * Whether this class can be used for retrieving an URL. |
1238 * Whether this class can be used for retrieving a URL. |
1008 * |
1239 * |
1009 * @static |
1240 * @static |
1010 * @access public |
1241 * @access public |
1011 * @since 2.7.0 |
1242 * @since 2.7.0 |
1012 * @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client(). |
1243 * @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client(). |
1094 * @var resource |
1330 * @var resource |
1095 */ |
1331 */ |
1096 private $stream_handle = false; |
1332 private $stream_handle = false; |
1097 |
1333 |
1098 /** |
1334 /** |
|
1335 * The total bytes written in the current request. |
|
1336 * |
|
1337 * @since 4.1.0 |
|
1338 * @access private |
|
1339 * @var int |
|
1340 */ |
|
1341 private $bytes_written_total = 0; |
|
1342 |
|
1343 /** |
1099 * Send a HTTP request to a URI using cURL extension. |
1344 * Send a HTTP request to a URI using cURL extension. |
1100 * |
1345 * |
1101 * @access public |
1346 * @access public |
1102 * @since 2.7.0 |
1347 * @since 2.7.0 |
1103 * |
1348 * |
1104 * @param string $url |
1349 * @param string $url The request URL. |
1105 * @param str|array $args Optional. Override the defaults. |
1350 * @param string|array $args Optional. Override the defaults. |
1106 * @return array 'headers', 'body', 'response', 'cookies' and 'filename' keys. |
1351 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error |
1107 */ |
1352 */ |
1108 function request($url, $args = array()) { |
1353 public function request($url, $args = array()) { |
1109 $defaults = array( |
1354 $defaults = array( |
1110 'method' => 'GET', 'timeout' => 5, |
1355 'method' => 'GET', 'timeout' => 5, |
1111 'redirection' => 5, 'httpversion' => '1.0', |
1356 'redirection' => 5, 'httpversion' => '1.0', |
1112 'blocking' => true, |
1357 'blocking' => true, |
1113 'headers' => array(), 'body' => null, 'cookies' => array() |
1358 'headers' => array(), 'body' => null, 'cookies' => array() |
1114 ); |
1359 ); |
1115 |
1360 |
1116 $r = wp_parse_args( $args, $defaults ); |
1361 $r = wp_parse_args( $args, $defaults ); |
1117 |
1362 |
1118 if ( isset($r['headers']['User-Agent']) ) { |
1363 if ( isset( $r['headers']['User-Agent'] ) ) { |
1119 $r['user-agent'] = $r['headers']['User-Agent']; |
1364 $r['user-agent'] = $r['headers']['User-Agent']; |
1120 unset($r['headers']['User-Agent']); |
1365 unset( $r['headers']['User-Agent'] ); |
1121 } else if ( isset($r['headers']['user-agent']) ) { |
1366 } elseif ( isset( $r['headers']['user-agent'] ) ) { |
1122 $r['user-agent'] = $r['headers']['user-agent']; |
1367 $r['user-agent'] = $r['headers']['user-agent']; |
1123 unset($r['headers']['user-agent']); |
1368 unset( $r['headers']['user-agent'] ); |
1124 } |
1369 } |
1125 |
1370 |
1126 // Construct Cookie: header if any cookies are set. |
1371 // Construct Cookie: header if any cookies are set. |
1127 WP_Http::buildCookieHeader( $r ); |
1372 WP_Http::buildCookieHeader( $r ); |
1128 |
1373 |
1143 } |
1388 } |
1144 } |
1389 } |
1145 |
1390 |
1146 $is_local = isset($r['local']) && $r['local']; |
1391 $is_local = isset($r['local']) && $r['local']; |
1147 $ssl_verify = isset($r['sslverify']) && $r['sslverify']; |
1392 $ssl_verify = isset($r['sslverify']) && $r['sslverify']; |
1148 if ( $is_local ) |
1393 if ( $is_local ) { |
1149 $ssl_verify = apply_filters('https_local_ssl_verify', $ssl_verify); |
1394 /** This filter is documented in wp-includes/class-http.php */ |
1150 elseif ( ! $is_local ) |
1395 $ssl_verify = apply_filters( 'https_local_ssl_verify', $ssl_verify ); |
1151 $ssl_verify = apply_filters('https_ssl_verify', $ssl_verify); |
1396 } elseif ( ! $is_local ) { |
1152 |
1397 /** This filter is documented in wp-includes/class-http.php */ |
1153 // CURLOPT_TIMEOUT and CURLOPT_CONNECTTIMEOUT expect integers. Have to use ceil since |
1398 $ssl_verify = apply_filters( 'https_ssl_verify', $ssl_verify ); |
1154 // a value of 0 will allow an unlimited timeout. |
1399 } |
|
1400 |
|
1401 /* |
|
1402 * CURLOPT_TIMEOUT and CURLOPT_CONNECTTIMEOUT expect integers. Have to use ceil since. |
|
1403 * a value of 0 will allow an unlimited timeout. |
|
1404 */ |
1155 $timeout = (int) ceil( $r['timeout'] ); |
1405 $timeout = (int) ceil( $r['timeout'] ); |
1156 curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, $timeout ); |
1406 curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, $timeout ); |
1157 curl_setopt( $handle, CURLOPT_TIMEOUT, $timeout ); |
1407 curl_setopt( $handle, CURLOPT_TIMEOUT, $timeout ); |
1158 |
1408 |
1159 curl_setopt( $handle, CURLOPT_URL, $url); |
1409 curl_setopt( $handle, CURLOPT_URL, $url); |
1160 curl_setopt( $handle, CURLOPT_RETURNTRANSFER, true ); |
1410 curl_setopt( $handle, CURLOPT_RETURNTRANSFER, true ); |
1161 curl_setopt( $handle, CURLOPT_SSL_VERIFYHOST, ( $ssl_verify === true ) ? 2 : false ); |
1411 curl_setopt( $handle, CURLOPT_SSL_VERIFYHOST, ( $ssl_verify === true ) ? 2 : false ); |
1162 curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, $ssl_verify ); |
1412 curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, $ssl_verify ); |
1163 curl_setopt( $handle, CURLOPT_CAINFO, $r['sslcertificates'] ); |
1413 curl_setopt( $handle, CURLOPT_CAINFO, $r['sslcertificates'] ); |
1164 curl_setopt( $handle, CURLOPT_USERAGENT, $r['user-agent'] ); |
1414 curl_setopt( $handle, CURLOPT_USERAGENT, $r['user-agent'] ); |
1165 // The option doesn't work with safe mode or when open_basedir is set, and there's a |
1415 |
1166 // bug #17490 with redirected POST requests, so handle redirections outside Curl. |
1416 /* |
|
1417 * The option doesn't work with safe mode or when open_basedir is set, and there's |
|
1418 * a bug #17490 with redirected POST requests, so handle redirections outside Curl. |
|
1419 */ |
1167 curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, false ); |
1420 curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, false ); |
1168 if ( defined( 'CURLOPT_PROTOCOLS' ) ) // PHP 5.2.10 / cURL 7.19.4 |
1421 if ( defined( 'CURLOPT_PROTOCOLS' ) ) // PHP 5.2.10 / cURL 7.19.4 |
1169 curl_setopt( $handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS ); |
1422 curl_setopt( $handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS ); |
1170 |
1423 |
1171 switch ( $r['method'] ) { |
1424 switch ( $r['method'] ) { |
1223 if ( $r['httpversion'] == '1.0' ) |
1476 if ( $r['httpversion'] == '1.0' ) |
1224 curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 ); |
1477 curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 ); |
1225 else |
1478 else |
1226 curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); |
1479 curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); |
1227 |
1480 |
1228 // Cookies are not handled by the HTTP API currently. Allow for plugin authors to handle it |
1481 /** |
1229 // themselves... Although, it is somewhat pointless without some reference. |
1482 * Fires before the cURL request is executed. |
1230 do_action_ref_array( 'http_api_curl', array(&$handle) ); |
1483 * |
|
1484 * Cookies are not currently handled by the HTTP API. This action allows |
|
1485 * plugins to handle cookies themselves. |
|
1486 * |
|
1487 * @since 2.8.0 |
|
1488 * |
|
1489 * @param resource &$handle The cURL handle returned by curl_init(). |
|
1490 * @param array $r The HTTP request arguments. |
|
1491 * @param string $url The request URL. |
|
1492 */ |
|
1493 do_action_ref_array( 'http_api_curl', array( &$handle, $r, $url ) ); |
1231 |
1494 |
1232 // We don't need to return the body, so don't. Just execute request and return. |
1495 // We don't need to return the body, so don't. Just execute request and return. |
1233 if ( ! $r['blocking'] ) { |
1496 if ( ! $r['blocking'] ) { |
1234 curl_exec( $handle ); |
1497 curl_exec( $handle ); |
1235 |
1498 |
1244 |
1507 |
1245 curl_close( $handle ); |
1508 curl_close( $handle ); |
1246 return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() ); |
1509 return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() ); |
1247 } |
1510 } |
1248 |
1511 |
1249 $theResponse = curl_exec( $handle ); |
1512 curl_exec( $handle ); |
1250 $theHeaders = WP_Http::processHeaders( $this->headers, $url ); |
1513 $theHeaders = WP_Http::processHeaders( $this->headers, $url ); |
1251 $theBody = $this->body; |
1514 $theBody = $this->body; |
|
1515 $bytes_written_total = $this->bytes_written_total; |
1252 |
1516 |
1253 $this->headers = ''; |
1517 $this->headers = ''; |
1254 $this->body = ''; |
1518 $this->body = ''; |
|
1519 $this->bytes_written_total = 0; |
1255 |
1520 |
1256 $curl_error = curl_errno( $handle ); |
1521 $curl_error = curl_errno( $handle ); |
1257 |
1522 |
1258 // If an error occured, or, no response |
1523 // If an error occurred, or, no response. |
1259 if ( $curl_error || ( 0 == strlen( $theBody ) && empty( $theHeaders['headers'] ) ) ) { |
1524 if ( $curl_error || ( 0 == strlen( $theBody ) && empty( $theHeaders['headers'] ) ) ) { |
1260 if ( CURLE_WRITE_ERROR /* 23 */ == $curl_error && $r['stream'] ) { |
1525 if ( CURLE_WRITE_ERROR /* 23 */ == $curl_error ) { |
1261 fclose( $this->stream_handle ); |
1526 if ( ! $this->max_body_length || $this->max_body_length != $bytes_written_total ) { |
1262 return new WP_Error( 'http_request_failed', __( 'Failed to write request to temporary file.' ) ); |
1527 if ( $r['stream'] ) { |
1263 } |
1528 curl_close( $handle ); |
1264 if ( $curl_error = curl_error( $handle ) ) { |
1529 fclose( $this->stream_handle ); |
1265 curl_close( $handle ); |
1530 return new WP_Error( 'http_request_failed', __( 'Failed to write request to temporary file.' ) ); |
1266 return new WP_Error( 'http_request_failed', $curl_error ); |
1531 } else { |
|
1532 curl_close( $handle ); |
|
1533 return new WP_Error( 'http_request_failed', curl_error( $handle ) ); |
|
1534 } |
|
1535 } |
|
1536 } else { |
|
1537 if ( $curl_error = curl_error( $handle ) ) { |
|
1538 curl_close( $handle ); |
|
1539 return new WP_Error( 'http_request_failed', $curl_error ); |
|
1540 } |
1267 } |
1541 } |
1268 if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array( 301, 302 ) ) ) { |
1542 if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array( 301, 302 ) ) ) { |
1269 curl_close( $handle ); |
1543 curl_close( $handle ); |
1270 return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); |
1544 return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); |
1271 } |
1545 } |
1272 } |
1546 } |
1273 |
1547 |
1274 $response = array(); |
|
1275 $response['code'] = curl_getinfo( $handle, CURLINFO_HTTP_CODE ); |
|
1276 $response['message'] = get_status_header_desc($response['code']); |
|
1277 |
|
1278 curl_close( $handle ); |
1548 curl_close( $handle ); |
1279 |
1549 |
1280 if ( $r['stream'] ) |
1550 if ( $r['stream'] ) |
1281 fclose( $this->stream_handle ); |
1551 fclose( $this->stream_handle ); |
1282 |
1552 |
1283 $response = array( |
1553 $response = array( |
1284 'headers' => $theHeaders['headers'], |
1554 'headers' => $theHeaders['headers'], |
1285 'body' => null, |
1555 'body' => null, |
1286 'response' => $response, |
1556 'response' => $theHeaders['response'], |
1287 'cookies' => $theHeaders['cookies'], |
1557 'cookies' => $theHeaders['cookies'], |
1288 'filename' => $r['filename'] |
1558 'filename' => $r['filename'] |
1289 ); |
1559 ); |
1290 |
1560 |
1291 // Handle redirects |
1561 // Handle redirects. |
1292 if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) ) |
1562 if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) ) |
1293 return $redirect_response; |
1563 return $redirect_response; |
1294 |
1564 |
1295 if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders['headers']) ) |
1565 if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders['headers']) ) |
1296 $theBody = WP_Http_Encoding::decompress( $theBody ); |
1566 $theBody = WP_Http_Encoding::decompress( $theBody ); |
1316 |
1586 |
1317 /** |
1587 /** |
1318 * Grab the body of the cURL request |
1588 * Grab the body of the cURL request |
1319 * |
1589 * |
1320 * The contents of the document are passed in chunks, so we append to the $body property for temporary storage. |
1590 * The contents of the document are passed in chunks, so we append to the $body property for temporary storage. |
1321 * Returning a length shorter than the length of $data passed in will cause cURL to abort the request as "completed" |
1591 * Returning a length shorter than the length of $data passed in will cause cURL to abort the request with CURLE_WRITE_ERROR |
1322 * |
1592 * |
1323 * @since 3.6.0 |
1593 * @since 3.6.0 |
1324 * @access private |
1594 * @access private |
1325 * @return int |
1595 * @return int |
1326 */ |
1596 */ |
1327 private function stream_body( $handle, $data ) { |
1597 private function stream_body( $handle, $data ) { |
1328 $data_length = strlen( $data ); |
1598 $data_length = strlen( $data ); |
1329 |
1599 |
1330 if ( $this->max_body_length && ( strlen( $this->body ) + $data_length ) > $this->max_body_length ) |
1600 if ( $this->max_body_length && ( $this->bytes_written_total + $data_length ) > $this->max_body_length ) { |
1331 $data = substr( $data, 0, ( $this->max_body_length - $data_length ) ); |
1601 $data_length = ( $this->max_body_length - $this->bytes_written_total ); |
|
1602 $data = substr( $data, 0, $data_length ); |
|
1603 } |
1332 |
1604 |
1333 if ( $this->stream_handle ) { |
1605 if ( $this->stream_handle ) { |
1334 $bytes_written = fwrite( $this->stream_handle, $data ); |
1606 $bytes_written = fwrite( $this->stream_handle, $data ); |
1335 } else { |
1607 } else { |
1336 $this->body .= $data; |
1608 $this->body .= $data; |
1337 $bytes_written = $data_length; |
1609 $bytes_written = $data_length; |
1338 } |
1610 } |
1339 |
1611 |
1340 // Upon event of this function returning less than strlen( $data ) curl will error with CURLE_WRITE_ERROR |
1612 $this->bytes_written_total += $bytes_written; |
|
1613 |
|
1614 // Upon event of this function returning less than strlen( $data ) curl will error with CURLE_WRITE_ERROR. |
1341 return $bytes_written; |
1615 return $bytes_written; |
1342 } |
1616 } |
1343 |
1617 |
1344 /** |
1618 /** |
1345 * Whether this class can be used for retrieving an URL. |
1619 * Whether this class can be used for retrieving an URL. |
1385 * You do not need to have localhost and the blog host in this list, because they will not be passed |
1668 * You do not need to have localhost and the blog host in this list, because they will not be passed |
1386 * through the proxy. The list should be presented in a comma separated list, wildcards using * are supported, eg. *.wordpress.org</li> |
1669 * through the proxy. The list should be presented in a comma separated list, wildcards using * are supported, eg. *.wordpress.org</li> |
1387 * </ol> |
1670 * </ol> |
1388 * |
1671 * |
1389 * An example can be as seen below. |
1672 * An example can be as seen below. |
1390 * <code> |
|
1391 * define('WP_PROXY_HOST', '192.168.84.101'); |
|
1392 * define('WP_PROXY_PORT', '8080'); |
|
1393 * define('WP_PROXY_BYPASS_HOSTS', 'localhost, www.example.com, *.wordpress.org'); |
|
1394 * </code> |
|
1395 * |
1673 * |
1396 * @link http://core.trac.wordpress.org/ticket/4011 Proxy support ticket in WordPress. |
1674 * define('WP_PROXY_HOST', '192.168.84.101'); |
1397 * @link http://core.trac.wordpress.org/ticket/14636 Allow wildcard domains in WP_PROXY_BYPASS_HOSTS |
1675 * define('WP_PROXY_PORT', '8080'); |
1398 * @since 2.8 |
1676 * define('WP_PROXY_BYPASS_HOSTS', 'localhost, www.example.com, *.wordpress.org'); |
|
1677 * |
|
1678 * @link https://core.trac.wordpress.org/ticket/4011 Proxy support ticket in WordPress. |
|
1679 * @link https://core.trac.wordpress.org/ticket/14636 Allow wildcard domains in WP_PROXY_BYPASS_HOSTS |
|
1680 * @since 2.8.0 |
1399 */ |
1681 */ |
1400 class WP_HTTP_Proxy { |
1682 class WP_HTTP_Proxy { |
1401 |
1683 |
1402 /** |
1684 /** |
1403 * Whether proxy connection should be used. |
1685 * Whether proxy connection should be used. |
1404 * |
1686 * |
1405 * @since 2.8 |
1687 * @since 2.8.0 |
|
1688 * |
1406 * @use WP_PROXY_HOST |
1689 * @use WP_PROXY_HOST |
1407 * @use WP_PROXY_PORT |
1690 * @use WP_PROXY_PORT |
1408 * |
1691 * |
1409 * @return bool |
1692 * @return bool |
1410 */ |
1693 */ |
1411 function is_enabled() { |
1694 public function is_enabled() { |
1412 return defined('WP_PROXY_HOST') && defined('WP_PROXY_PORT'); |
1695 return defined('WP_PROXY_HOST') && defined('WP_PROXY_PORT'); |
1413 } |
1696 } |
1414 |
1697 |
1415 /** |
1698 /** |
1416 * Whether authentication should be used. |
1699 * Whether authentication should be used. |
1417 * |
1700 * |
1418 * @since 2.8 |
1701 * @since 2.8.0 |
|
1702 * |
1419 * @use WP_PROXY_USERNAME |
1703 * @use WP_PROXY_USERNAME |
1420 * @use WP_PROXY_PASSWORD |
1704 * @use WP_PROXY_PASSWORD |
1421 * |
1705 * |
1422 * @return bool |
1706 * @return bool |
1423 */ |
1707 */ |
1424 function use_authentication() { |
1708 public function use_authentication() { |
1425 return defined('WP_PROXY_USERNAME') && defined('WP_PROXY_PASSWORD'); |
1709 return defined('WP_PROXY_USERNAME') && defined('WP_PROXY_PASSWORD'); |
1426 } |
1710 } |
1427 |
1711 |
1428 /** |
1712 /** |
1429 * Retrieve the host for the proxy server. |
1713 * Retrieve the host for the proxy server. |
1430 * |
1714 * |
1431 * @since 2.8 |
1715 * @since 2.8.0 |
1432 * |
1716 * |
1433 * @return string |
1717 * @return string |
1434 */ |
1718 */ |
1435 function host() { |
1719 public function host() { |
1436 if ( defined('WP_PROXY_HOST') ) |
1720 if ( defined('WP_PROXY_HOST') ) |
1437 return WP_PROXY_HOST; |
1721 return WP_PROXY_HOST; |
1438 |
1722 |
1439 return ''; |
1723 return ''; |
1440 } |
1724 } |
1441 |
1725 |
1442 /** |
1726 /** |
1443 * Retrieve the port for the proxy server. |
1727 * Retrieve the port for the proxy server. |
1444 * |
1728 * |
1445 * @since 2.8 |
1729 * @since 2.8.0 |
1446 * |
1730 * |
1447 * @return string |
1731 * @return string |
1448 */ |
1732 */ |
1449 function port() { |
1733 public function port() { |
1450 if ( defined('WP_PROXY_PORT') ) |
1734 if ( defined('WP_PROXY_PORT') ) |
1451 return WP_PROXY_PORT; |
1735 return WP_PROXY_PORT; |
1452 |
1736 |
1453 return ''; |
1737 return ''; |
1454 } |
1738 } |
1455 |
1739 |
1456 /** |
1740 /** |
1457 * Retrieve the username for proxy authentication. |
1741 * Retrieve the username for proxy authentication. |
1458 * |
1742 * |
1459 * @since 2.8 |
1743 * @since 2.8.0 |
1460 * |
1744 * |
1461 * @return string |
1745 * @return string |
1462 */ |
1746 */ |
1463 function username() { |
1747 public function username() { |
1464 if ( defined('WP_PROXY_USERNAME') ) |
1748 if ( defined('WP_PROXY_USERNAME') ) |
1465 return WP_PROXY_USERNAME; |
1749 return WP_PROXY_USERNAME; |
1466 |
1750 |
1467 return ''; |
1751 return ''; |
1468 } |
1752 } |
1469 |
1753 |
1470 /** |
1754 /** |
1471 * Retrieve the password for proxy authentication. |
1755 * Retrieve the password for proxy authentication. |
1472 * |
1756 * |
1473 * @since 2.8 |
1757 * @since 2.8.0 |
1474 * |
1758 * |
1475 * @return string |
1759 * @return string |
1476 */ |
1760 */ |
1477 function password() { |
1761 public function password() { |
1478 if ( defined('WP_PROXY_PASSWORD') ) |
1762 if ( defined('WP_PROXY_PASSWORD') ) |
1479 return WP_PROXY_PASSWORD; |
1763 return WP_PROXY_PASSWORD; |
1480 |
1764 |
1481 return ''; |
1765 return ''; |
1482 } |
1766 } |
1483 |
1767 |
1484 /** |
1768 /** |
1485 * Retrieve authentication string for proxy authentication. |
1769 * Retrieve authentication string for proxy authentication. |
1486 * |
1770 * |
1487 * @since 2.8 |
1771 * @since 2.8.0 |
1488 * |
1772 * |
1489 * @return string |
1773 * @return string |
1490 */ |
1774 */ |
1491 function authentication() { |
1775 public function authentication() { |
1492 return $this->username() . ':' . $this->password(); |
1776 return $this->username() . ':' . $this->password(); |
1493 } |
1777 } |
1494 |
1778 |
1495 /** |
1779 /** |
1496 * Retrieve header string for proxy authentication. |
1780 * Retrieve header string for proxy authentication. |
1497 * |
1781 * |
1498 * @since 2.8 |
1782 * @since 2.8.0 |
1499 * |
1783 * |
1500 * @return string |
1784 * @return string |
1501 */ |
1785 */ |
1502 function authentication_header() { |
1786 public function authentication_header() { |
1503 return 'Proxy-Authorization: Basic ' . base64_encode( $this->authentication() ); |
1787 return 'Proxy-Authorization: Basic ' . base64_encode( $this->authentication() ); |
1504 } |
1788 } |
1505 |
1789 |
1506 /** |
1790 /** |
1507 * Whether URL should be sent through the proxy server. |
1791 * Whether URL should be sent through the proxy server. |
1508 * |
1792 * |
1509 * We want to keep localhost and the blog URL from being sent through the proxy server, because |
1793 * We want to keep localhost and the blog URL from being sent through the proxy server, because |
1510 * some proxies can not handle this. We also have the constant available for defining other |
1794 * some proxies can not handle this. We also have the constant available for defining other |
1511 * hosts that won't be sent through the proxy. |
1795 * hosts that won't be sent through the proxy. |
1512 * |
1796 * |
1513 * @uses WP_PROXY_BYPASS_HOSTS |
|
1514 * @since 2.8.0 |
1797 * @since 2.8.0 |
1515 * |
1798 * |
1516 * @param string $uri URI to check. |
1799 * @param string $uri URI to check. |
1517 * @return bool True, to send through the proxy and false if, the proxy should not be used. |
1800 * @return bool True, to send through the proxy and false if, the proxy should not be used. |
1518 */ |
1801 */ |
1519 function send_through_proxy( $uri ) { |
1802 public function send_through_proxy( $uri ) { |
1520 // parse_url() only handles http, https type URLs, and will emit E_WARNING on failure. |
1803 /* |
1521 // This will be displayed on blogs, which is not reasonable. |
1804 * parse_url() only handles http, https type URLs, and will emit E_WARNING on failure. |
|
1805 * This will be displayed on blogs, which is not reasonable. |
|
1806 */ |
1522 $check = @parse_url($uri); |
1807 $check = @parse_url($uri); |
1523 |
1808 |
1524 // Malformed URL, can not process, but this could mean ssl, so let through anyway. |
1809 // Malformed URL, can not process, but this could mean ssl, so let through anyway. |
1525 if ( $check === false ) |
1810 if ( $check === false ) |
1526 return true; |
1811 return true; |
1527 |
1812 |
1528 $home = parse_url( get_option('siteurl') ); |
1813 $home = parse_url( get_option('siteurl') ); |
1529 |
1814 |
|
1815 /** |
|
1816 * Filter whether to preempt sending the request through the proxy server. |
|
1817 * |
|
1818 * Returning false will bypass the proxy; returning true will send |
|
1819 * the request through the proxy. Returning null bypasses the filter. |
|
1820 * |
|
1821 * @since 3.5.0 |
|
1822 * |
|
1823 * @param null $override Whether to override the request result. Default null. |
|
1824 * @param string $uri URL to check. |
|
1825 * @param array $check Associative array result of parsing the URI. |
|
1826 * @param array $home Associative array result of parsing the site URL. |
|
1827 */ |
1530 $result = apply_filters( 'pre_http_send_through_proxy', null, $uri, $check, $home ); |
1828 $result = apply_filters( 'pre_http_send_through_proxy', null, $uri, $check, $home ); |
1531 if ( ! is_null( $result ) ) |
1829 if ( ! is_null( $result ) ) |
1532 return $result; |
1830 return $result; |
1533 |
1831 |
1534 if ( $check['host'] == 'localhost' || $check['host'] == $home['host'] ) |
1832 if ( 'localhost' == $check['host'] || ( isset( $home['host'] ) && $home['host'] == $check['host'] ) ) |
1535 return false; |
1833 return false; |
1536 |
1834 |
1537 if ( !defined('WP_PROXY_BYPASS_HOSTS') ) |
1835 if ( !defined('WP_PROXY_BYPASS_HOSTS') ) |
1538 return true; |
1836 return true; |
1539 |
1837 |
1575 * Cookie name. |
1873 * Cookie name. |
1576 * |
1874 * |
1577 * @since 2.8.0 |
1875 * @since 2.8.0 |
1578 * @var string |
1876 * @var string |
1579 */ |
1877 */ |
1580 var $name; |
1878 public $name; |
1581 |
1879 |
1582 /** |
1880 /** |
1583 * Cookie value. |
1881 * Cookie value. |
1584 * |
1882 * |
1585 * @since 2.8.0 |
1883 * @since 2.8.0 |
1586 * @var string |
1884 * @var string |
1587 */ |
1885 */ |
1588 var $value; |
1886 public $value; |
1589 |
1887 |
1590 /** |
1888 /** |
1591 * When the cookie expires. |
1889 * When the cookie expires. |
1592 * |
1890 * |
1593 * @since 2.8.0 |
1891 * @since 2.8.0 |
1594 * @var string |
1892 * @var string |
1595 */ |
1893 */ |
1596 var $expires; |
1894 public $expires; |
1597 |
1895 |
1598 /** |
1896 /** |
1599 * Cookie URL path. |
1897 * Cookie URL path. |
1600 * |
1898 * |
1601 * @since 2.8.0 |
1899 * @since 2.8.0 |
1602 * @var string |
1900 * @var string |
1603 */ |
1901 */ |
1604 var $path; |
1902 public $path; |
1605 |
1903 |
1606 /** |
1904 /** |
1607 * Cookie Domain. |
1905 * Cookie Domain. |
1608 * |
1906 * |
1609 * @since 2.8.0 |
1907 * @since 2.8.0 |
1610 * @var string |
1908 * @var string |
1611 */ |
1909 */ |
1612 var $domain; |
1910 public $domain; |
1613 |
1911 |
1614 /** |
1912 /** |
1615 * Sets up this cookie object. |
1913 * Sets up this cookie object. |
1616 * |
1914 * |
1617 * The parameter $data should be either an associative array containing the indices names below |
1915 * The parameter $data should be either an associative array containing the indices names below |
1618 * or a header string detailing it. |
1916 * or a header string detailing it. |
1619 * |
1917 * |
1620 * If it's an array, it should include the following elements: |
1918 * @since 2.8.0 |
1621 * <ol> |
|
1622 * <li>Name</li> |
|
1623 * <li>Value - should NOT be urlencoded already.</li> |
|
1624 * <li>Expires - (optional) String or int (UNIX timestamp).</li> |
|
1625 * <li>Path (optional)</li> |
|
1626 * <li>Domain (optional)</li> |
|
1627 * <li>Port (optional)</li> |
|
1628 * </ol> |
|
1629 * |
|
1630 * @access public |
1919 * @access public |
1631 * @since 2.8.0 |
1920 * |
1632 * |
1921 * @param string|array $data { |
1633 * @param string|array $data Raw cookie data. |
1922 * Raw cookie data as header string or data array. |
1634 * @param string $requested_url The URL which the cookie was set on, used for default 'domain' and 'port' values |
1923 * |
1635 */ |
1924 * @type string $name Cookie name. |
1636 function __construct( $data, $requested_url = '' ) { |
1925 * @type mixed $value Value. Should NOT already be urlencoded. |
|
1926 * @type string|int $expires Optional. Unix timestamp or formatted date. Default null. |
|
1927 * @type string $path Optional. Path. Default '/'. |
|
1928 * @type string $domain Optional. Domain. Default host of parsed $requested_url. |
|
1929 * @type int $port Optional. Port. Default null. |
|
1930 * } |
|
1931 * @param string $requested_url The URL which the cookie was set on, used for default $domain |
|
1932 * and $port values. |
|
1933 */ |
|
1934 public function __construct( $data, $requested_url = '' ) { |
1637 if ( $requested_url ) |
1935 if ( $requested_url ) |
1638 $arrURL = @parse_url( $requested_url ); |
1936 $arrURL = @parse_url( $requested_url ); |
1639 if ( isset( $arrURL['host'] ) ) |
1937 if ( isset( $arrURL['host'] ) ) |
1640 $this->domain = $arrURL['host']; |
1938 $this->domain = $arrURL['host']; |
1641 $this->path = isset( $arrURL['path'] ) ? $arrURL['path'] : '/'; |
1939 $this->path = isset( $arrURL['path'] ) ? $arrURL['path'] : '/'; |
1642 if ( '/' != substr( $this->path, -1 ) ) |
1940 if ( '/' != substr( $this->path, -1 ) ) |
1643 $this->path = dirname( $this->path ) . '/'; |
1941 $this->path = dirname( $this->path ) . '/'; |
1644 |
1942 |
1645 if ( is_string( $data ) ) { |
1943 if ( is_string( $data ) ) { |
1646 // Assume it's a header string direct from a previous request |
1944 // Assume it's a header string direct from a previous request. |
1647 $pairs = explode( ';', $data ); |
1945 $pairs = explode( ';', $data ); |
1648 |
1946 |
1649 // Special handling for first pair; name=value. Also be careful of "=" in value |
1947 // Special handling for first pair; name=value. Also be careful of "=" in value. |
1650 $name = trim( substr( $pairs[0], 0, strpos( $pairs[0], '=' ) ) ); |
1948 $name = trim( substr( $pairs[0], 0, strpos( $pairs[0], '=' ) ) ); |
1651 $value = substr( $pairs[0], strpos( $pairs[0], '=' ) + 1 ); |
1949 $value = substr( $pairs[0], strpos( $pairs[0], '=' ) + 1 ); |
1652 $this->name = $name; |
1950 $this->name = $name; |
1653 $this->value = urldecode( $value ); |
1951 $this->value = urldecode( $value ); |
1654 array_shift( $pairs ); //Removes name=value from items. |
1952 |
1655 |
1953 // Removes name=value from items. |
1656 // Set everything else as a property |
1954 array_shift( $pairs ); |
|
1955 |
|
1956 // Set everything else as a property. |
1657 foreach ( $pairs as $pair ) { |
1957 foreach ( $pairs as $pair ) { |
1658 $pair = rtrim($pair); |
1958 $pair = rtrim($pair); |
1659 if ( empty($pair) ) //Handles the cookie ending in ; which results in a empty final pair |
1959 |
|
1960 // Handle the cookie ending in ; which results in a empty final pair. |
|
1961 if ( empty($pair) ) |
1660 continue; |
1962 continue; |
1661 |
1963 |
1662 list( $key, $val ) = strpos( $pair, '=' ) ? explode( '=', $pair ) : array( $pair, '' ); |
1964 list( $key, $val ) = strpos( $pair, '=' ) ? explode( '=', $pair ) : array( $pair, '' ); |
1663 $key = strtolower( trim( $key ) ); |
1965 $key = strtolower( trim( $key ) ); |
1664 if ( 'expires' == $key ) |
1966 if ( 'expires' == $key ) |
1665 $val = strtotime( $val ); |
1967 $val = strtotime( $val ); |
1666 $this->$key = $val; |
1968 $this->$key = $val; |
1667 } |
1969 } |
1668 } else { |
1970 } else { |
1669 if ( !isset( $data['name'] ) ) |
1971 if ( !isset( $data['name'] ) ) |
1670 return false; |
1972 return; |
1671 |
1973 |
1672 // Set properties based directly on parameters |
1974 // Set properties based directly on parameters. |
1673 foreach ( array( 'name', 'value', 'path', 'domain', 'port' ) as $field ) { |
1975 foreach ( array( 'name', 'value', 'path', 'domain', 'port' ) as $field ) { |
1674 if ( isset( $data[ $field ] ) ) |
1976 if ( isset( $data[ $field ] ) ) |
1675 $this->$field = $data[ $field ]; |
1977 $this->$field = $data[ $field ]; |
1676 } |
1978 } |
1677 |
1979 |
1691 * @since 2.8.0 |
1993 * @since 2.8.0 |
1692 * |
1994 * |
1693 * @param string $url URL you intend to send this cookie to |
1995 * @param string $url URL you intend to send this cookie to |
1694 * @return boolean true if allowed, false otherwise. |
1996 * @return boolean true if allowed, false otherwise. |
1695 */ |
1997 */ |
1696 function test( $url ) { |
1998 public function test( $url ) { |
1697 if ( is_null( $this->name ) ) |
1999 if ( is_null( $this->name ) ) |
1698 return false; |
2000 return false; |
1699 |
2001 |
1700 // Expires - if expired then nothing else matters |
2002 // Expires - if expired then nothing else matters. |
1701 if ( isset( $this->expires ) && time() > $this->expires ) |
2003 if ( isset( $this->expires ) && time() > $this->expires ) |
1702 return false; |
2004 return false; |
1703 |
2005 |
1704 // Get details on the URL we're thinking about sending to |
2006 // Get details on the URL we're thinking about sending to. |
1705 $url = parse_url( $url ); |
2007 $url = parse_url( $url ); |
1706 $url['port'] = isset( $url['port'] ) ? $url['port'] : ( 'https' == $url['scheme'] ? 443 : 80 ); |
2008 $url['port'] = isset( $url['port'] ) ? $url['port'] : ( 'https' == $url['scheme'] ? 443 : 80 ); |
1707 $url['path'] = isset( $url['path'] ) ? $url['path'] : '/'; |
2009 $url['path'] = isset( $url['path'] ) ? $url['path'] : '/'; |
1708 |
2010 |
1709 // Values to use for comparison against the URL |
2011 // Values to use for comparison against the URL. |
1710 $path = isset( $this->path ) ? $this->path : '/'; |
2012 $path = isset( $this->path ) ? $this->path : '/'; |
1711 $port = isset( $this->port ) ? $this->port : null; |
2013 $port = isset( $this->port ) ? $this->port : null; |
1712 $domain = isset( $this->domain ) ? strtolower( $this->domain ) : strtolower( $url['host'] ); |
2014 $domain = isset( $this->domain ) ? strtolower( $this->domain ) : strtolower( $url['host'] ); |
1713 if ( false === stripos( $domain, '.' ) ) |
2015 if ( false === stripos( $domain, '.' ) ) |
1714 $domain .= '.local'; |
2016 $domain .= '.local'; |
1715 |
2017 |
1716 // Host - very basic check that the request URL ends with the domain restriction (minus leading dot) |
2018 // Host - very basic check that the request URL ends with the domain restriction (minus leading dot). |
1717 $domain = substr( $domain, 0, 1 ) == '.' ? substr( $domain, 1 ) : $domain; |
2019 $domain = substr( $domain, 0, 1 ) == '.' ? substr( $domain, 1 ) : $domain; |
1718 if ( substr( $url['host'], -strlen( $domain ) ) != $domain ) |
2020 if ( substr( $url['host'], -strlen( $domain ) ) != $domain ) |
1719 return false; |
2021 return false; |
1720 |
2022 |
1721 // Port - supports "port-lists" in the format: "80,8000,8080" |
2023 // Port - supports "port-lists" in the format: "80,8000,8080". |
1722 if ( !empty( $port ) && !in_array( $url['port'], explode( ',', $port) ) ) |
2024 if ( !empty( $port ) && !in_array( $url['port'], explode( ',', $port) ) ) |
1723 return false; |
2025 return false; |
1724 |
2026 |
1725 // Path - request path must start with path restriction |
2027 // Path - request path must start with path restriction. |
1726 if ( substr( $url['path'], 0, strlen( $path ) ) != $path ) |
2028 if ( substr( $url['path'], 0, strlen( $path ) ) != $path ) |
1727 return false; |
2029 return false; |
1728 |
2030 |
1729 return true; |
2031 return true; |
1730 } |
2032 } |
1750 * @access public |
2060 * @access public |
1751 * @since 2.8.0 |
2061 * @since 2.8.0 |
1752 * |
2062 * |
1753 * @return string |
2063 * @return string |
1754 */ |
2064 */ |
1755 function getFullHeader() { |
2065 public function getFullHeader() { |
1756 return 'Cookie: ' . $this->getHeaderValue(); |
2066 return 'Cookie: ' . $this->getHeaderValue(); |
1757 } |
2067 } |
1758 } |
2068 } |
1759 |
2069 |
1760 /** |
2070 /** |
1761 * Implementation for deflate and gzip transfer encodings. |
2071 * Implementation for deflate and gzip transfer encodings. |
1762 * |
2072 * |
1763 * Includes RFC 1950, RFC 1951, and RFC 1952. |
2073 * Includes RFC 1950, RFC 1951, and RFC 1952. |
1764 * |
2074 * |
1765 * @since 2.8 |
2075 * @since 2.8.0 |
1766 * @package WordPress |
2076 * @package WordPress |
1767 * @subpackage HTTP |
2077 * @subpackage HTTP |
1768 */ |
2078 */ |
1769 class WP_Http_Encoding { |
2079 class WP_Http_Encoding { |
1770 |
2080 |
1771 /** |
2081 /** |
1772 * Compress raw string using the deflate format. |
2082 * Compress raw string using the deflate format. |
1773 * |
2083 * |
1774 * Supports the RFC 1951 standard. |
2084 * Supports the RFC 1951 standard. |
1775 * |
2085 * |
1776 * @since 2.8 |
2086 * @since 2.8.0 |
1777 * |
2087 * |
1778 * @param string $raw String to compress. |
2088 * @param string $raw String to compress. |
1779 * @param int $level Optional, default is 9. Compression level, 9 is highest. |
2089 * @param int $level Optional, default is 9. Compression level, 9 is highest. |
1780 * @param string $supports Optional, not used. When implemented it will choose the right compression based on what the server supports. |
2090 * @param string $supports Optional, not used. When implemented it will choose the right compression based on what the server supports. |
1781 * @return string|bool False on failure. |
2091 * @return string|false False on failure. |
1782 */ |
2092 */ |
1783 public static function compress( $raw, $level = 9, $supports = null ) { |
2093 public static function compress( $raw, $level = 9, $supports = null ) { |
1784 return gzdeflate( $raw, $level ); |
2094 return gzdeflate( $raw, $level ); |
1785 } |
2095 } |
1786 |
2096 |
1830 * various snippets on the gzinflate() PHP documentation. |
2140 * various snippets on the gzinflate() PHP documentation. |
1831 * |
2141 * |
1832 * Warning: Magic numbers within. Due to the potential different formats that the compressed |
2142 * Warning: Magic numbers within. Due to the potential different formats that the compressed |
1833 * data may be returned in, some "magic offsets" are needed to ensure proper decompression |
2143 * data may be returned in, some "magic offsets" are needed to ensure proper decompression |
1834 * takes place. For a simple progmatic way to determine the magic offset in use, see: |
2144 * takes place. For a simple progmatic way to determine the magic offset in use, see: |
1835 * http://core.trac.wordpress.org/ticket/18273 |
2145 * https://core.trac.wordpress.org/ticket/18273 |
1836 * |
2146 * |
1837 * @since 2.8.1 |
2147 * @since 2.8.1 |
1838 * @link http://core.trac.wordpress.org/ticket/18273 |
2148 * @link https://core.trac.wordpress.org/ticket/18273 |
1839 * @link http://au2.php.net/manual/en/function.gzinflate.php#70875 |
2149 * @link http://au2.php.net/manual/en/function.gzinflate.php#70875 |
1840 * @link http://au2.php.net/manual/en/function.gzinflate.php#77336 |
2150 * @link http://au2.php.net/manual/en/function.gzinflate.php#77336 |
1841 * |
2151 * |
1842 * @param string $gzData String to decompress. |
2152 * @param string $gzData String to decompress. |
1843 * @return string|bool False on failure. |
2153 * @return string|bool False on failure. |
1844 */ |
2154 */ |
1845 public static function compatible_gzinflate($gzData) { |
2155 public static function compatible_gzinflate($gzData) { |
1846 |
2156 |
1847 // Compressed data might contain a full header, if so strip it for gzinflate() |
2157 // Compressed data might contain a full header, if so strip it for gzinflate(). |
1848 if ( substr($gzData, 0, 3) == "\x1f\x8b\x08" ) { |
2158 if ( substr($gzData, 0, 3) == "\x1f\x8b\x08" ) { |
1849 $i = 10; |
2159 $i = 10; |
1850 $flg = ord( substr($gzData, 3, 1) ); |
2160 $flg = ord( substr($gzData, 3, 1) ); |
1851 if ( $flg > 0 ) { |
2161 if ( $flg > 0 ) { |
1852 if ( $flg & 4 ) { |
2162 if ( $flg & 4 ) { |
1874 } |
2184 } |
1875 |
2185 |
1876 /** |
2186 /** |
1877 * What encoding types to accept and their priority values. |
2187 * What encoding types to accept and their priority values. |
1878 * |
2188 * |
1879 * @since 2.8 |
2189 * @since 2.8.0 |
1880 * |
2190 * |
|
2191 * @param string $url |
|
2192 * @param array $args |
1881 * @return string Types of encoding to accept. |
2193 * @return string Types of encoding to accept. |
1882 */ |
2194 */ |
1883 public static function accept_encoding( $url, $args ) { |
2195 public static function accept_encoding( $url, $args ) { |
1884 $type = array(); |
2196 $type = array(); |
1885 $compression_enabled = WP_Http_Encoding::is_available(); |
2197 $compression_enabled = self::is_available(); |
1886 |
2198 |
1887 if ( ! $args['decompress'] ) // decompression specifically disabled |
2199 if ( ! $args['decompress'] ) // Decompression specifically disabled. |
1888 $compression_enabled = false; |
2200 $compression_enabled = false; |
1889 elseif ( $args['stream'] ) // disable when streaming to file |
2201 elseif ( $args['stream'] ) // Disable when streaming to file. |
1890 $compression_enabled = false; |
2202 $compression_enabled = false; |
1891 elseif ( isset( $args['limit_response_size'] ) ) // If only partial content is being requested, we won't be able to decompress it |
2203 elseif ( isset( $args['limit_response_size'] ) ) // If only partial content is being requested, we won't be able to decompress it. |
1892 $compression_enabled = false; |
2204 $compression_enabled = false; |
1893 |
2205 |
1894 if ( $compression_enabled ) { |
2206 if ( $compression_enabled ) { |
1895 if ( function_exists( 'gzinflate' ) ) |
2207 if ( function_exists( 'gzinflate' ) ) |
1896 $type[] = 'deflate;q=1.0'; |
2208 $type[] = 'deflate;q=1.0'; |
1900 |
2212 |
1901 if ( function_exists( 'gzdecode' ) ) |
2213 if ( function_exists( 'gzdecode' ) ) |
1902 $type[] = 'gzip;q=0.5'; |
2214 $type[] = 'gzip;q=0.5'; |
1903 } |
2215 } |
1904 |
2216 |
|
2217 /** |
|
2218 * Filter the allowed encoding types. |
|
2219 * |
|
2220 * @since 3.6.0 |
|
2221 * |
|
2222 * @param array $type Encoding types allowed. Accepts 'gzinflate', |
|
2223 * 'gzuncompress', 'gzdecode'. |
|
2224 * @param string $url URL of the HTTP request. |
|
2225 * @param array $args HTTP request arguments. |
|
2226 */ |
1905 $type = apply_filters( 'wp_http_accept_encoding', $type, $url, $args ); |
2227 $type = apply_filters( 'wp_http_accept_encoding', $type, $url, $args ); |
1906 |
2228 |
1907 return implode(', ', $type); |
2229 return implode(', ', $type); |
1908 } |
2230 } |
1909 |
2231 |
1910 /** |
2232 /** |
1911 * What encoding the content used when it was compressed to send in the headers. |
2233 * What encoding the content used when it was compressed to send in the headers. |
1912 * |
2234 * |
1913 * @since 2.8 |
2235 * @since 2.8.0 |
1914 * |
2236 * |
1915 * @return string Content-Encoding string to send in the header. |
2237 * @return string Content-Encoding string to send in the header. |
1916 */ |
2238 */ |
1917 public static function content_encoding() { |
2239 public static function content_encoding() { |
1918 return 'deflate'; |
2240 return 'deflate'; |
1919 } |
2241 } |
1920 |
2242 |
1921 /** |
2243 /** |
1922 * Whether the content be decoded based on the headers. |
2244 * Whether the content be decoded based on the headers. |
1923 * |
2245 * |
1924 * @since 2.8 |
2246 * @since 2.8.0 |
1925 * |
2247 * |
1926 * @param array|string $headers All of the available headers. |
2248 * @param array|string $headers All of the available headers. |
1927 * @return bool |
2249 * @return bool |
1928 */ |
2250 */ |
1929 public static function should_decode($headers) { |
2251 public static function should_decode($headers) { |
1930 if ( is_array( $headers ) ) { |
2252 if ( is_array( $headers ) ) { |
1931 if ( array_key_exists('content-encoding', $headers) && ! empty( $headers['content-encoding'] ) ) |
2253 if ( array_key_exists('content-encoding', $headers) && ! empty( $headers['content-encoding'] ) ) |
1932 return true; |
2254 return true; |
1933 } else if ( is_string( $headers ) ) { |
2255 } elseif ( is_string( $headers ) ) { |
1934 return ( stripos($headers, 'content-encoding:') !== false ); |
2256 return ( stripos($headers, 'content-encoding:') !== false ); |
1935 } |
2257 } |
1936 |
2258 |
1937 return false; |
2259 return false; |
1938 } |
2260 } |