Projects : mp-wp : mp-wp_genesis
1 | <?php |
2 | /** |
3 | * Simple and uniform HTTP request API. |
4 | * |
5 | * Will eventually replace and standardize the WordPress HTTP requests made. |
6 | * |
7 | * @link http://trac.wordpress.org/ticket/4779 HTTP API Proposal |
8 | * |
9 | * @package WordPress |
10 | * @subpackage HTTP |
11 | * @since 2.7 |
12 | * @author Jacob Santos <wordpress@santosj.name> |
13 | */ |
14 | |
15 | /** |
16 | * WordPress HTTP Class for managing HTTP Transports and making HTTP requests. |
17 | * |
18 | * This class is called for the functionality of making HTTP requests and should |
19 | * replace Snoopy functionality, eventually. There is no available functionality |
20 | * to add HTTP transport implementations, since most of the HTTP transports are |
21 | * added and available for use. |
22 | * |
23 | * The exception is that cURL is not available as a transport and lacking an |
24 | * implementation. It will be added later and should be a patch on the WordPress |
25 | * Trac. |
26 | * |
27 | * There are no properties, because none are needed and for performance reasons. |
28 | * Some of the functions are static and while they do have some overhead over |
29 | * functions in PHP4, the purpose is maintainability. When PHP5 is finally the |
30 | * requirement, it will be easy to add the static keyword to the code. It is not |
31 | * as easy to convert a function to a method after enough code uses the old way. |
32 | * |
33 | * @package WordPress |
34 | * @subpackage HTTP |
35 | * @since 2.7 |
36 | */ |
37 | class WP_Http { |
38 | |
39 | /** |
40 | * PHP4 style Constructor - Calls PHP5 Style Constructor |
41 | * |
42 | * @since 2.7 |
43 | * @return WP_Http |
44 | */ |
45 | function WP_Http() { |
46 | $this->__construct(); |
47 | } |
48 | |
49 | /** |
50 | * PHP5 style Constructor - Setup available transport if not available. |
51 | * |
52 | * PHP4 does not have the 'self' keyword and since WordPress supports PHP4, |
53 | * the class needs to be used for the static call. |
54 | * |
55 | * The transport are setup to save time. This should only be called once, so |
56 | * the overhead should be fine. |
57 | * |
58 | * @since 2.7 |
59 | * @return WP_Http |
60 | */ |
61 | function __construct() { |
62 | WP_Http::_getTransport(); |
63 | WP_Http::_postTransport(); |
64 | } |
65 | |
66 | /** |
67 | * Tests the WordPress HTTP objects for an object to use and returns it. |
68 | * |
69 | * Tests all of the objects and returns the object that passes. Also caches |
70 | * that object to be used later. |
71 | * |
72 | * The order for the GET/HEAD requests are Streams, HTTP Extension, Fopen, |
73 | * and finally Fsockopen. fsockopen() is used last, because it has the most |
74 | * overhead in its implementation. There isn't any real way around it, since |
75 | * redirects have to be supported, much the same way the other transports |
76 | * also handle redirects. |
77 | * |
78 | * There are currently issues with "localhost" not resolving correctly with |
79 | * DNS. This may cause an error "failed to open stream: A connection attempt |
80 | * failed because the connected party did not properly respond after a |
81 | * period of time, or established connection failed because connected host |
82 | * has failed to respond." |
83 | * |
84 | * @since 2.7 |
85 | * @access private |
86 | * |
87 | * @param array $args Request args, default us an empty array |
88 | * @return object|null Null if no transports are available, HTTP transport object. |
89 | */ |
90 | function &_getTransport( $args = array() ) { |
91 | static $working_transport, $blocking_transport, $nonblocking_transport; |
92 | |
93 | if ( is_null($working_transport) ) { |
94 | if ( true === WP_Http_ExtHttp::test() && apply_filters('use_http_extension_transport', true) ) { |
95 | $working_transport['exthttp'] = new WP_Http_ExtHttp(); |
96 | $blocking_transport[] = &$working_transport['exthttp']; |
97 | } else if ( true === WP_Http_Curl::test() && apply_filters('use_curl_transport', true) ) { |
98 | $working_transport['curl'] = new WP_Http_Curl(); |
99 | $blocking_transport[] = &$working_transport['curl']; |
100 | } else if ( true === WP_Http_Streams::test() && apply_filters('use_streams_transport', true) ) { |
101 | $working_transport['streams'] = new WP_Http_Streams(); |
102 | $blocking_transport[] = &$working_transport['streams']; |
103 | } else if ( true === WP_Http_Fopen::test() && apply_filters('use_fopen_transport', true) ) { |
104 | $working_transport['fopen'] = new WP_Http_Fopen(); |
105 | $blocking_transport[] = &$working_transport['fopen']; |
106 | } else if ( true === WP_Http_Fsockopen::test() && apply_filters('use_fsockopen_transport', true) ) { |
107 | $working_transport['fsockopen'] = new WP_Http_Fsockopen(); |
108 | $blocking_transport[] = &$working_transport['fsockopen']; |
109 | } |
110 | |
111 | foreach ( array('curl', 'streams', 'fopen', 'fsockopen', 'exthttp') as $transport ) { |
112 | if ( isset($working_transport[$transport]) ) |
113 | $nonblocking_transport[] = &$working_transport[$transport]; |
114 | } |
115 | } |
116 | |
117 | if ( isset($args['blocking']) && !$args['blocking'] ) |
118 | return $nonblocking_transport; |
119 | else |
120 | return $blocking_transport; |
121 | } |
122 | |
123 | /** |
124 | * Tests the WordPress HTTP objects for an object to use and returns it. |
125 | * |
126 | * Tests all of the objects and returns the object that passes. Also caches |
127 | * that object to be used later. This is for posting content to a URL and |
128 | * is used when there is a body. The plain Fopen Transport can not be used |
129 | * to send content, but the streams transport can. This is a limitation that |
130 | * is addressed here, by just not including that transport. |
131 | * |
132 | * @since 2.7 |
133 | * @access private |
134 | * |
135 | * @param array $args Request args, default us an empty array |
136 | * @return object|null Null if no transports are available, HTTP transport object. |
137 | */ |
138 | function &_postTransport( $args = array() ) { |
139 | static $working_transport, $blocking_transport, $nonblocking_transport; |
140 | |
141 | if ( is_null($working_transport) ) { |
142 | if ( true === WP_Http_ExtHttp::test() && apply_filters('use_http_extension_transport', true) ) { |
143 | $working_transport['exthttp'] = new WP_Http_ExtHttp(); |
144 | $blocking_transport[] = &$working_transport['exthttp']; |
145 | } else if ( true === WP_Http_Streams::test() && apply_filters('use_streams_transport', true) ) { |
146 | $working_transport['streams'] = new WP_Http_Streams(); |
147 | $blocking_transport[] = &$working_transport['streams']; |
148 | } else if ( true === WP_Http_Fsockopen::test() && apply_filters('use_fsockopen_transport', true) ) { |
149 | $working_transport['fsockopen'] = new WP_Http_Fsockopen(); |
150 | $blocking_transport[] = &$working_transport['fsockopen']; |
151 | } |
152 | |
153 | foreach ( array('streams', 'fsockopen', 'exthttp') as $transport ) { |
154 | if ( isset($working_transport[$transport]) ) |
155 | $nonblocking_transport[] = &$working_transport[$transport]; |
156 | } |
157 | } |
158 | |
159 | if ( isset($args['blocking']) && !$args['blocking'] ) |
160 | return $nonblocking_transport; |
161 | else |
162 | return $blocking_transport; |
163 | } |
164 | |
165 | /** |
166 | * Send a HTTP request to a URI. |
167 | * |
168 | * The body and headers are part of the arguments. The 'body' argument is |
169 | * for the body and will accept either a string or an array. The 'headers' |
170 | * argument should be an array, but a string is acceptable. If the 'body' |
171 | * argument is an array, then it will automatically be escaped using |
172 | * http_build_query(). |
173 | * |
174 | * The only URI that are supported in the HTTP Transport implementation are |
175 | * the HTTP and HTTPS protocols. HTTP and HTTPS are assumed so the server |
176 | * might not know how to handle the send headers. Other protocols are |
177 | * unsupported and most likely will fail. |
178 | * |
179 | * The defaults are 'method', 'timeout', 'redirection', 'httpversion', |
180 | * 'blocking' and 'user-agent'. |
181 | * |
182 | * Accepted 'method' values are 'GET', 'POST', and 'HEAD', some transports |
183 | * technically allow others, but should not be assumed. The 'timeout' is |
184 | * used to sent how long the connection should stay open before failing when |
185 | * no response. 'redirection' is used to track how many redirects were taken |
186 | * and used to sent the amount for other transports, but not all transports |
187 | * accept setting that value. |
188 | * |
189 | * The 'httpversion' option is used to sent the HTTP version and accepted |
190 | * values are '1.0', and '1.1' and should be a string. Version 1.1 is not |
191 | * supported, because of chunk response. The 'user-agent' option is the |
192 | * user-agent and is used to replace the default user-agent, which is |
193 | * 'WordPress/WP_Version', where WP_Version is the value from $wp_version. |
194 | * |
195 | * 'blocking' is the default, which is used to tell the transport, whether |
196 | * it should halt PHP while it performs the request or continue regardless. |
197 | * Actually, that isn't entirely correct. Blocking mode really just means |
198 | * whether the fread should just pull what it can whenever it gets bytes or |
199 | * if it should wait until it has enough in the buffer to read or finishes |
200 | * reading the entire content. It doesn't actually always mean that PHP will |
201 | * continue going after making the request. |
202 | * |
203 | * @access public |
204 | * @since 2.7 |
205 | * |
206 | * @param string $url URI resource. |
207 | * @param str|array $args Optional. Override the defaults. |
208 | * @return boolean |
209 | */ |
210 | function request( $url, $args = array() ) { |
211 | global $wp_version; |
212 | |
213 | $defaults = array( |
214 | 'method' => 'GET', |
215 | 'timeout' => apply_filters( 'http_request_timeout', 5), |
216 | 'redirection' => apply_filters( 'http_request_redirection_count', 5), |
217 | 'httpversion' => apply_filters( 'http_request_version', '1.0'), |
218 | 'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version ), |
219 | 'blocking' => true, |
220 | 'headers' => array(), 'body' => null |
221 | ); |
222 | |
223 | $r = wp_parse_args( $args, $defaults ); |
224 | $r = apply_filters( 'http_request_args', $r ); |
225 | |
226 | if ( is_null( $r['headers'] ) ) |
227 | $r['headers'] = array(); |
228 | |
229 | if ( ! is_array($r['headers']) ) { |
230 | $processedHeaders = WP_Http::processHeaders($r['headers']); |
231 | $r['headers'] = $processedHeaders['headers']; |
232 | } |
233 | |
234 | if ( isset($r['headers']['User-Agent']) ) { |
235 | $r['user-agent'] = $r['headers']['User-Agent']; |
236 | unset($r['headers']['User-Agent']); |
237 | } |
238 | |
239 | if ( isset($r['headers']['user-agent']) ) { |
240 | $r['user-agent'] = $r['headers']['user-agent']; |
241 | unset($r['headers']['user-agent']); |
242 | } |
243 | |
244 | if ( is_null($r['body']) ) { |
245 | $transports = WP_Http::_getTransport($r); |
246 | } else { |
247 | if ( is_array( $r['body'] ) || is_object( $r['body'] ) ) { |
248 | $r['body'] = http_build_query($r['body'], null, '&'); |
249 | $r['headers']['Content-Type'] = 'application/x-www-form-urlencoded; charset=' . get_option('blog_charset'); |
250 | $r['headers']['Content-Length'] = strlen($r['body']); |
251 | } |
252 | |
253 | if ( ! isset( $r['headers']['Content-Length'] ) && ! isset( $r['headers']['content-length'] ) ) |
254 | $r['headers']['Content-Length'] = strlen($r['body']); |
255 | |
256 | $transports = WP_Http::_postTransport($r); |
257 | } |
258 | |
259 | $response = array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') ); |
260 | foreach( (array) $transports as $transport ) { |
261 | $response = $transport->request($url, $r); |
262 | |
263 | if( !is_wp_error($response) ) |
264 | return $response; |
265 | } |
266 | |
267 | return $response; |
268 | } |
269 | |
270 | /** |
271 | * Uses the POST HTTP method. |
272 | * |
273 | * Used for sending data that is expected to be in the body. |
274 | * |
275 | * @access public |
276 | * @since 2.7 |
277 | * |
278 | * @param string $url URI resource. |
279 | * @param str|array $args Optional. Override the defaults. |
280 | * @return boolean |
281 | */ |
282 | function post($url, $args = array()) { |
283 | $defaults = array('method' => 'POST'); |
284 | $r = wp_parse_args( $args, $defaults ); |
285 | return $this->request($url, $r); |
286 | } |
287 | |
288 | /** |
289 | * Uses the GET HTTP method. |
290 | * |
291 | * Used for sending data that is expected to be in the body. |
292 | * |
293 | * @access public |
294 | * @since 2.7 |
295 | * |
296 | * @param string $url URI resource. |
297 | * @param str|array $args Optional. Override the defaults. |
298 | * @return boolean |
299 | */ |
300 | function get($url, $args = array()) { |
301 | $defaults = array('method' => 'GET'); |
302 | $r = wp_parse_args( $args, $defaults ); |
303 | return $this->request($url, $r); |
304 | } |
305 | |
306 | /** |
307 | * Uses the HEAD HTTP method. |
308 | * |
309 | * Used for sending data that is expected to be in the body. |
310 | * |
311 | * @access public |
312 | * @since 2.7 |
313 | * |
314 | * @param string $url URI resource. |
315 | * @param str|array $args Optional. Override the defaults. |
316 | * @return boolean |
317 | */ |
318 | function head($url, $args = array()) { |
319 | $defaults = array('method' => 'HEAD'); |
320 | $r = wp_parse_args( $args, $defaults ); |
321 | return $this->request($url, $r); |
322 | } |
323 | |
324 | /** |
325 | * Parses the responses and splits the parts into headers and body. |
326 | * |
327 | * @access public |
328 | * @static |
329 | * @since 2.7 |
330 | * |
331 | * @param string $strResponse The full response string |
332 | * @return array Array with 'headers' and 'body' keys. |
333 | */ |
334 | function processResponse($strResponse) { |
335 | list($theHeaders, $theBody) = explode("\r\n\r\n", $strResponse, 2); |
336 | return array('headers' => $theHeaders, 'body' => $theBody); |
337 | } |
338 | |
339 | /** |
340 | * Transform header string into an array. |
341 | * |
342 | * If an array is given then it is assumed to be raw header data with |
343 | * numeric keys with the headers as the values. No headers must be passed |
344 | * that were already processed. |
345 | * |
346 | * @access public |
347 | * @static |
348 | * @since 2.7 |
349 | * |
350 | * @param string|array $headers |
351 | * @return array Processed string headers |
352 | */ |
353 | function processHeaders($headers) { |
354 | if ( is_string($headers) ) |
355 | $headers = explode("\n", str_replace(array("\r\n", "\r"), "\n", $headers) ); |
356 | |
357 | $response = array('code' => 0, 'message' => ''); |
358 | |
359 | $newheaders = array(); |
360 | foreach ( $headers as $tempheader ) { |
361 | if ( empty($tempheader) ) |
362 | continue; |
363 | |
364 | if ( false === strpos($tempheader, ':') ) { |
365 | list( , $iResponseCode, $strResponseMsg) = explode(' ', $tempheader, 3); |
366 | $response['code'] = $iResponseCode; |
367 | $response['message'] = $strResponseMsg; |
368 | continue; |
369 | } |
370 | |
371 | list($key, $value) = explode(':', $tempheader, 2); |
372 | |
373 | if ( ! empty($value) ) |
374 | $newheaders[strtolower($key)] = trim($value); |
375 | } |
376 | |
377 | return array('response' => $response, 'headers' => $newheaders); |
378 | } |
379 | |
380 | /** |
381 | * Decodes chunk transfer-encoding, based off the HTTP 1.1 specification. |
382 | * |
383 | * Based off the HTTP http_encoding_dechunk function. Does not support |
384 | * UTF-8. Does not support returning footer headers. Shouldn't be too |
385 | * difficult to support it though. |
386 | * |
387 | * @todo Add support for footer chunked headers. |
388 | * @access public |
389 | * @since 2.7 |
390 | * @static |
391 | * |
392 | * @param string $body Body content |
393 | * @return bool|string|WP_Error False if not chunked encoded. WP_Error on failure. Chunked decoded body on success. |
394 | */ |
395 | function chunkTransferDecode($body) { |
396 | $body = str_replace(array("\r\n", "\r"), "\n", $body); |
397 | // The body is not chunked encoding or is malformed. |
398 | if ( ! preg_match( '/^[0-9a-f]+(\s|\n)+/mi', trim($body) ) ) |
399 | return $body; |
400 | |
401 | $parsedBody = ''; |
402 | //$parsedHeaders = array(); Unsupported |
403 | |
404 | $done = false; |
405 | |
406 | do { |
407 | $hasChunk = (bool) preg_match( '/^([0-9a-f]+)(\s|\n)+/mi', $body, $match ); |
408 | |
409 | if ( $hasChunk ) { |
410 | if ( empty($match[1]) ) { |
411 | return new WP_Error('http_chunked_decode', __('Does not appear to be chunked encoded or body is malformed.') ); |
412 | } |
413 | |
414 | $length = hexdec( $match[1] ); |
415 | $chunkLength = strlen( $match[0] ); |
416 | |
417 | $strBody = substr($body, $chunkLength, $length); |
418 | $parsedBody .= $strBody; |
419 | |
420 | $body = ltrim(str_replace(array($match[0], $strBody), '', $body), "\n"); |
421 | |
422 | if( "0" == trim($body) ) { |
423 | $done = true; |
424 | return $parsedBody; // Ignore footer headers. |
425 | break; |
426 | } |
427 | } else { |
428 | return new WP_Error('http_chunked_decode', __('Does not appear to be chunked encoded or body is malformed.') ); |
429 | } |
430 | } while ( false === $done ); |
431 | } |
432 | } |
433 | |
434 | /** |
435 | * HTTP request method uses fsockopen function to retrieve the url. |
436 | * |
437 | * This would be the preferred method, but the fsockopen implementation has the |
438 | * most overhead of all the HTTP transport implementations. |
439 | * |
440 | * @package WordPress |
441 | * @subpackage HTTP |
442 | * @since 2.7 |
443 | */ |
444 | class WP_Http_Fsockopen { |
445 | /** |
446 | * Send a HTTP request to a URI using fsockopen(). |
447 | * |
448 | * Does not support non-blocking mode. |
449 | * |
450 | * @see WP_Http::request For default options descriptions. |
451 | * |
452 | * @since 2.7 |
453 | * @access public |
454 | * @param string $url URI resource. |
455 | * @param str|array $args Optional. Override the defaults. |
456 | * @return array 'headers', 'body', and 'response' keys. |
457 | */ |
458 | function request($url, $args = array()) { |
459 | $defaults = array( |
460 | 'method' => 'GET', 'timeout' => 5, |
461 | 'redirection' => 5, 'httpversion' => '1.0', |
462 | 'blocking' => true, |
463 | 'headers' => array(), 'body' => null |
464 | ); |
465 | |
466 | $r = wp_parse_args( $args, $defaults ); |
467 | |
468 | if ( isset($r['headers']['User-Agent']) ) { |
469 | $r['user-agent'] = $r['headers']['User-Agent']; |
470 | unset($r['headers']['User-Agent']); |
471 | } else if( isset($r['headers']['user-agent']) ) { |
472 | $r['user-agent'] = $r['headers']['user-agent']; |
473 | unset($r['headers']['user-agent']); |
474 | } |
475 | |
476 | $iError = null; // Store error number |
477 | $strError = null; // Store error string |
478 | |
479 | $arrURL = parse_url($url); |
480 | |
481 | $secure_transport = false; |
482 | |
483 | if ( ! isset($arrURL['port']) ) { |
484 | if ( ($arrURL['scheme'] == 'ssl' || $arrURL['scheme'] == 'https') && extension_loaded('openssl') ) { |
485 | $arrURL['host'] = 'ssl://' . $arrURL['host']; |
486 | $arrURL['port'] = apply_filters('http_request_port', 443); |
487 | $secure_transport = true; |
488 | } else { |
489 | $arrURL['port'] = apply_filters('http_request_default_port', 80); |
490 | } |
491 | } else { |
492 | $arrURL['port'] = apply_filters('http_request_port', $arrURL['port']); |
493 | } |
494 | |
495 | // There are issues with the HTTPS and SSL protocols that cause errors |
496 | // that can be safely ignored and should be ignored. |
497 | if ( true === $secure_transport ) |
498 | $error_reporting = error_reporting(0); |
499 | |
500 | $startDelay = time(); |
501 | |
502 | if ( !defined('WP_DEBUG') || ( defined('WP_DEBUG') && false === WP_DEBUG ) ) |
503 | $handle = @fsockopen($arrURL['host'], $arrURL['port'], $iError, $strError, $r['timeout'] ); |
504 | else |
505 | $handle = fsockopen($arrURL['host'], $arrURL['port'], $iError, $strError, $r['timeout'] ); |
506 | |
507 | $endDelay = time(); |
508 | |
509 | // If the delay is greater than the timeout then fsockopen should't be |
510 | // used, because it will cause a long delay. |
511 | $elapseDelay = ($endDelay-$startDelay) > $r['timeout']; |
512 | if ( true === $elapseDelay ) |
513 | add_option( 'disable_fsockopen', $endDelay, null, true ); |
514 | |
515 | if ( false === $handle ) |
516 | return new WP_Error('http_request_failed', $iError . ': ' . $strError); |
517 | |
518 | // WordPress supports PHP 4.3, which has this function. Removed sanity |
519 | // checking for performance reasons. |
520 | stream_set_timeout($handle, $r['timeout'] ); |
521 | |
522 | $requestPath = $arrURL['path'] . ( isset($arrURL['query']) ? '?' . $arrURL['query'] : '' ); |
523 | $requestPath = empty($requestPath) ? '/' : $requestPath; |
524 | |
525 | $strHeaders = ''; |
526 | $strHeaders .= strtoupper($r['method']) . ' ' . $requestPath . ' HTTP/' . $r['httpversion'] . "\r\n"; |
527 | $strHeaders .= 'Host: ' . $arrURL['host'] . "\r\n"; |
528 | |
529 | if( isset($r['user-agent']) ) |
530 | $strHeaders .= 'User-agent: ' . $r['user-agent'] . "\r\n"; |
531 | |
532 | if ( is_array($r['headers']) ) { |
533 | foreach ( (array) $r['headers'] as $header => $headerValue ) |
534 | $strHeaders .= $header . ': ' . $headerValue . "\r\n"; |
535 | } else { |
536 | $strHeaders .= $r['headers']; |
537 | } |
538 | |
539 | $strHeaders .= "\r\n"; |
540 | |
541 | if ( ! is_null($r['body']) ) |
542 | $strHeaders .= $r['body']; |
543 | |
544 | fwrite($handle, $strHeaders); |
545 | |
546 | if ( ! $r['blocking'] ) { |
547 | fclose($handle); |
548 | return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') ); |
549 | } |
550 | |
551 | $strResponse = ''; |
552 | while ( ! feof($handle) ) |
553 | $strResponse .= fread($handle, 4096); |
554 | |
555 | fclose($handle); |
556 | |
557 | if ( true === $secure_transport ) |
558 | error_reporting($error_reporting); |
559 | |
560 | $process = WP_Http::processResponse($strResponse); |
561 | $arrHeaders = WP_Http::processHeaders($process['headers']); |
562 | |
563 | // Is the response code within the 400 range? |
564 | if ( (int) $arrHeaders['response']['code'] >= 400 && (int) $arrHeaders['response']['code'] < 500 ) |
565 | return new WP_Error('http_request_failed', $arrHeaders['response']['code'] . ': ' . $arrHeaders['response']['message']); |
566 | |
567 | // If location is found, then assume redirect and redirect to location. |
568 | if ( isset($arrHeaders['headers']['location']) ) { |
569 | if ( $r['redirection']-- > 0 ) { |
570 | return $this->request($arrHeaders['headers']['location'], $r); |
571 | } else { |
572 | return new WP_Error('http_request_failed', __('Too many redirects.')); |
573 | } |
574 | } |
575 | |
576 | // If the body was chunk encoded, then decode it. |
577 | if ( ! empty( $process['body'] ) && isset( $arrHeaders['headers']['transfer-encoding'] ) && 'chunked' == $arrHeaders['headers']['transfer-encoding'] ) |
578 | $process['body'] = WP_Http::chunkTransferDecode($process['body']); |
579 | |
580 | return array('headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response']); |
581 | } |
582 | |
583 | /** |
584 | * Whether this class can be used for retrieving an URL. |
585 | * |
586 | * @since 2.7 |
587 | * @static |
588 | * @return boolean False means this class can not be used, true means it can. |
589 | */ |
590 | function test() { |
591 | if ( false !== ($option = get_option( 'disable_fsockopen' )) && time()-$option < 43200 ) // 12 hours |
592 | return false; |
593 | |
594 | if ( function_exists( 'fsockopen' ) ) |
595 | return true; |
596 | |
597 | return false; |
598 | } |
599 | } |
600 | |
601 | /** |
602 | * HTTP request method uses fopen function to retrieve the url. |
603 | * |
604 | * Requires PHP version greater than 4.3.0 for stream support. Does not allow |
605 | * for $context support, but should still be okay, to write the headers, before |
606 | * getting the response. Also requires that 'allow_url_fopen' to be enabled. |
607 | * |
608 | * @package WordPress |
609 | * @subpackage HTTP |
610 | * @since 2.7 |
611 | */ |
612 | class WP_Http_Fopen { |
613 | /** |
614 | * Send a HTTP request to a URI using fopen(). |
615 | * |
616 | * This transport does not support sending of headers and body, therefore |
617 | * should not be used in the instances, where there is a body and headers. |
618 | * |
619 | * Notes: Does not support non-blocking mode. Ignores 'redirection' option. |
620 | * |
621 | * @see WP_Http::retrieve For default options descriptions. |
622 | * |
623 | * @access public |
624 | * @since 2.7 |
625 | * |
626 | * @param string $url URI resource. |
627 | * @param str|array $args Optional. Override the defaults. |
628 | * @return array 'headers', 'body', and 'response' keys. |
629 | */ |
630 | function request($url, $args = array()) { |
631 | global $http_response_header; |
632 | |
633 | $defaults = array( |
634 | 'method' => 'GET', 'timeout' => 5, |
635 | 'redirection' => 5, 'httpversion' => '1.0', |
636 | 'blocking' => true, |
637 | 'headers' => array(), 'body' => null |
638 | ); |
639 | |
640 | $r = wp_parse_args( $args, $defaults ); |
641 | |
642 | $arrURL = parse_url($url); |
643 | |
644 | if ( false === $arrURL ) |
645 | return new WP_Error('http_request_failed', sprintf(__('Malformed URL: %s'), $url)); |
646 | |
647 | if ( 'http' != $arrURL['scheme'] || 'https' != $arrURL['scheme'] ) |
648 | $url = str_replace($arrURL['scheme'], 'http', $url); |
649 | |
650 | if ( !defined('WP_DEBUG') || ( defined('WP_DEBUG') && false === WP_DEBUG ) ) |
651 | $handle = @fopen($url, 'r'); |
652 | else |
653 | $handle = fopen($url, 'r'); |
654 | |
655 | if (! $handle) |
656 | return new WP_Error('http_request_failed', sprintf(__('Could not open handle for fopen() to %s'), $url)); |
657 | |
658 | // WordPress supports PHP 4.3, which has this function. Removed sanity |
659 | // checking for performance reasons. |
660 | stream_set_timeout($handle, $r['timeout'] ); |
661 | |
662 | if ( ! $r['blocking'] ) { |
663 | fclose($handle); |
664 | return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') ); |
665 | } |
666 | |
667 | $strResponse = ''; |
668 | while ( ! feof($handle) ) |
669 | $strResponse .= fread($handle, 4096); |
670 | |
671 | $theHeaders = ''; |
672 | if ( function_exists('stream_get_meta_data') ) { |
673 | $meta = stream_get_meta_data($handle); |
674 | $theHeaders = $meta['wrapper_data']; |
675 | if( isset( $meta['wrapper_data']['headers'] ) ) |
676 | $theHeaders = $meta['wrapper_data']['headers']; |
677 | } else { |
678 | if( ! isset( $http_response_header ) ) |
679 | global $http_response_header; |
680 | $theHeaders = $http_response_header; |
681 | } |
682 | |
683 | fclose($handle); |
684 | |
685 | $processedHeaders = WP_Http::processHeaders($theHeaders); |
686 | |
687 | if ( ! empty( $strResponse ) && isset( $processedHeaders['headers']['transfer-encoding'] ) && 'chunked' == $processedHeaders['headers']['transfer-encoding'] ) |
688 | $strResponse = WP_Http::chunkTransferDecode($strResponse); |
689 | |
690 | return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response']); |
691 | } |
692 | |
693 | /** |
694 | * Whether this class can be used for retrieving an URL. |
695 | * |
696 | * @static |
697 | * @return boolean False means this class can not be used, true means it can. |
698 | */ |
699 | function test() { |
700 | if ( ! function_exists('fopen') || (function_exists('ini_get') && true != ini_get('allow_url_fopen')) ) |
701 | return false; |
702 | |
703 | return true; |
704 | } |
705 | } |
706 | |
707 | /** |
708 | * HTTP request method uses Streams to retrieve the url. |
709 | * |
710 | * Requires PHP 5.0+ and uses fopen with stream context. Requires that |
711 | * 'allow_url_fopen' PHP setting to be enabled. |
712 | * |
713 | * Second preferred method for getting the URL, for PHP 5. |
714 | * |
715 | * @package WordPress |
716 | * @subpackage HTTP |
717 | * @since 2.7 |
718 | */ |
719 | class WP_Http_Streams { |
720 | /** |
721 | * Send a HTTP request to a URI using streams with fopen(). |
722 | * |
723 | * @access public |
724 | * @since 2.7 |
725 | * |
726 | * @param string $url |
727 | * @param str|array $args Optional. Override the defaults. |
728 | * @return array 'headers', 'body', and 'response' keys. |
729 | */ |
730 | function request($url, $args = array()) { |
731 | $defaults = array( |
732 | 'method' => 'GET', 'timeout' => 5, |
733 | 'redirection' => 5, 'httpversion' => '1.0', |
734 | 'blocking' => true, |
735 | 'headers' => array(), 'body' => null |
736 | ); |
737 | |
738 | $r = wp_parse_args( $args, $defaults ); |
739 | |
740 | if ( isset($r['headers']['User-Agent']) ) { |
741 | $r['user-agent'] = $r['headers']['User-Agent']; |
742 | unset($r['headers']['User-Agent']); |
743 | } else if( isset($r['headers']['user-agent']) ) { |
744 | $r['user-agent'] = $r['headers']['user-agent']; |
745 | unset($r['headers']['user-agent']); |
746 | } |
747 | |
748 | $arrURL = parse_url($url); |
749 | |
750 | if ( false === $arrURL ) |
751 | return new WP_Error('http_request_failed', sprintf(__('Malformed URL: %s'), $url)); |
752 | |
753 | if ( 'http' != $arrURL['scheme'] || 'https' != $arrURL['scheme'] ) |
754 | $url = str_replace($arrURL['scheme'], 'http', $url); |
755 | |
756 | // Convert Header array to string. |
757 | $strHeaders = ''; |
758 | if ( is_array( $r['headers'] ) ) |
759 | foreach( $r['headers'] as $name => $value ) |
760 | $strHeaders .= "{$name}: $value\r\n"; |
761 | else if ( is_string( $r['headers'] ) ) |
762 | $strHeaders = $r['headers']; |
763 | |
764 | $arrContext = array('http' => |
765 | array( |
766 | 'method' => strtoupper($r['method']), |
767 | 'user_agent' => $r['user-agent'], |
768 | 'max_redirects' => $r['redirection'], |
769 | 'protocol_version' => (float) $r['httpversion'], |
770 | 'header' => $strHeaders, |
771 | 'timeout' => $r['timeout'] |
772 | ) |
773 | ); |
774 | |
775 | if ( ! is_null($r['body']) && ! empty($r['body'] ) ) |
776 | $arrContext['http']['content'] = $r['body']; |
777 | |
778 | $context = stream_context_create($arrContext); |
779 | |
780 | if ( !defined('WP_DEBUG') || ( defined('WP_DEBUG') && false === WP_DEBUG ) ) |
781 | $handle = @fopen($url, 'r', false, $context); |
782 | else |
783 | $handle = fopen($url, 'r', false, $context); |
784 | |
785 | if ( ! $handle) |
786 | return new WP_Error('http_request_failed', sprintf(__('Could not open handle for fopen() to %s'), $url)); |
787 | |
788 | // WordPress supports PHP 4.3, which has this function. Removed sanity |
789 | // checking for performance reasons. |
790 | stream_set_timeout($handle, $r['timeout'] ); |
791 | |
792 | if ( ! $r['blocking'] ) { |
793 | stream_set_blocking($handle, 0); |
794 | fclose($handle); |
795 | return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') ); |
796 | } |
797 | |
798 | $strResponse = stream_get_contents($handle); |
799 | $meta = stream_get_meta_data($handle); |
800 | |
801 | $processedHeaders = array(); |
802 | if( isset( $meta['wrapper_data']['headers'] ) ) |
803 | $processedHeaders = WP_Http::processHeaders($meta['wrapper_data']['headers']); |
804 | else |
805 | $processedHeaders = WP_Http::processHeaders($meta['wrapper_data']); |
806 | |
807 | if ( ! empty( $strResponse ) && isset( $processedHeaders['headers']['transfer-encoding'] ) && 'chunked' == $processedHeaders['headers']['transfer-encoding'] ) |
808 | $strResponse = WP_Http::chunkTransferDecode($strResponse); |
809 | |
810 | fclose($handle); |
811 | |
812 | return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response']); |
813 | } |
814 | |
815 | /** |
816 | * Whether this class can be used for retrieving an URL. |
817 | * |
818 | * @static |
819 | * @access public |
820 | * @since 2.7 |
821 | * |
822 | * @return boolean False means this class can not be used, true means it can. |
823 | */ |
824 | function test() { |
825 | if ( ! function_exists('fopen') || (function_exists('ini_get') && true != ini_get('allow_url_fopen')) ) |
826 | return false; |
827 | |
828 | if ( version_compare(PHP_VERSION, '5.0', '<') ) |
829 | return false; |
830 | |
831 | return true; |
832 | } |
833 | } |
834 | |
835 | /** |
836 | * HTTP request method uses HTTP extension to retrieve the url. |
837 | * |
838 | * Requires the HTTP extension to be installed. This would be the preferred |
839 | * transport since it can handle a lot of the problems that forces the others to |
840 | * use the HTTP version 1.0. Even if PHP 5.2+ is being used, it doesn't mean |
841 | * that the HTTP extension will be enabled. |
842 | * |
843 | * @package WordPress |
844 | * @subpackage HTTP |
845 | * @since 2.7 |
846 | */ |
847 | class WP_Http_ExtHTTP { |
848 | /** |
849 | * Send a HTTP request to a URI using HTTP extension. |
850 | * |
851 | * Does not support non-blocking. |
852 | * |
853 | * @access public |
854 | * @since 2.7 |
855 | * |
856 | * @param string $url |
857 | * @param str|array $args Optional. Override the defaults. |
858 | * @return array 'headers', 'body', and 'response' keys. |
859 | */ |
860 | function request($url, $args = array()) { |
861 | $defaults = array( |
862 | 'method' => 'GET', 'timeout' => 5, |
863 | 'redirection' => 5, 'httpversion' => '1.0', |
864 | 'blocking' => true, |
865 | 'headers' => array(), 'body' => null |
866 | ); |
867 | |
868 | $r = wp_parse_args( $args, $defaults ); |
869 | |
870 | if ( isset($r['headers']['User-Agent']) ) { |
871 | $r['user-agent'] = $r['headers']['User-Agent']; |
872 | unset($r['headers']['User-Agent']); |
873 | } else if( isset($r['headers']['user-agent']) ) { |
874 | $r['user-agent'] = $r['headers']['user-agent']; |
875 | unset($r['headers']['user-agent']); |
876 | } |
877 | |
878 | switch ( $r['method'] ) { |
879 | case 'POST': |
880 | $r['method'] = HTTP_METH_POST; |
881 | break; |
882 | case 'HEAD': |
883 | $r['method'] = HTTP_METH_HEAD; |
884 | break; |
885 | case 'GET': |
886 | default: |
887 | $r['method'] = HTTP_METH_GET; |
888 | } |
889 | |
890 | $arrURL = parse_url($url); |
891 | |
892 | if ( 'http' != $arrURL['scheme'] || 'https' != $arrURL['scheme'] ) |
893 | $url = str_replace($arrURL['scheme'], 'http', $url); |
894 | |
895 | $options = array( |
896 | 'timeout' => $r['timeout'], |
897 | 'connecttimeout' => $r['timeout'], |
898 | 'redirect' => $r['redirection'], |
899 | 'useragent' => $r['user-agent'], |
900 | 'headers' => $r['headers'], |
901 | ); |
902 | |
903 | if ( !defined('WP_DEBUG') || ( defined('WP_DEBUG') && false === WP_DEBUG ) ) //Emits warning level notices for max redirects and timeouts |
904 | $strResponse = @http_request($r['method'], $url, $r['body'], $options, $info); |
905 | else |
906 | $strResponse = http_request($r['method'], $url, $r['body'], $options, $info); //Emits warning level notices for max redirects and timeouts |
907 | |
908 | if ( false === $strResponse || ! empty($info['error']) ) //Error may still be set, Response may return headers or partial document, and error contains a reason the request was aborted, eg, timeout expired or max-redirects reached |
909 | return new WP_Error('http_request_failed', $info['response_code'] . ': ' . $info['error']); |
910 | |
911 | if ( ! $r['blocking'] ) |
912 | return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') ); |
913 | |
914 | list($theHeaders, $theBody) = explode("\r\n\r\n", $strResponse, 2); |
915 | $theHeaders = WP_Http::processHeaders($theHeaders); |
916 | |
917 | if ( ! empty( $theBody ) && isset( $theHeaders['headers']['transfer-encoding'] ) && 'chunked' == $theHeaders['headers']['transfer-encoding'] ) { |
918 | if ( !defined('WP_DEBUG') || ( defined('WP_DEBUG') && false === WP_DEBUG ) ) |
919 | $theBody = @http_chunked_decode($theBody); |
920 | else |
921 | $theBody = http_chunked_decode($theBody); |
922 | } |
923 | |
924 | $theResponse = array(); |
925 | $theResponse['code'] = $info['response_code']; |
926 | $theResponse['message'] = get_status_header_desc($info['response_code']); |
927 | |
928 | return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $theResponse); |
929 | } |
930 | |
931 | /** |
932 | * Whether this class can be used for retrieving an URL. |
933 | * |
934 | * @static |
935 | * @since 2.7 |
936 | * |
937 | * @return boolean False means this class can not be used, true means it can. |
938 | */ |
939 | function test() { |
940 | if ( function_exists('http_request') ) |
941 | return true; |
942 | |
943 | return false; |
944 | } |
945 | } |
946 | |
947 | /** |
948 | * HTTP request method uses Curl extension to retrieve the url. |
949 | * |
950 | * Requires the Curl extension to be installed. |
951 | * |
952 | * @package WordPress |
953 | * @subpackage HTTP |
954 | * @since 2.7 |
955 | */ |
956 | class WP_Http_Curl { |
957 | /** |
958 | * Send a HTTP request to a URI using cURL extension. |
959 | * |
960 | * @access public |
961 | * @since 2.7 |
962 | * |
963 | * @param string $url |
964 | * @param str|array $args Optional. Override the defaults. |
965 | * @return array 'headers', 'body', and 'response' keys. |
966 | */ |
967 | function request($url, $args = array()) { |
968 | $defaults = array( |
969 | 'method' => 'GET', 'timeout' => 5, |
970 | 'redirection' => 5, 'httpversion' => '1.0', |
971 | 'blocking' => true, |
972 | 'headers' => array(), 'body' => null |
973 | ); |
974 | |
975 | $r = wp_parse_args( $args, $defaults ); |
976 | |
977 | if ( isset($r['headers']['User-Agent']) ) { |
978 | $r['user-agent'] = $r['headers']['User-Agent']; |
979 | unset($r['headers']['User-Agent']); |
980 | } else if( isset($r['headers']['user-agent']) ) { |
981 | $r['user-agent'] = $r['headers']['user-agent']; |
982 | unset($r['headers']['user-agent']); |
983 | } |
984 | |
985 | // If timeout is a float less than 1, round it up to 1. |
986 | if ( $r['timeout'] > 0 && $r['timeout'] < 1 ) |
987 | $r['timeout'] = 1; |
988 | |
989 | $handle = curl_init(); |
990 | curl_setopt( $handle, CURLOPT_URL, $url); |
991 | |
992 | if ( 'HEAD' === $r['method'] ) { |
993 | curl_setopt( $handle, CURLOPT_NOBODY, true ); |
994 | } |
995 | |
996 | if ( true === $r['blocking'] ) { |
997 | curl_setopt( $handle, CURLOPT_HEADER, true ); |
998 | curl_setopt( $handle, CURLOPT_RETURNTRANSFER, 1 ); |
999 | } else { |
1000 | curl_setopt( $handle, CURLOPT_HEADER, false ); |
1001 | curl_setopt( $handle, CURLOPT_NOBODY, true ); |
1002 | curl_setopt( $handle, CURLOPT_RETURNTRANSFER, 0 ); |
1003 | } |
1004 | |
1005 | curl_setopt( $handle, CURLOPT_USERAGENT, $r['user-agent'] ); |
1006 | curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, 1 ); |
1007 | curl_setopt( $handle, CURLOPT_TIMEOUT, $r['timeout'] ); |
1008 | curl_setopt( $handle, CURLOPT_MAXREDIRS, $r['redirection'] ); |
1009 | |
1010 | if ( !ini_get('safe_mode') && !ini_get('open_basedir') ) |
1011 | curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, true ); |
1012 | |
1013 | if( ! is_null($r['headers']) ) |
1014 | curl_setopt( $handle, CURLOPT_HTTPHEADER, $r['headers'] ); |
1015 | |
1016 | if ( $r['httpversion'] == '1.0' ) |
1017 | curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 ); |
1018 | else |
1019 | curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); |
1020 | |
1021 | if ( ! $r['blocking'] ) { |
1022 | curl_exec( $handle ); |
1023 | curl_close( $handle ); |
1024 | return array( 'headers' => array(), 'body' => '', 'response' => array('code', 'message') ); |
1025 | } |
1026 | |
1027 | $theResponse = curl_exec( $handle ); |
1028 | |
1029 | if ( !empty($theResponse) ) { |
1030 | $headerLength = curl_getinfo($handle, CURLINFO_HEADER_SIZE); |
1031 | $theHeaders = trim( substr($theResponse, 0, $headerLength) ); |
1032 | $theBody = substr( $theResponse, $headerLength ); |
1033 | if ( false !== strrpos($theHeaders, "\r\n\r\n") ) { |
1034 | $headerParts = explode("\r\n\r\n", $theHeaders); |
1035 | $theHeaders = $headerParts[ count($headerParts) -1 ]; |
1036 | } |
1037 | $theHeaders = WP_Http::processHeaders($theHeaders); |
1038 | } else { |
1039 | if ( $curl_error = curl_error($handle) ) |
1040 | return new WP_Error('http_request_failed', $curl_error); |
1041 | if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array(301, 302) ) ) |
1042 | return new WP_Error('http_request_failed', __('Too many redirects.')); |
1043 | |
1044 | $theHeaders = array( 'headers' => array() ); |
1045 | $theBody = ''; |
1046 | } |
1047 | $response = array(); |
1048 | $response['code'] = curl_getinfo( $handle, CURLINFO_HTTP_CODE ); |
1049 | $response['message'] = get_status_header_desc($response['code']); |
1050 | |
1051 | curl_close( $handle ); |
1052 | |
1053 | return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response); |
1054 | } |
1055 | |
1056 | /** |
1057 | * Whether this class can be used for retrieving an URL. |
1058 | * |
1059 | * @static |
1060 | * @since 2.7 |
1061 | * |
1062 | * @return boolean False means this class can not be used, true means it can. |
1063 | */ |
1064 | function test() { |
1065 | if ( function_exists('curl_init') ) |
1066 | return true; |
1067 | |
1068 | return false; |
1069 | } |
1070 | } |
1071 | |
1072 | /** |
1073 | * Returns the initialized WP_Http Object |
1074 | * |
1075 | * @since 2.7 |
1076 | * @access private |
1077 | * |
1078 | * @return WP_Http HTTP Transport object. |
1079 | */ |
1080 | function &_wp_http_get_object() { |
1081 | static $http; |
1082 | |
1083 | if ( is_null($http) ) |
1084 | $http = new WP_Http(); |
1085 | |
1086 | return $http; |
1087 | } |
1088 | |
1089 | /** |
1090 | * Retrieve the raw response from the HTTP request. |
1091 | * |
1092 | * The array structure is a little complex. |
1093 | * |
1094 | * <code> |
1095 | * $res = array( 'headers' => array(), 'response' => array('code', 'message') ); |
1096 | * </code> |
1097 | * |
1098 | * All of the headers in $res['headers'] are with the name as the key and the |
1099 | * value as the value. So to get the User-Agent, you would do the following. |
1100 | * |
1101 | * <code> |
1102 | * $user_agent = $res['headers']['user-agent']; |
1103 | * </code> |
1104 | * |
1105 | * The body is the raw response content and can be retrieved from $res['body']. |
1106 | * |
1107 | * This function is called first to make the request and there are other API |
1108 | * functions to abstract out the above convoluted setup. |
1109 | * |
1110 | * @since 2.7.0 |
1111 | * |
1112 | * @param string $url Site URL to retrieve. |
1113 | * @param array $args Optional. Override the defaults. |
1114 | * @return string The body of the response |
1115 | */ |
1116 | function wp_remote_request($url, $args = array()) { |
1117 | $objFetchSite = _wp_http_get_object(); |
1118 | return $objFetchSite->request($url, $args); |
1119 | } |
1120 | |
1121 | /** |
1122 | * Retrieve the raw response from the HTTP request using the GET method. |
1123 | * |
1124 | * @see wp_remote_request() For more information on the response array format. |
1125 | * |
1126 | * @since 2.7 |
1127 | * |
1128 | * @param string $url Site URL to retrieve. |
1129 | * @param array $args Optional. Override the defaults. |
1130 | * @return string The body of the response |
1131 | */ |
1132 | function wp_remote_get($url, $args = array()) { |
1133 | $objFetchSite = _wp_http_get_object(); |
1134 | |
1135 | return $objFetchSite->get($url, $args); |
1136 | } |
1137 | |
1138 | /** |
1139 | * Retrieve the raw response from the HTTP request using the POST method. |
1140 | * |
1141 | * @see wp_remote_request() For more information on the response array format. |
1142 | * |
1143 | * @since 2.7 |
1144 | * |
1145 | * @param string $url Site URL to retrieve. |
1146 | * @param array $args Optional. Override the defaults. |
1147 | * @return string The body of the response |
1148 | */ |
1149 | function wp_remote_post($url, $args = array()) { |
1150 | $objFetchSite = _wp_http_get_object(); |
1151 | return $objFetchSite->post($url, $args); |
1152 | } |
1153 | |
1154 | /** |
1155 | * Retrieve the raw response from the HTTP request using the HEAD method. |
1156 | * |
1157 | * @see wp_remote_request() For more information on the response array format. |
1158 | * |
1159 | * @since 2.7 |
1160 | * |
1161 | * @param string $url Site URL to retrieve. |
1162 | * @param array $args Optional. Override the defaults. |
1163 | * @return string The body of the response |
1164 | */ |
1165 | function wp_remote_head($url, $args = array()) { |
1166 | $objFetchSite = _wp_http_get_object(); |
1167 | return $objFetchSite->head($url, $args); |
1168 | } |
1169 | |
1170 | /** |
1171 | * Retrieve only the headers from the raw response. |
1172 | * |
1173 | * @since 2.7 |
1174 | * |
1175 | * @param array $response HTTP response. |
1176 | * @return array The headers of the response. Empty array if incorrect parameter given. |
1177 | */ |
1178 | function wp_remote_retrieve_headers(&$response) { |
1179 | if ( ! isset($response['headers']) || ! is_array($response['headers'])) |
1180 | return array(); |
1181 | |
1182 | return $response['headers']; |
1183 | } |
1184 | |
1185 | /** |
1186 | * Retrieve a single header by name from the raw response. |
1187 | * |
1188 | * @since 2.7 |
1189 | * |
1190 | * @param array $response |
1191 | * @param string $header Header name to retrieve value from. |
1192 | * @return array The header value. Empty string on if incorrect parameter given. |
1193 | */ |
1194 | function wp_remote_retrieve_header(&$response, $header) { |
1195 | if ( ! isset($response['headers']) || ! is_array($response['headers'])) |
1196 | return ''; |
1197 | |
1198 | if ( array_key_exists($header, $response['headers']) ) |
1199 | return $response['headers'][$header]; |
1200 | |
1201 | return ''; |
1202 | } |
1203 | |
1204 | /** |
1205 | * Retrieve only the response code from the raw response. |
1206 | * |
1207 | * Will return an empty array if incorrect parameter value is given. |
1208 | * |
1209 | * @since 2.7 |
1210 | * |
1211 | * @param array $response HTTP response. |
1212 | * @return array The keys 'code' and 'message' give information on the response. |
1213 | */ |
1214 | function wp_remote_retrieve_response_code(&$response) { |
1215 | if ( ! isset($response['response']) || ! is_array($response['response'])) |
1216 | return ''; |
1217 | |
1218 | return $response['response']['code']; |
1219 | } |
1220 | |
1221 | /** |
1222 | * Retrieve only the response message from the raw response. |
1223 | * |
1224 | * Will return an empty array if incorrect parameter value is given. |
1225 | * |
1226 | * @since 2.7 |
1227 | * |
1228 | * @param array $response HTTP response. |
1229 | * @return array The keys 'code' and 'message' give information on the response. |
1230 | */ |
1231 | function wp_remote_retrieve_response_message(&$response) { |
1232 | if ( ! isset($response['response']) || ! is_array($response['response'])) |
1233 | return ''; |
1234 | |
1235 | return $response['response']['message']; |
1236 | } |
1237 | |
1238 | /** |
1239 | * Retrieve only the body from the raw response. |
1240 | * |
1241 | * @since 2.7 |
1242 | * |
1243 | * @param array $response HTTP response. |
1244 | * @return string The body of the response. Empty string if no body or incorrect parameter given. |
1245 | */ |
1246 | function wp_remote_retrieve_body(&$response) { |
1247 | if ( ! isset($response['body']) ) |
1248 | return ''; |
1249 | |
1250 | return $response['body']; |
1251 | } |
1252 | |
1253 | ?> |