wp/wp-includes/http.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
     2 /**
     2 /**
     3  * Simple and uniform HTTP request API.
     3  * Simple and uniform HTTP request API.
     4  *
     4  *
     5  * Will eventually replace and standardize the WordPress HTTP requests made.
     5  * Will eventually replace and standardize the WordPress HTTP requests made.
     6  *
     6  *
     7  * @link http://trac.wordpress.org/ticket/4779 HTTP API Proposal
     7  * @link https://core.trac.wordpress.org/ticket/4779 HTTP API Proposal
     8  *
     8  *
     9  * @package WordPress
     9  * @package WordPress
    10  * @subpackage HTTP
    10  * @subpackage HTTP
    11  * @since 2.7.0
    11  * @since 2.7.0
    12  */
    12  */
    32  * Retrieve the raw response from a safe HTTP request.
    32  * Retrieve the raw response from a safe HTTP request.
    33  *
    33  *
    34  * This function is ideal when the HTTP request is being made to an arbitrary
    34  * This function is ideal when the HTTP request is being made to an arbitrary
    35  * URL. The URL is validated to avoid redirection and request forgery attacks.
    35  * URL. The URL is validated to avoid redirection and request forgery attacks.
    36  *
    36  *
    37  * @see wp_remote_request() For more information on the response array format
       
    38  * 	and default arguments.
       
    39  *
       
    40  * @since 3.6.0
    37  * @since 3.6.0
    41  *
    38  *
    42  * @param string $url Site URL to retrieve.
    39  * @see wp_remote_request() For more information on the response array format.
    43  * @param array $args Optional. Override the defaults.
    40  * @see WP_Http::request() For default arguments information.
       
    41  *
       
    42  * @param string $url  Site URL to retrieve.
       
    43  * @param array  $args Optional. Request arguments. Default empty array.
    44  * @return WP_Error|array The response or WP_Error on failure.
    44  * @return WP_Error|array The response or WP_Error on failure.
    45  */
    45  */
    46 function wp_safe_remote_request( $url, $args = array() ) {
    46 function wp_safe_remote_request( $url, $args = array() ) {
    47 	$args['reject_unsafe_urls'] = true;
    47 	$args['reject_unsafe_urls'] = true;
    48 	$http = _wp_http_get_object();
    48 	$http = _wp_http_get_object();
    53  * Retrieve the raw response from a safe HTTP request using the GET method.
    53  * Retrieve the raw response from a safe HTTP request using the GET method.
    54  *
    54  *
    55  * This function is ideal when the HTTP request is being made to an arbitrary
    55  * This function is ideal when the HTTP request is being made to an arbitrary
    56  * URL. The URL is validated to avoid redirection and request forgery attacks.
    56  * URL. The URL is validated to avoid redirection and request forgery attacks.
    57  *
    57  *
    58  * @see wp_remote_request() For more information on the response array format
       
    59  * 	and default arguments.
       
    60  *
       
    61  * @since 3.6.0
    58  * @since 3.6.0
    62  *
    59  *
    63  * @param string $url Site URL to retrieve.
    60  * @see wp_remote_request() For more information on the response array format.
    64  * @param array $args Optional. Override the defaults.
    61  * @see WP_Http::request() For default arguments information.
       
    62  *
       
    63  * @param string $url  Site URL to retrieve.
       
    64  * @param array  $args Optional. Request arguments. Default empty array.
    65  * @return WP_Error|array The response or WP_Error on failure.
    65  * @return WP_Error|array The response or WP_Error on failure.
    66  */
    66  */
    67 function wp_safe_remote_get( $url, $args = array() ) {
    67 function wp_safe_remote_get( $url, $args = array() ) {
    68 	$args['reject_unsafe_urls'] = true;
    68 	$args['reject_unsafe_urls'] = true;
    69 	$http = _wp_http_get_object();
    69 	$http = _wp_http_get_object();
    74  * Retrieve the raw response from a safe HTTP request using the POST method.
    74  * Retrieve the raw response from a safe HTTP request using the POST method.
    75  *
    75  *
    76  * This function is ideal when the HTTP request is being made to an arbitrary
    76  * This function is ideal when the HTTP request is being made to an arbitrary
    77  * URL. The URL is validated to avoid redirection and request forgery attacks.
    77  * URL. The URL is validated to avoid redirection and request forgery attacks.
    78  *
    78  *
    79  * @see wp_remote_request() For more information on the response array format
       
    80  * 	and default arguments.
       
    81  *
       
    82  * @since 3.6.0
    79  * @since 3.6.0
    83  *
    80  *
    84  * @param string $url Site URL to retrieve.
    81  * @see wp_remote_request() For more information on the response array format.
    85  * @param array $args Optional. Override the defaults.
    82  * @see WP_Http::request() For default arguments information.
       
    83  *
       
    84  * @param string $url  Site URL to retrieve.
       
    85  * @param array  $args Optional. Request arguments. Default empty array.
    86  * @return WP_Error|array The response or WP_Error on failure.
    86  * @return WP_Error|array The response or WP_Error on failure.
    87  */
    87  */
    88 function wp_safe_remote_post( $url, $args = array() ) {
    88 function wp_safe_remote_post( $url, $args = array() ) {
    89 	$args['reject_unsafe_urls'] = true;
    89 	$args['reject_unsafe_urls'] = true;
    90 	$http = _wp_http_get_object();
    90 	$http = _wp_http_get_object();
    95  * Retrieve the raw response from a safe HTTP request using the HEAD method.
    95  * Retrieve the raw response from a safe HTTP request using the HEAD method.
    96  *
    96  *
    97  * This function is ideal when the HTTP request is being made to an arbitrary
    97  * This function is ideal when the HTTP request is being made to an arbitrary
    98  * URL. The URL is validated to avoid redirection and request forgery attacks.
    98  * URL. The URL is validated to avoid redirection and request forgery attacks.
    99  *
    99  *
   100  * @see wp_remote_request() For more information on the response array format
       
   101  * 	and default arguments.
       
   102  *
       
   103  * @since 3.6.0
   100  * @since 3.6.0
   104  *
   101  *
       
   102  * @see wp_remote_request() For more information on the response array format.
       
   103  * @see WP_Http::request() For default arguments information.
       
   104  *
   105  * @param string $url Site URL to retrieve.
   105  * @param string $url Site URL to retrieve.
   106  * @param array $args Optional. Override the defaults.
   106  * @param array $args Optional. Request arguments. Default empty array.
   107  * @return WP_Error|array The response or WP_Error on failure.
   107  * @return WP_Error|array The response or WP_Error on failure.
   108  */
   108  */
   109 function wp_safe_remote_head( $url, $args = array() ) {
   109 function wp_safe_remote_head( $url, $args = array() ) {
   110 	$args['reject_unsafe_urls'] = true;
   110 	$args['reject_unsafe_urls'] = true;
   111 	$http = _wp_http_get_object();
   111 	$http = _wp_http_get_object();
   113 }
   113 }
   114 
   114 
   115 /**
   115 /**
   116  * Retrieve the raw response from the HTTP request.
   116  * Retrieve the raw response from the HTTP request.
   117  *
   117  *
   118  * The array structure is a little complex.
   118  * The array structure is a little complex:
   119  *
   119  *
   120  * <code>
   120  *     $res = array(
   121  * $res = array( 'headers' => array(), 'response' => array('code' => int, 'message' => string) );
   121  *         'headers'  => array(),
   122  * </code>
   122  *         'response' => array(
       
   123  *             'code'    => int,
       
   124  *             'message' => string
       
   125  *         )
       
   126  *     );
   123  *
   127  *
   124  * All of the headers in $res['headers'] are with the name as the key and the
   128  * All of the headers in $res['headers'] are with the name as the key and the
   125  * value as the value. So to get the User-Agent, you would do the following.
   129  * value as the value. So to get the User-Agent, you would do the following.
   126  *
   130  *
   127  * <code>
   131  *     $user_agent = $res['headers']['user-agent'];
   128  * $user_agent = $res['headers']['user-agent'];
       
   129  * </code>
       
   130  *
   132  *
   131  * The body is the raw response content and can be retrieved from $res['body'].
   133  * The body is the raw response content and can be retrieved from $res['body'].
   132  *
   134  *
   133  * This function is called first to make the request and there are other API
   135  * This function is called first to make the request and there are other API
   134  * functions to abstract out the above convoluted setup.
   136  * functions to abstract out the above convoluted setup.
   135  *
   137  *
   136  * List of default arguments:
   138  * Request method defaults for helper functions:
   137  * 'method'      => 'GET'
       
   138  *  - Default 'GET'  for wp_remote_get()
   139  *  - Default 'GET'  for wp_remote_get()
   139  *  - Default 'POST' for wp_remote_post()
   140  *  - Default 'POST' for wp_remote_post()
   140  *  - Default 'HEAD' for wp_remote_head()
   141  *  - Default 'HEAD' for wp_remote_head()
   141  * 'timeout'     => 5
   142  *
   142  * 'redirection' => 5
   143  * @since 2.7.0
   143  * 'httpversion' => '1.0'
   144  *
   144  * 'user-agent'  => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
   145  * @see WP_Http::request() For additional information on default arguments.
   145  * 'blocking'    => true
   146  *
   146  * 'headers'     => array()
   147  * @param string $url  Site URL to retrieve.
   147  * 'cookies'     => array()
   148  * @param array  $args Optional. Request arguments. Default empty array.
   148  * 'body'        => null
       
   149  * 'compress'    => false,
       
   150  * 'decompress'  => true,
       
   151  * 'sslverify'   => true,
       
   152  * 'stream'      => false,
       
   153  * 'filename'    => null
       
   154  *
       
   155  * @since 2.7.0
       
   156  *
       
   157  * @param string $url Site URL to retrieve.
       
   158  * @param array $args Optional. Override the defaults.
       
   159  * @return WP_Error|array The response or WP_Error on failure.
   149  * @return WP_Error|array The response or WP_Error on failure.
   160  */
   150  */
   161 function wp_remote_request($url, $args = array()) {
   151 function wp_remote_request($url, $args = array()) {
   162 	$objFetchSite = _wp_http_get_object();
   152 	$objFetchSite = _wp_http_get_object();
   163 	return $objFetchSite->request($url, $args);
   153 	return $objFetchSite->request($url, $args);
   164 }
   154 }
   165 
   155 
   166 /**
   156 /**
   167  * Retrieve the raw response from the HTTP request using the GET method.
   157  * Retrieve the raw response from the HTTP request using the GET method.
   168  *
   158  *
   169  * @see wp_remote_request() For more information on the response array format and default arguments.
   159  * @since 2.7.0
   170  *
   160  *
   171  * @since 2.7.0
   161  * @see wp_remote_request() For more information on the response array format.
   172  *
   162  * @see WP_Http::request() For default arguments information.
   173  * @param string $url Site URL to retrieve.
   163  *
   174  * @param array $args Optional. Override the defaults.
   164  * @param string $url  Site URL to retrieve.
       
   165  * @param array  $args Optional. Request arguments. Default empty array.
   175  * @return WP_Error|array The response or WP_Error on failure.
   166  * @return WP_Error|array The response or WP_Error on failure.
   176  */
   167  */
   177 function wp_remote_get($url, $args = array()) {
   168 function wp_remote_get($url, $args = array()) {
   178 	$objFetchSite = _wp_http_get_object();
   169 	$objFetchSite = _wp_http_get_object();
   179 	return $objFetchSite->get($url, $args);
   170 	return $objFetchSite->get($url, $args);
   180 }
   171 }
   181 
   172 
   182 /**
   173 /**
   183  * Retrieve the raw response from the HTTP request using the POST method.
   174  * Retrieve the raw response from the HTTP request using the POST method.
   184  *
   175  *
   185  * @see wp_remote_request() For more information on the response array format and default arguments.
   176  * @since 2.7.0
   186  *
   177  *
   187  * @since 2.7.0
   178  * @see wp_remote_request() For more information on the response array format.
   188  *
   179  * @see WP_Http::request() For default arguments information.
   189  * @param string $url Site URL to retrieve.
   180  *
   190  * @param array $args Optional. Override the defaults.
   181  * @param string $url  Site URL to retrieve.
       
   182  * @param array  $args Optional. Request arguments. Default empty array.
   191  * @return WP_Error|array The response or WP_Error on failure.
   183  * @return WP_Error|array The response or WP_Error on failure.
   192  */
   184  */
   193 function wp_remote_post($url, $args = array()) {
   185 function wp_remote_post($url, $args = array()) {
   194 	$objFetchSite = _wp_http_get_object();
   186 	$objFetchSite = _wp_http_get_object();
   195 	return $objFetchSite->post($url, $args);
   187 	return $objFetchSite->post($url, $args);
   196 }
   188 }
   197 
   189 
   198 /**
   190 /**
   199  * Retrieve the raw response from the HTTP request using the HEAD method.
   191  * Retrieve the raw response from the HTTP request using the HEAD method.
   200  *
   192  *
   201  * @see wp_remote_request() For more information on the response array format and default arguments.
   193  * @since 2.7.0
   202  *
   194  *
   203  * @since 2.7.0
   195  * @see wp_remote_request() For more information on the response array format.
   204  *
   196  * @see WP_Http::request() For default arguments information.
   205  * @param string $url Site URL to retrieve.
   197  *
   206  * @param array $args Optional. Override the defaults.
   198  * @param string $url  Site URL to retrieve.
       
   199  * @param array  $args Optional. Request arguments. Default empty array.
   207  * @return WP_Error|array The response or WP_Error on failure.
   200  * @return WP_Error|array The response or WP_Error on failure.
   208  */
   201  */
   209 function wp_remote_head($url, $args = array()) {
   202 function wp_remote_head($url, $args = array()) {
   210 	$objFetchSite = _wp_http_get_object();
   203 	$objFetchSite = _wp_http_get_object();
   211 	return $objFetchSite->head($url, $args);
   204 	return $objFetchSite->head($url, $args);
   217  * @since 2.7.0
   210  * @since 2.7.0
   218  *
   211  *
   219  * @param array $response HTTP response.
   212  * @param array $response HTTP response.
   220  * @return array The headers of the response. Empty array if incorrect parameter given.
   213  * @return array The headers of the response. Empty array if incorrect parameter given.
   221  */
   214  */
   222 function wp_remote_retrieve_headers(&$response) {
   215 function wp_remote_retrieve_headers( $response ) {
   223 	if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers']))
   216 	if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers']))
   224 		return array();
   217 		return array();
   225 
   218 
   226 	return $response['headers'];
   219 	return $response['headers'];
   227 }
   220 }
   233  *
   226  *
   234  * @param array $response
   227  * @param array $response
   235  * @param string $header Header name to retrieve value from.
   228  * @param string $header Header name to retrieve value from.
   236  * @return string The header value. Empty string on if incorrect parameter given, or if the header doesn't exist.
   229  * @return string The header value. Empty string on if incorrect parameter given, or if the header doesn't exist.
   237  */
   230  */
   238 function wp_remote_retrieve_header(&$response, $header) {
   231 function wp_remote_retrieve_header( $response, $header ) {
   239 	if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers']))
   232 	if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers']))
   240 		return '';
   233 		return '';
   241 
   234 
   242 	if ( array_key_exists($header, $response['headers']) )
   235 	if ( array_key_exists($header, $response['headers']) )
   243 		return $response['headers'][$header];
   236 		return $response['headers'][$header];
   251  * Will return an empty array if incorrect parameter value is given.
   244  * Will return an empty array if incorrect parameter value is given.
   252  *
   245  *
   253  * @since 2.7.0
   246  * @since 2.7.0
   254  *
   247  *
   255  * @param array $response HTTP response.
   248  * @param array $response HTTP response.
   256  * @return string the response code. Empty string on incorrect parameter given.
   249  * @return int|string The response code as an integer. Empty string on incorrect parameter given.
   257  */
   250  */
   258 function wp_remote_retrieve_response_code(&$response) {
   251 function wp_remote_retrieve_response_code( $response ) {
   259 	if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response']))
   252 	if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response']))
   260 		return '';
   253 		return '';
   261 
   254 
   262 	return $response['response']['code'];
   255 	return $response['response']['code'];
   263 }
   256 }
   270  * @since 2.7.0
   263  * @since 2.7.0
   271  *
   264  *
   272  * @param array $response HTTP response.
   265  * @param array $response HTTP response.
   273  * @return string The response message. Empty string on incorrect parameter given.
   266  * @return string The response message. Empty string on incorrect parameter given.
   274  */
   267  */
   275 function wp_remote_retrieve_response_message(&$response) {
   268 function wp_remote_retrieve_response_message( $response ) {
   276 	if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response']))
   269 	if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response']))
   277 		return '';
   270 		return '';
   278 
   271 
   279 	return $response['response']['message'];
   272 	return $response['response']['message'];
   280 }
   273 }
   285  * @since 2.7.0
   278  * @since 2.7.0
   286  *
   279  *
   287  * @param array $response HTTP response.
   280  * @param array $response HTTP response.
   288  * @return string The body of the response. Empty string if no body or incorrect parameter given.
   281  * @return string The body of the response. Empty string if no body or incorrect parameter given.
   289  */
   282  */
   290 function wp_remote_retrieve_body(&$response) {
   283 function wp_remote_retrieve_body( $response ) {
   291 	if ( is_wp_error($response) || ! isset($response['body']) )
   284 	if ( is_wp_error($response) || ! isset($response['body']) )
   292 		return '';
   285 		return '';
   293 
   286 
   294 	return $response['body'];
   287 	return $response['body'];
   295 }
   288 }
   386 /**
   379 /**
   387  * Determines if the HTTP origin is an authorized one.
   380  * Determines if the HTTP origin is an authorized one.
   388  *
   381  *
   389  * @since 3.4.0
   382  * @since 3.4.0
   390  *
   383  *
   391  * @param string Origin URL. If not provided, the value of get_http_origin() is used.
   384  * @param null|string $origin Origin URL. If not provided, the value of get_http_origin() is used.
   392  * @return bool True if the origin is allowed. False otherwise.
   385  * @return bool|null True if the origin is allowed. False otherwise.
   393  */
   386  */
   394 function is_allowed_http_origin( $origin = null ) {
   387 function is_allowed_http_origin( $origin = null ) {
   395 	$origin_arg = $origin;
   388 	$origin_arg = $origin;
   396 
   389 
   397 	if ( null === $origin )
   390 	if ( null === $origin )
   446 /**
   439 /**
   447  * Validate a URL for safe use in the HTTP API.
   440  * Validate a URL for safe use in the HTTP API.
   448  *
   441  *
   449  * @since 3.5.2
   442  * @since 3.5.2
   450  *
   443  *
   451  * @return mixed URL or false on failure.
   444  * @param string $url
       
   445  * @return false|string URL or false on failure.
   452  */
   446  */
   453 function wp_http_validate_url( $url ) {
   447 function wp_http_validate_url( $url ) {
       
   448 	$original_url = $url;
   454 	$url = wp_kses_bad_protocol( $url, array( 'http', 'https' ) );
   449 	$url = wp_kses_bad_protocol( $url, array( 'http', 'https' ) );
   455 	if ( ! $url )
   450 	if ( ! $url || strtolower( $url ) !== strtolower( $original_url ) )
   456 		return false;
   451 		return false;
   457 
   452 
   458 	$parsed_url = @parse_url( $url );
   453 	$parsed_url = @parse_url( $url );
   459 	if ( ! $parsed_url || empty( $parsed_url['host'] ) )
   454 	if ( ! $parsed_url || empty( $parsed_url['host'] ) )
   460 		return false;
   455 		return false;
   461 
   456 
   462 	if ( isset( $parsed_url['user'] ) || isset( $parsed_url['pass'] ) )
   457 	if ( isset( $parsed_url['user'] ) || isset( $parsed_url['pass'] ) )
   463 		return false;
   458 		return false;
   464 
   459 
   465 	if ( false !== strpos( $parsed_url['host'], ':' ) )
   460 	if ( false !== strpbrk( $parsed_url['host'], ':#?[]' ) )
   466 		return false;
   461 		return false;
   467 
   462 
   468 	$parsed_home = @parse_url( get_option( 'home' ) );
   463 	$parsed_home = @parse_url( get_option( 'home' ) );
   469 
   464 
   470 	$same_host = strtolower( $parsed_home['host'] ) === strtolower( $parsed_url['host'] );
   465 	$same_host = strtolower( $parsed_home['host'] ) === strtolower( $parsed_url['host'] );
   478 			if ( $ip === $host ) // Error condition for gethostbyname()
   473 			if ( $ip === $host ) // Error condition for gethostbyname()
   479 				$ip = false;
   474 				$ip = false;
   480 		}
   475 		}
   481 		if ( $ip ) {
   476 		if ( $ip ) {
   482 			$parts = array_map( 'intval', explode( '.', $ip ) );
   477 			$parts = array_map( 'intval', explode( '.', $ip ) );
   483 			if ( '127.0.0.1' === $ip
   478 			if ( 127 === $parts[0] || 10 === $parts[0]
   484 				|| ( 10 === $parts[0] )
       
   485 				|| ( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] )
   479 				|| ( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] )
   486 				|| ( 192 === $parts[0] && 168 === $parts[1] )
   480 				|| ( 192 === $parts[0] && 168 === $parts[1] )
   487 			) {
   481 			) {
   488 				// If host appears local, reject unless specifically allowed.
   482 				// If host appears local, reject unless specifically allowed.
   489 				/**
   483 				/**
   508 
   502 
   509 	$port = $parsed_url['port'];
   503 	$port = $parsed_url['port'];
   510 	if ( 80 === $port || 443 === $port || 8080 === $port )
   504 	if ( 80 === $port || 443 === $port || 8080 === $port )
   511 		return $url;
   505 		return $url;
   512 
   506 
   513 	if ( $parsed_home && $same_host && $parsed_home['port'] === $port )
   507 	if ( $parsed_home && $same_host && isset( $parsed_home['port'] ) && $parsed_home['port'] === $port )
   514 		return $url;
   508 		return $url;
   515 
   509 
   516 	return false;
   510 	return false;
   517 }
   511 }
   518 
   512 
   543  * @param bool $is_external
   537  * @param bool $is_external
   544  * @param string $host
   538  * @param string $host
   545  * @return bool
   539  * @return bool
   546  */
   540  */
   547 function ms_allowed_http_request_hosts( $is_external, $host ) {
   541 function ms_allowed_http_request_hosts( $is_external, $host ) {
   548 	global $wpdb, $current_site;
   542 	global $wpdb;
   549 	static $queried = array();
   543 	static $queried = array();
   550 	if ( $is_external )
   544 	if ( $is_external )
   551 		return $is_external;
   545 		return $is_external;
   552 	if ( $host === $current_site->domain )
   546 	if ( $host === get_current_site()->domain )
   553 		return true;
   547 		return true;
   554 	if ( isset( $queried[ $host ] ) )
   548 	if ( isset( $queried[ $host ] ) )
   555 		return $queried[ $host ];
   549 		return $queried[ $host ];
   556 	$queried[ $host ] = (bool) $wpdb->get_var( $wpdb->prepare( "SELECT domain FROM $wpdb->blogs WHERE domain = %s LIMIT 1", $host ) );
   550 	$queried[ $host ] = (bool) $wpdb->get_var( $wpdb->prepare( "SELECT domain FROM $wpdb->blogs WHERE domain = %s LIMIT 1", $host ) );
   557 	return $queried[ $host ];
   551 	return $queried[ $host ];