wp/wp-includes/class-http.php
changeset 9 177826044cd9
parent 7 cf61fcea0001
child 16 a86126ab1dd4
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
    26  * @since 2.7.0
    26  * @since 2.7.0
    27  */
    27  */
    28 class WP_Http {
    28 class WP_Http {
    29 
    29 
    30 	// Aliases for HTTP response codes.
    30 	// Aliases for HTTP response codes.
    31 	const HTTP_CONTINUE                   = 100;
    31 	const HTTP_CONTINUE       = 100;
    32 	const SWITCHING_PROTOCOLS             = 101;
    32 	const SWITCHING_PROTOCOLS = 101;
    33 	const PROCESSING                      = 102;
    33 	const PROCESSING          = 102;
    34 
    34 	const EARLY_HINTS         = 103;
    35 	const OK                              = 200;
    35 
    36 	const CREATED                         = 201;
    36 	const OK                            = 200;
    37 	const ACCEPTED                        = 202;
    37 	const CREATED                       = 201;
    38 	const NON_AUTHORITATIVE_INFORMATION   = 203;
    38 	const ACCEPTED                      = 202;
    39 	const NO_CONTENT                      = 204;
    39 	const NON_AUTHORITATIVE_INFORMATION = 203;
    40 	const RESET_CONTENT                   = 205;
    40 	const NO_CONTENT                    = 204;
    41 	const PARTIAL_CONTENT                 = 206;
    41 	const RESET_CONTENT                 = 205;
    42 	const MULTI_STATUS                    = 207;
    42 	const PARTIAL_CONTENT               = 206;
    43 	const IM_USED                         = 226;
    43 	const MULTI_STATUS                  = 207;
    44 
    44 	const IM_USED                       = 226;
    45 	const MULTIPLE_CHOICES                = 300;
    45 
    46 	const MOVED_PERMANENTLY               = 301;
    46 	const MULTIPLE_CHOICES   = 300;
    47 	const FOUND                           = 302;
    47 	const MOVED_PERMANENTLY  = 301;
    48 	const SEE_OTHER                       = 303;
    48 	const FOUND              = 302;
    49 	const NOT_MODIFIED                    = 304;
    49 	const SEE_OTHER          = 303;
    50 	const USE_PROXY                       = 305;
    50 	const NOT_MODIFIED       = 304;
    51 	const RESERVED                        = 306;
    51 	const USE_PROXY          = 305;
    52 	const TEMPORARY_REDIRECT              = 307;
    52 	const RESERVED           = 306;
    53 	const PERMANENT_REDIRECT              = 308;
    53 	const TEMPORARY_REDIRECT = 307;
       
    54 	const PERMANENT_REDIRECT = 308;
    54 
    55 
    55 	const BAD_REQUEST                     = 400;
    56 	const BAD_REQUEST                     = 400;
    56 	const UNAUTHORIZED                    = 401;
    57 	const UNAUTHORIZED                    = 401;
    57 	const PAYMENT_REQUIRED                = 402;
    58 	const PAYMENT_REQUIRED                = 402;
    58 	const FORBIDDEN                       = 403;
    59 	const FORBIDDEN                       = 403;
   102 	 *
   103 	 *
   103 	 * @param string       $url  The request URL.
   104 	 * @param string       $url  The request URL.
   104 	 * @param string|array $args {
   105 	 * @param string|array $args {
   105 	 *     Optional. Array or string of HTTP request arguments.
   106 	 *     Optional. Array or string of HTTP request arguments.
   106 	 *
   107 	 *
   107 	 *     @type string       $method              Request method. Accepts 'GET', 'POST', 'HEAD', or 'PUT'.
   108 	 *     @type string       $method              Request method. Accepts 'GET', 'POST', 'HEAD', 'PUT', 'DELETE',
       
   109 	 *                                             'TRACE', 'OPTIONS', or 'PATCH'.
   108 	 *                                             Some transports technically allow others, but should not be
   110 	 *                                             Some transports technically allow others, but should not be
   109 	 *                                             assumed. Default 'GET'.
   111 	 *                                             assumed. Default 'GET'.
   110 	 *     @type int          $timeout             How long the connection should stay open in seconds. Default 5.
   112 	 *     @type int          $timeout             How long the connection should stay open in seconds. Default 5.
   111 	 *     @type int          $redirection         Number of allowed redirects. Not supported by all transports
   113 	 *     @type int          $redirection         Number of allowed redirects. Not supported by all transports
   112 	 *                                             Default 5.
   114 	 *                                             Default 5.
   144 	 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'.
   146 	 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'.
   145 	 *                        A WP_Error instance upon error.
   147 	 *                        A WP_Error instance upon error.
   146 	 */
   148 	 */
   147 	public function request( $url, $args = array() ) {
   149 	public function request( $url, $args = array() ) {
   148 		$defaults = array(
   150 		$defaults = array(
   149 			'method' => 'GET',
   151 			'method'              => 'GET',
   150 			/**
   152 			/**
   151 			 * Filters the timeout value for an HTTP request.
   153 			 * Filters the timeout value for an HTTP request.
   152 			 *
   154 			 *
   153 			 * @since 2.7.0
   155 			 * @since 2.7.0
   154 			 *
   156 			 * @since 5.1.0 The `$url` parameter was added.
   155 			 * @param int $timeout_value Time in seconds until a request times out.
   157 			 *
   156 			 *                           Default 5.
   158 			 * @param int    $timeout_value Time in seconds until a request times out. Default 5.
       
   159 			 * @param string $url           The request URL.
   157 			 */
   160 			 */
   158 			'timeout' => apply_filters( 'http_request_timeout', 5 ),
   161 			'timeout'             => apply_filters( 'http_request_timeout', 5, $url ),
   159 			/**
   162 			/**
   160 			 * Filters the number of redirects allowed during an HTTP request.
   163 			 * Filters the number of redirects allowed during an HTTP request.
   161 			 *
   164 			 *
   162 			 * @since 2.7.0
   165 			 * @since 2.7.0
   163 			 *
   166 			 * @since 5.1.0 The `$url` parameter was added.
   164 			 * @param int $redirect_count Number of redirects allowed. Default 5.
   167 			 *
       
   168 			 * @param int    $redirect_count Number of redirects allowed. Default 5.
       
   169 			 * @param string $url            The request URL.
   165 			 */
   170 			 */
   166 			'redirection' => apply_filters( 'http_request_redirection_count', 5 ),
   171 			'redirection'         => apply_filters( 'http_request_redirection_count', 5, $url ),
   167 			/**
   172 			/**
   168 			 * Filters the version of the HTTP protocol used in a request.
   173 			 * Filters the version of the HTTP protocol used in a request.
   169 			 *
   174 			 *
   170 			 * @since 2.7.0
   175 			 * @since 2.7.0
   171 			 *
   176 			 * @since 5.1.0 The `$url` parameter was added.
   172 			 * @param string $version Version of HTTP used. Accepts '1.0' and '1.1'.
   177 			 *
   173 			 *                        Default '1.0'.
   178 			 * @param string $version Version of HTTP used. Accepts '1.0' and '1.1'. Default '1.0'.
       
   179 			 * @param string $url     The request URL.
   174 			 */
   180 			 */
   175 			'httpversion' => apply_filters( 'http_request_version', '1.0' ),
   181 			'httpversion'         => apply_filters( 'http_request_version', '1.0', $url ),
   176 			/**
   182 			/**
   177 			 * Filters the user agent value sent with an HTTP request.
   183 			 * Filters the user agent value sent with an HTTP request.
   178 			 *
   184 			 *
   179 			 * @since 2.7.0
   185 			 * @since 2.7.0
       
   186 			 * @since 5.1.0 The `$url` parameter was added.
   180 			 *
   187 			 *
   181 			 * @param string $user_agent WordPress user agent string.
   188 			 * @param string $user_agent WordPress user agent string.
       
   189 			 * @param string $url        The request URL.
   182 			 */
   190 			 */
   183 			'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ) ),
   191 			'user-agent'          => apply_filters( 'http_headers_useragent', 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ), $url ),
   184 			/**
   192 			/**
   185 			 * Filters whether to pass URLs through wp_http_validate_url() in an HTTP request.
   193 			 * Filters whether to pass URLs through wp_http_validate_url() in an HTTP request.
   186 			 *
   194 			 *
   187 			 * @since 3.6.0
   195 			 * @since 3.6.0
   188 			 *
   196 			 * @since 5.1.0 The `$url` parameter was added.
   189 			 * @param bool $pass_url Whether to pass URLs through wp_http_validate_url().
   197 			 *
   190 			 *                       Default false.
   198 			 * @param bool   $pass_url Whether to pass URLs through wp_http_validate_url(). Default false.
       
   199 			 * @param string $url      The request URL.
   191 			 */
   200 			 */
   192 			'reject_unsafe_urls' => apply_filters( 'http_request_reject_unsafe_urls', false ),
   201 			'reject_unsafe_urls'  => apply_filters( 'http_request_reject_unsafe_urls', false, $url ),
   193 			'blocking' => true,
   202 			'blocking'            => true,
   194 			'headers' => array(),
   203 			'headers'             => array(),
   195 			'cookies' => array(),
   204 			'cookies'             => array(),
   196 			'body' => null,
   205 			'body'                => null,
   197 			'compress' => false,
   206 			'compress'            => false,
   198 			'decompress' => true,
   207 			'decompress'          => true,
   199 			'sslverify' => true,
   208 			'sslverify'           => true,
   200 			'sslcertificates' => ABSPATH . WPINC . '/certificates/ca-bundle.crt',
   209 			'sslcertificates'     => ABSPATH . WPINC . '/certificates/ca-bundle.crt',
   201 			'stream' => false,
   210 			'stream'              => false,
   202 			'filename' => null,
   211 			'filename'            => null,
   203 			'limit_response_size' => null,
   212 			'limit_response_size' => null,
   204 		);
   213 		);
   205 
   214 
   206 		// Pre-parse for the HEAD checks.
   215 		// Pre-parse for the HEAD checks.
   207 		$args = wp_parse_args( $args );
   216 		$args = wp_parse_args( $args );
   208 
   217 
   209 		// By default, Head requests do not cause redirections.
   218 		// By default, Head requests do not cause redirections.
   210 		if ( isset($args['method']) && 'HEAD' == $args['method'] )
   219 		if ( isset( $args['method'] ) && 'HEAD' == $args['method'] ) {
   211 			$defaults['redirection'] = 0;
   220 			$defaults['redirection'] = 0;
       
   221 		}
   212 
   222 
   213 		$r = wp_parse_args( $args, $defaults );
   223 		$r = wp_parse_args( $args, $defaults );
   214 		/**
   224 		/**
   215 		 * Filters the arguments used in an HTTP request.
   225 		 * Filters the arguments used in an HTTP request.
   216 		 *
   226 		 *
   220 		 * @param string $url The request URL.
   230 		 * @param string $url The request URL.
   221 		 */
   231 		 */
   222 		$r = apply_filters( 'http_request_args', $r, $url );
   232 		$r = apply_filters( 'http_request_args', $r, $url );
   223 
   233 
   224 		// The transports decrement this, store a copy of the original value for loop purposes.
   234 		// The transports decrement this, store a copy of the original value for loop purposes.
   225 		if ( ! isset( $r['_redirection'] ) )
   235 		if ( ! isset( $r['_redirection'] ) ) {
   226 			$r['_redirection'] = $r['redirection'];
   236 			$r['_redirection'] = $r['redirection'];
       
   237 		}
   227 
   238 
   228 		/**
   239 		/**
   229 		 * Filters whether to preempt an HTTP request's return value.
   240 		 * Filters whether to preempt an HTTP request's return value.
   230 		 *
   241 		 *
   231 		 * Returning a non-false value from the filter will short-circuit the HTTP request and return
   242 		 * Returning a non-false value from the filter will short-circuit the HTTP request and return
   243 		 * @param array               $r        HTTP request arguments.
   254 		 * @param array               $r        HTTP request arguments.
   244 		 * @param string              $url      The request URL.
   255 		 * @param string              $url      The request URL.
   245 		 */
   256 		 */
   246 		$pre = apply_filters( 'pre_http_request', false, $r, $url );
   257 		$pre = apply_filters( 'pre_http_request', false, $r, $url );
   247 
   258 
   248 		if ( false !== $pre )
   259 		if ( false !== $pre ) {
   249 			return $pre;
   260 			return $pre;
       
   261 		}
   250 
   262 
   251 		if ( function_exists( 'wp_kses_bad_protocol' ) ) {
   263 		if ( function_exists( 'wp_kses_bad_protocol' ) ) {
   252 			if ( $r['reject_unsafe_urls'] ) {
   264 			if ( $r['reject_unsafe_urls'] ) {
   253 				$url = wp_http_validate_url( $url );
   265 				$url = wp_http_validate_url( $url );
   254 			}
   266 			}
   258 		}
   270 		}
   259 
   271 
   260 		$arrURL = @parse_url( $url );
   272 		$arrURL = @parse_url( $url );
   261 
   273 
   262 		if ( empty( $url ) || empty( $arrURL['scheme'] ) ) {
   274 		if ( empty( $url ) || empty( $arrURL['scheme'] ) ) {
   263 			return new WP_Error('http_request_failed', __('A valid URL was not provided.'));
   275 			return new WP_Error( 'http_request_failed', __( 'A valid URL was not provided.' ) );
   264 		}
   276 		}
   265 
   277 
   266 		if ( $this->block_request( $url ) ) {
   278 		if ( $this->block_request( $url ) ) {
   267 			return new WP_Error( 'http_request_failed', __( 'User has blocked requests through HTTP.' ) );
   279 			return new WP_Error( 'http_request_failed', __( 'User has blocked requests through HTTP.' ) );
   268 		}
   280 		}
   286 		}
   298 		}
   287 
   299 
   288 		// WP allows passing in headers as a string, weirdly.
   300 		// WP allows passing in headers as a string, weirdly.
   289 		if ( ! is_array( $r['headers'] ) ) {
   301 		if ( ! is_array( $r['headers'] ) ) {
   290 			$processedHeaders = WP_Http::processHeaders( $r['headers'] );
   302 			$processedHeaders = WP_Http::processHeaders( $r['headers'] );
   291 			$r['headers'] = $processedHeaders['headers'];
   303 			$r['headers']     = $processedHeaders['headers'];
   292 		}
   304 		}
   293 
   305 
   294 		// Setup arguments
   306 		// Setup arguments
   295 		$headers = $r['headers'];
   307 		$headers = $r['headers'];
   296 		$data = $r['body'];
   308 		$data    = $r['body'];
   297 		$type = $r['method'];
   309 		$type    = $r['method'];
   298 		$options = array(
   310 		$options = array(
   299 			'timeout' => $r['timeout'],
   311 			'timeout'   => $r['timeout'],
   300 			'useragent' => $r['user-agent'],
   312 			'useragent' => $r['user-agent'],
   301 			'blocking' => $r['blocking'],
   313 			'blocking'  => $r['blocking'],
   302 			'hooks' => new WP_HTTP_Requests_Hooks( $url, $r ),
   314 			'hooks'     => new WP_HTTP_Requests_Hooks( $url, $r ),
   303 		);
   315 		);
   304 
   316 
   305 		// Ensure redirects follow browser behaviour.
   317 		// Ensure redirects follow browser behaviour.
   306 		$options['hooks']->register( 'requests.before_redirect', array( get_class(), 'browser_redirect_compatibility' ) );
   318 		$options['hooks']->register( 'requests.before_redirect', array( get_class(), 'browser_redirect_compatibility' ) );
   307 
   319 
   329 			$options['cookies'] = WP_Http::normalize_cookies( $r['cookies'] );
   341 			$options['cookies'] = WP_Http::normalize_cookies( $r['cookies'] );
   330 		}
   342 		}
   331 
   343 
   332 		// SSL certificate handling
   344 		// SSL certificate handling
   333 		if ( ! $r['sslverify'] ) {
   345 		if ( ! $r['sslverify'] ) {
   334 			$options['verify'] = false;
   346 			$options['verify']     = false;
   335 			$options['verifyname'] = false;
   347 			$options['verifyname'] = false;
   336 		} else {
   348 		} else {
   337 			$options['verify'] = $r['sslcertificates'];
   349 			$options['verify'] = $r['sslcertificates'];
   338 		}
   350 		}
   339 
   351 
   344 
   356 
   345 		/**
   357 		/**
   346 		 * Filters whether SSL should be verified for non-local requests.
   358 		 * Filters whether SSL should be verified for non-local requests.
   347 		 *
   359 		 *
   348 		 * @since 2.8.0
   360 		 * @since 2.8.0
   349 		 *
   361 		 * @since 5.1.0 The `$url` parameter was added.
   350 		 * @param bool $ssl_verify Whether to verify the SSL connection. Default true.
   362 		 *
       
   363 		 * @param bool   $ssl_verify Whether to verify the SSL connection. Default true.
       
   364 		 * @param string $url        The request URL.
   351 		 */
   365 		 */
   352 		$options['verify'] = apply_filters( 'https_ssl_verify', $options['verify'] );
   366 		$options['verify'] = apply_filters( 'https_ssl_verify', $options['verify'], $url );
   353 
   367 
   354 		// Check for proxies.
   368 		// Check for proxies.
   355 		$proxy = new WP_HTTP_Proxy();
   369 		$proxy = new WP_HTTP_Proxy();
   356 		if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {
   370 		if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {
   357 			$options['proxy'] = new Requests_Proxy_HTTP( $proxy->host() . ':' . $proxy->port() );
   371 			$options['proxy'] = new Requests_Proxy_HTTP( $proxy->host() . ':' . $proxy->port() );
   358 
   372 
   359 			if ( $proxy->use_authentication() ) {
   373 			if ( $proxy->use_authentication() ) {
   360 				$options['proxy']->use_authentication = true;
   374 				$options['proxy']->use_authentication = true;
   361 				$options['proxy']->user = $proxy->username();
   375 				$options['proxy']->user               = $proxy->username();
   362 				$options['proxy']->pass = $proxy->password();
   376 				$options['proxy']->pass               = $proxy->password();
   363 			}
   377 			}
   364 		}
   378 		}
   365 
   379 
   366 		// Avoid issues where mbstring.func_overload is enabled
   380 		// Avoid issues where mbstring.func_overload is enabled
   367 		mbstring_binary_safe_encoding();
   381 		mbstring_binary_safe_encoding();
   369 		try {
   383 		try {
   370 			$requests_response = Requests::request( $url, $headers, $data, $type, $options );
   384 			$requests_response = Requests::request( $url, $headers, $data, $type, $options );
   371 
   385 
   372 			// Convert the response into an array
   386 			// Convert the response into an array
   373 			$http_response = new WP_HTTP_Requests_Response( $requests_response, $r['filename'] );
   387 			$http_response = new WP_HTTP_Requests_Response( $requests_response, $r['filename'] );
   374 			$response = $http_response->to_array();
   388 			$response      = $http_response->to_array();
   375 
   389 
   376 			// Add the original object to the array.
   390 			// Add the original object to the array.
   377 			$response['http_response'] = $http_response;
   391 			$response['http_response'] = $http_response;
   378 		}
   392 		} catch ( Requests_Exception $e ) {
   379 		catch ( Requests_Exception $e ) {
       
   380 			$response = new WP_Error( 'http_request_failed', $e->getMessage() );
   393 			$response = new WP_Error( 'http_request_failed', $e->getMessage() );
   381 		}
   394 		}
   382 
   395 
   383 		reset_mbstring_encoding();
   396 		reset_mbstring_encoding();
   384 
   397 
   398 			return $response;
   411 			return $response;
   399 		}
   412 		}
   400 
   413 
   401 		if ( ! $r['blocking'] ) {
   414 		if ( ! $r['blocking'] ) {
   402 			return array(
   415 			return array(
   403 				'headers' => array(),
   416 				'headers'       => array(),
   404 				'body' => '',
   417 				'body'          => '',
   405 				'response' => array(
   418 				'response'      => array(
   406 					'code' => false,
   419 					'code'    => false,
   407 					'message' => false,
   420 					'message' => false,
   408 				),
   421 				),
   409 				'cookies' => array(),
   422 				'cookies'       => array(),
   410 				'http_response' => null,
   423 				'http_response' => null,
   411 			);
   424 			);
   412 		}
   425 		}
   413 
   426 
   414 		/**
   427 		/**
   425 
   438 
   426 	/**
   439 	/**
   427 	 * Normalizes cookies for using in Requests.
   440 	 * Normalizes cookies for using in Requests.
   428 	 *
   441 	 *
   429 	 * @since 4.6.0
   442 	 * @since 4.6.0
   430 	 * @static
   443 	 *
   431 	 *
   444 	 * @param array $cookies Array of cookies to send with the request.
   432 	 * @param array $cookies List of cookies to send with the request.
       
   433 	 * @return Requests_Cookie_Jar Cookie holder object.
   445 	 * @return Requests_Cookie_Jar Cookie holder object.
   434 	 */
   446 	 */
   435 	public static function normalize_cookies( $cookies ) {
   447 	public static function normalize_cookies( $cookies ) {
   436 		$cookie_jar = new Requests_Cookie_Jar();
   448 		$cookie_jar = new Requests_Cookie_Jar();
   437 
   449 
   438 		foreach ( $cookies as $name => $value ) {
   450 		foreach ( $cookies as $name => $value ) {
   439 			if ( $value instanceof WP_Http_Cookie ) {
   451 			if ( $value instanceof WP_Http_Cookie ) {
   440 				$cookie_jar[ $value->name ] = new Requests_Cookie( $value->name, $value->value, $value->get_attributes() );
   452 				$cookie_jar[ $value->name ] = new Requests_Cookie( $value->name, $value->value, $value->get_attributes(), array( 'host-only' => $value->host_only ) );
   441 			} elseif ( is_scalar( $value ) ) {
   453 			} elseif ( is_scalar( $value ) ) {
   442 				$cookie_jar[ $name ] = new Requests_Cookie( $name, $value );
   454 				$cookie_jar[ $name ] = new Requests_Cookie( $name, $value );
   443 			}
   455 			}
   444 		}
   456 		}
   445 
   457 
   452 	 * Changes 302 redirects from POST to GET to match browser handling. Per
   464 	 * Changes 302 redirects from POST to GET to match browser handling. Per
   453 	 * RFC 7231, user agents can deviate from the strict reading of the
   465 	 * RFC 7231, user agents can deviate from the strict reading of the
   454 	 * specification for compatibility purposes.
   466 	 * specification for compatibility purposes.
   455 	 *
   467 	 *
   456 	 * @since 4.6.0
   468 	 * @since 4.6.0
   457 	 * @static
       
   458 	 *
   469 	 *
   459 	 * @param string            $location URL to redirect to.
   470 	 * @param string            $location URL to redirect to.
   460 	 * @param array             $headers  Headers for the redirect.
   471 	 * @param array             $headers  Headers for the redirect.
   461 	 * @param string|array      $data     Body to send with the request.
   472 	 * @param string|array      $data     Body to send with the request.
   462 	 * @param array             $options  Redirect request options.
   473 	 * @param array             $options  Redirect request options.
   477 	 * @throws Requests_Exception On unsuccessful URL validation
   488 	 * @throws Requests_Exception On unsuccessful URL validation
   478 	 * @param string $location URL to redirect to.
   489 	 * @param string $location URL to redirect to.
   479 	 */
   490 	 */
   480 	public static function validate_redirects( $location ) {
   491 	public static function validate_redirects( $location ) {
   481 		if ( ! wp_http_validate_url( $location ) ) {
   492 		if ( ! wp_http_validate_url( $location ) ) {
   482 			throw new Requests_Exception( __('A valid URL was not provided.'), 'wp_http.redirect_failed_validation' );
   493 			throw new Requests_Exception( __( 'A valid URL was not provided.' ), 'wp_http.redirect_failed_validation' );
   483 		}
   494 		}
   484 	}
   495 	}
   485 
   496 
   486 	/**
   497 	/**
   487 	 * Tests which transports are capable of supporting the request.
   498 	 * Tests which transports are capable of supporting the request.
   514 				$transport = ucfirst( $transport );
   525 				$transport = ucfirst( $transport );
   515 			}
   526 			}
   516 			$class = 'WP_Http_' . $transport;
   527 			$class = 'WP_Http_' . $transport;
   517 
   528 
   518 			// Check to see if this transport is a possibility, calls the transport statically.
   529 			// Check to see if this transport is a possibility, calls the transport statically.
   519 			if ( !call_user_func( array( $class, 'test' ), $args, $url ) )
   530 			if ( ! call_user_func( array( $class, 'test' ), $args, $url ) ) {
   520 				continue;
   531 				continue;
       
   532 			}
   521 
   533 
   522 			return $class;
   534 			return $class;
   523 		}
   535 		}
   524 
   536 
   525 		return false;
   537 		return false;
   532 	 * Also caches the transport instance to be used later.
   544 	 * Also caches the transport instance to be used later.
   533 	 *
   545 	 *
   534 	 * The order for requests is cURL, and then PHP Streams.
   546 	 * The order for requests is cURL, and then PHP Streams.
   535 	 *
   547 	 *
   536 	 * @since 3.2.0
   548 	 * @since 3.2.0
   537 	 *
   549 	 * @deprecated 5.1.0 Use WP_Http::request()
   538 	 * @static
   550 	 * @see WP_Http::request()
   539 	 *
   551 	 *
   540 	 * @param string $url URL to Request
   552 	 * @param string $url URL to Request
   541 	 * @param array $args Request arguments
   553 	 * @param array $args Request arguments
   542 	 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error
   554 	 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error
   543 	 */
   555 	 */
   544 	private function _dispatch_request( $url, $args ) {
   556 	private function _dispatch_request( $url, $args ) {
   545 		static $transports = array();
   557 		static $transports = array();
   546 
   558 
   547 		$class = $this->_get_first_available_transport( $args, $url );
   559 		$class = $this->_get_first_available_transport( $args, $url );
   548 		if ( !$class )
   560 		if ( ! $class ) {
   549 			return new WP_Error( 'http_failure', __( 'There are no HTTP transports available which can complete the requested request.' ) );
   561 			return new WP_Error( 'http_failure', __( 'There are no HTTP transports available which can complete the requested request.' ) );
       
   562 		}
   550 
   563 
   551 		// Transport claims to support request, instantiate it and give it a whirl.
   564 		// Transport claims to support request, instantiate it and give it a whirl.
   552 		if ( empty( $transports[$class] ) )
   565 		if ( empty( $transports[ $class ] ) ) {
   553 			$transports[$class] = new $class;
   566 			$transports[ $class ] = new $class;
   554 
   567 		}
   555 		$response = $transports[$class]->request( $url, $args );
   568 
       
   569 		$response = $transports[ $class ]->request( $url, $args );
   556 
   570 
   557 		/** This action is documented in wp-includes/class-http.php */
   571 		/** This action is documented in wp-includes/class-http.php */
   558 		do_action( 'http_api_debug', $response, 'response', $class, $args, $url );
   572 		do_action( 'http_api_debug', $response, 'response', $class, $args, $url );
   559 
   573 
   560 		if ( is_wp_error( $response ) )
   574 		if ( is_wp_error( $response ) ) {
   561 			return $response;
   575 			return $response;
   562 
   576 		}
   563 		/**
   577 
   564 		 * Filters the HTTP API response immediately before the response is returned.
   578 		/** This filter is documented in wp-includes/class-http.php */
   565 		 *
       
   566 		 * @since 2.9.0
       
   567 		 *
       
   568 		 * @param array  $response HTTP response.
       
   569 		 * @param array  $args     HTTP request arguments.
       
   570 		 * @param string $url      The request URL.
       
   571 		 */
       
   572 		return apply_filters( 'http_response', $response, $args, $url );
   579 		return apply_filters( 'http_response', $response, $args, $url );
   573 	}
   580 	}
   574 
   581 
   575 	/**
   582 	/**
   576 	 * Uses the POST HTTP method.
   583 	 * Uses the POST HTTP method.
   581 	 *
   588 	 *
   582 	 * @param string       $url  The request URL.
   589 	 * @param string       $url  The request URL.
   583 	 * @param string|array $args Optional. Override the defaults.
   590 	 * @param string|array $args Optional. Override the defaults.
   584 	 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error
   591 	 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error
   585 	 */
   592 	 */
   586 	public function post($url, $args = array()) {
   593 	public function post( $url, $args = array() ) {
   587 		$defaults = array('method' => 'POST');
   594 		$defaults = array( 'method' => 'POST' );
   588 		$r = wp_parse_args( $args, $defaults );
   595 		$r        = wp_parse_args( $args, $defaults );
   589 		return $this->request($url, $r);
   596 		return $this->request( $url, $r );
   590 	}
   597 	}
   591 
   598 
   592 	/**
   599 	/**
   593 	 * Uses the GET HTTP method.
   600 	 * Uses the GET HTTP method.
   594 	 *
   601 	 *
   598 	 *
   605 	 *
   599 	 * @param string $url The request URL.
   606 	 * @param string $url The request URL.
   600 	 * @param string|array $args Optional. Override the defaults.
   607 	 * @param string|array $args Optional. Override the defaults.
   601 	 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error
   608 	 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error
   602 	 */
   609 	 */
   603 	public function get($url, $args = array()) {
   610 	public function get( $url, $args = array() ) {
   604 		$defaults = array('method' => 'GET');
   611 		$defaults = array( 'method' => 'GET' );
   605 		$r = wp_parse_args( $args, $defaults );
   612 		$r        = wp_parse_args( $args, $defaults );
   606 		return $this->request($url, $r);
   613 		return $this->request( $url, $r );
   607 	}
   614 	}
   608 
   615 
   609 	/**
   616 	/**
   610 	 * Uses the HEAD HTTP method.
   617 	 * Uses the HEAD HTTP method.
   611 	 *
   618 	 *
   615 	 *
   622 	 *
   616 	 * @param string $url The request URL.
   623 	 * @param string $url The request URL.
   617 	 * @param string|array $args Optional. Override the defaults.
   624 	 * @param string|array $args Optional. Override the defaults.
   618 	 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error
   625 	 * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error
   619 	 */
   626 	 */
   620 	public function head($url, $args = array()) {
   627 	public function head( $url, $args = array() ) {
   621 		$defaults = array('method' => 'HEAD');
   628 		$defaults = array( 'method' => 'HEAD' );
   622 		$r = wp_parse_args( $args, $defaults );
   629 		$r        = wp_parse_args( $args, $defaults );
   623 		return $this->request($url, $r);
   630 		return $this->request( $url, $r );
   624 	}
   631 	}
   625 
   632 
   626 	/**
   633 	/**
   627 	 * Parses the responses and splits the parts into headers and body.
   634 	 * Parses the responses and splits the parts into headers and body.
   628 	 *
   635 	 *
   629 	 * @static
       
   630 	 * @since 2.7.0
   636 	 * @since 2.7.0
   631 	 *
   637 	 *
   632 	 * @param string $strResponse The full response string
   638 	 * @param string $strResponse The full response string
   633 	 * @return array Array with 'headers' and 'body' keys.
   639 	 * @return array Array with 'headers' and 'body' keys.
   634 	 */
   640 	 */
   635 	public static function processResponse($strResponse) {
   641 	public static function processResponse( $strResponse ) {
   636 		$res = explode("\r\n\r\n", $strResponse, 2);
   642 		$res = explode( "\r\n\r\n", $strResponse, 2 );
   637 
   643 
   638 		return array('headers' => $res[0], 'body' => isset($res[1]) ? $res[1] : '');
   644 		return array(
       
   645 			'headers' => $res[0],
       
   646 			'body'    => isset( $res[1] ) ? $res[1] : '',
       
   647 		);
   639 	}
   648 	}
   640 
   649 
   641 	/**
   650 	/**
   642 	 * Transform header string into an array.
   651 	 * Transform header string into an array.
   643 	 *
   652 	 *
   644 	 * If an array is given then it is assumed to be raw header data with numeric keys with the
   653 	 * If an array is given then it is assumed to be raw header data with numeric keys with the
   645 	 * headers as the values. No headers must be passed that were already processed.
   654 	 * headers as the values. No headers must be passed that were already processed.
   646 	 *
   655 	 *
   647 	 * @static
       
   648 	 * @since 2.7.0
   656 	 * @since 2.7.0
   649 	 *
   657 	 *
   650 	 * @param string|array $headers
   658 	 * @param string|array $headers
   651 	 * @param string $url The URL that was requested
   659 	 * @param string $url The URL that was requested
   652 	 * @return array Processed string headers. If duplicate headers are encountered,
   660 	 * @return array Processed string headers. If duplicate headers are encountered,
   653 	 * 					Then a numbered array is returned as the value of that header-key.
   661 	 *                  Then a numbered array is returned as the value of that header-key.
   654 	 */
   662 	 */
   655 	public static function processHeaders( $headers, $url = '' ) {
   663 	public static function processHeaders( $headers, $url = '' ) {
   656 		// Split headers, one per array element.
   664 		// Split headers, one per array element.
   657 		if ( is_string($headers) ) {
   665 		if ( is_string( $headers ) ) {
   658 			// Tolerate line terminator: CRLF = LF (RFC 2616 19.3).
   666 			// Tolerate line terminator: CRLF = LF (RFC 2616 19.3).
   659 			$headers = str_replace("\r\n", "\n", $headers);
   667 			$headers = str_replace( "\r\n", "\n", $headers );
   660 			/*
   668 			/*
   661 			 * Unfold folded header fields. LWS = [CRLF] 1*( SP | HT ) <US-ASCII SP, space (32)>,
   669 			 * Unfold folded header fields. LWS = [CRLF] 1*( SP | HT ) <US-ASCII SP, space (32)>,
   662 			 * <US-ASCII HT, horizontal-tab (9)> (RFC 2616 2.2).
   670 			 * <US-ASCII HT, horizontal-tab (9)> (RFC 2616 2.2).
   663 			 */
   671 			 */
   664 			$headers = preg_replace('/\n[ \t]/', ' ', $headers);
   672 			$headers = preg_replace( '/\n[ \t]/', ' ', $headers );
   665 			// Create the headers array.
   673 			// Create the headers array.
   666 			$headers = explode("\n", $headers);
   674 			$headers = explode( "\n", $headers );
   667 		}
   675 		}
   668 
   676 
   669 		$response = array('code' => 0, 'message' => '');
   677 		$response = array(
       
   678 			'code'    => 0,
       
   679 			'message' => '',
       
   680 		);
   670 
   681 
   671 		/*
   682 		/*
   672 		 * If a redirection has taken place, The headers for each page request may have been passed.
   683 		 * If a redirection has taken place, The headers for each page request may have been passed.
   673 		 * In this case, determine the final HTTP header and parse from there.
   684 		 * In this case, determine the final HTTP header and parse from there.
   674 		 */
   685 		 */
   675 		for ( $i = count($headers)-1; $i >= 0; $i-- ) {
   686 		for ( $i = count( $headers ) - 1; $i >= 0; $i-- ) {
   676 			if ( !empty($headers[$i]) && false === strpos($headers[$i], ':') ) {
   687 			if ( ! empty( $headers[ $i ] ) && false === strpos( $headers[ $i ], ':' ) ) {
   677 				$headers = array_splice($headers, $i);
   688 				$headers = array_splice( $headers, $i );
   678 				break;
   689 				break;
   679 			}
   690 			}
   680 		}
   691 		}
   681 
   692 
   682 		$cookies = array();
   693 		$cookies    = array();
   683 		$newheaders = array();
   694 		$newheaders = array();
   684 		foreach ( (array) $headers as $tempheader ) {
   695 		foreach ( (array) $headers as $tempheader ) {
   685 			if ( empty($tempheader) )
   696 			if ( empty( $tempheader ) ) {
   686 				continue;
   697 				continue;
   687 
   698 			}
   688 			if ( false === strpos($tempheader, ':') ) {
   699 
   689 				$stack = explode(' ', $tempheader, 3);
   700 			if ( false === strpos( $tempheader, ':' ) ) {
       
   701 				$stack   = explode( ' ', $tempheader, 3 );
   690 				$stack[] = '';
   702 				$stack[] = '';
   691 				list( , $response['code'], $response['message']) = $stack;
   703 				list( , $response['code'], $response['message']) = $stack;
   692 				continue;
   704 				continue;
   693 			}
   705 			}
   694 
   706 
   695 			list($key, $value) = explode(':', $tempheader, 2);
   707 			list($key, $value) = explode( ':', $tempheader, 2 );
   696 
   708 
   697 			$key = strtolower( $key );
   709 			$key   = strtolower( $key );
   698 			$value = trim( $value );
   710 			$value = trim( $value );
   699 
   711 
   700 			if ( isset( $newheaders[ $key ] ) ) {
   712 			if ( isset( $newheaders[ $key ] ) ) {
   701 				if ( ! is_array( $newheaders[ $key ] ) )
   713 				if ( ! is_array( $newheaders[ $key ] ) ) {
   702 					$newheaders[$key] = array( $newheaders[ $key ] );
   714 					$newheaders[ $key ] = array( $newheaders[ $key ] );
       
   715 				}
   703 				$newheaders[ $key ][] = $value;
   716 				$newheaders[ $key ][] = $value;
   704 			} else {
   717 			} else {
   705 				$newheaders[ $key ] = $value;
   718 				$newheaders[ $key ] = $value;
   706 			}
   719 			}
   707 			if ( 'set-cookie' == $key )
   720 			if ( 'set-cookie' == $key ) {
   708 				$cookies[] = new WP_Http_Cookie( $value, $url );
   721 				$cookies[] = new WP_Http_Cookie( $value, $url );
       
   722 			}
   709 		}
   723 		}
   710 
   724 
   711 		// Cast the Response Code to an int
   725 		// Cast the Response Code to an int
   712 		$response['code'] = intval( $response['code'] );
   726 		$response['code'] = intval( $response['code'] );
   713 
   727 
   714 		return array('response' => $response, 'headers' => $newheaders, 'cookies' => $cookies);
   728 		return array(
       
   729 			'response' => $response,
       
   730 			'headers'  => $newheaders,
       
   731 			'cookies'  => $cookies,
       
   732 		);
   715 	}
   733 	}
   716 
   734 
   717 	/**
   735 	/**
   718 	 * Takes the arguments for a ::request() and checks for the cookie array.
   736 	 * Takes the arguments for a ::request() and checks for the cookie array.
   719 	 *
   737 	 *
   720 	 * If it's found, then it upgrades any basic name => value pairs to WP_Http_Cookie instances,
   738 	 * If it's found, then it upgrades any basic name => value pairs to WP_Http_Cookie instances,
   721 	 * which are each parsed into strings and added to the Cookie: header (within the arguments array).
   739 	 * which are each parsed into strings and added to the Cookie: header (within the arguments array).
   722 	 * Edits the array by reference.
   740 	 * Edits the array by reference.
   723 	 *
   741 	 *
   724 	 * @since 2.8.0
   742 	 * @since 2.8.0
   725 	 * @static
       
   726 	 *
   743 	 *
   727 	 * @param array $r Full array of args passed into ::request()
   744 	 * @param array $r Full array of args passed into ::request()
   728 	 */
   745 	 */
   729 	public static function buildCookieHeader( &$r ) {
   746 	public static function buildCookieHeader( &$r ) {
   730 		if ( ! empty($r['cookies']) ) {
   747 		if ( ! empty( $r['cookies'] ) ) {
   731 			// Upgrade any name => value cookie pairs to WP_HTTP_Cookie instances.
   748 			// Upgrade any name => value cookie pairs to WP_HTTP_Cookie instances.
   732 			foreach ( $r['cookies'] as $name => $value ) {
   749 			foreach ( $r['cookies'] as $name => $value ) {
   733 				if ( ! is_object( $value ) )
   750 				if ( ! is_object( $value ) ) {
   734 					$r['cookies'][ $name ] = new WP_Http_Cookie( array( 'name' => $name, 'value' => $value ) );
   751 					$r['cookies'][ $name ] = new WP_Http_Cookie(
       
   752 						array(
       
   753 							'name'  => $name,
       
   754 							'value' => $value,
       
   755 						)
       
   756 					);
       
   757 				}
   735 			}
   758 			}
   736 
   759 
   737 			$cookies_header = '';
   760 			$cookies_header = '';
   738 			foreach ( (array) $r['cookies'] as $cookie ) {
   761 			foreach ( (array) $r['cookies'] as $cookie ) {
   739 				$cookies_header .= $cookie->getHeaderValue() . '; ';
   762 				$cookies_header .= $cookie->getHeaderValue() . '; ';
   740 			}
   763 			}
   741 
   764 
   742 			$cookies_header = substr( $cookies_header, 0, -2 );
   765 			$cookies_header         = substr( $cookies_header, 0, -2 );
   743 			$r['headers']['cookie'] = $cookies_header;
   766 			$r['headers']['cookie'] = $cookies_header;
   744 		}
   767 		}
   745 	}
   768 	}
   746 
   769 
   747 	/**
   770 	/**
   750 	 * Based off the HTTP http_encoding_dechunk function.
   773 	 * Based off the HTTP http_encoding_dechunk function.
   751 	 *
   774 	 *
   752 	 * @link https://tools.ietf.org/html/rfc2616#section-19.4.6 Process for chunked decoding.
   775 	 * @link https://tools.ietf.org/html/rfc2616#section-19.4.6 Process for chunked decoding.
   753 	 *
   776 	 *
   754 	 * @since 2.7.0
   777 	 * @since 2.7.0
   755 	 * @static
       
   756 	 *
   778 	 *
   757 	 * @param string $body Body content
   779 	 * @param string $body Body content
   758 	 * @return string Chunked decoded body on success or raw body on failure.
   780 	 * @return string Chunked decoded body on success or raw body on failure.
   759 	 */
   781 	 */
   760 	public static function chunkTransferDecode( $body ) {
   782 	public static function chunkTransferDecode( $body ) {
   761 		// The body is not chunked encoded or is malformed.
   783 		// The body is not chunked encoded or is malformed.
   762 		if ( ! preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', trim( $body ) ) )
   784 		if ( ! preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', trim( $body ) ) ) {
   763 			return $body;
   785 			return $body;
       
   786 		}
   764 
   787 
   765 		$parsed_body = '';
   788 		$parsed_body = '';
   766 
   789 
   767 		// We'll be altering $body, so need a backup in case of error.
   790 		// We'll be altering $body, so need a backup in case of error.
   768 		$body_original = $body;
   791 		$body_original = $body;
   769 
   792 
   770 		while ( true ) {
   793 		while ( true ) {
   771 			$has_chunk = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $body, $match );
   794 			$has_chunk = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $body, $match );
   772 			if ( ! $has_chunk || empty( $match[1] ) )
   795 			if ( ! $has_chunk || empty( $match[1] ) ) {
   773 				return $body_original;
   796 				return $body_original;
   774 
   797 			}
   775 			$length = hexdec( $match[1] );
   798 
       
   799 			$length       = hexdec( $match[1] );
   776 			$chunk_length = strlen( $match[0] );
   800 			$chunk_length = strlen( $match[0] );
   777 
   801 
   778 			// Parse out the chunk of data.
   802 			// Parse out the chunk of data.
   779 			$parsed_body .= substr( $body, $chunk_length, $length );
   803 			$parsed_body .= substr( $body, $chunk_length, $length );
   780 
   804 
   781 			// Remove the chunk from the raw data.
   805 			// Remove the chunk from the raw data.
   782 			$body = substr( $body, $length + $chunk_length );
   806 			$body = substr( $body, $length + $chunk_length );
   783 
   807 
   784 			// End of the document.
   808 			// End of the document.
   785 			if ( '0' === trim( $body ) )
   809 			if ( '0' === trim( $body ) ) {
   786 				return $parsed_body;
   810 				return $parsed_body;
       
   811 			}
   787 		}
   812 		}
   788 	}
   813 	}
   789 
   814 
   790 	/**
   815 	/**
   791 	 * Block requests through the proxy.
   816 	 * Block requests through the proxy.
   807 	 * @staticvar array      $wildcard_regex
   832 	 * @staticvar array      $wildcard_regex
   808 	 *
   833 	 *
   809 	 * @param string $uri URI of url.
   834 	 * @param string $uri URI of url.
   810 	 * @return bool True to block, false to allow.
   835 	 * @return bool True to block, false to allow.
   811 	 */
   836 	 */
   812 	public function block_request($uri) {
   837 	public function block_request( $uri ) {
   813 		// We don't need to block requests, because nothing is blocked.
   838 		// We don't need to block requests, because nothing is blocked.
   814 		if ( ! defined( 'WP_HTTP_BLOCK_EXTERNAL' ) || ! WP_HTTP_BLOCK_EXTERNAL )
   839 		if ( ! defined( 'WP_HTTP_BLOCK_EXTERNAL' ) || ! WP_HTTP_BLOCK_EXTERNAL ) {
   815 			return false;
   840 			return false;
   816 
   841 		}
   817 		$check = parse_url($uri);
   842 
   818 		if ( ! $check )
   843 		$check = parse_url( $uri );
       
   844 		if ( ! $check ) {
   819 			return true;
   845 			return true;
   820 
   846 		}
   821 		$home = parse_url( get_option('siteurl') );
   847 
       
   848 		$home = parse_url( get_option( 'siteurl' ) );
   822 
   849 
   823 		// Don't block requests back to ourselves by default.
   850 		// Don't block requests back to ourselves by default.
   824 		if ( 'localhost' == $check['host'] || ( isset( $home['host'] ) && $home['host'] == $check['host'] ) ) {
   851 		if ( 'localhost' == $check['host'] || ( isset( $home['host'] ) && $home['host'] == $check['host'] ) ) {
   825 			/**
   852 			/**
   826 			 * Filters whether to block local requests through the proxy.
   853 			 * Filters whether to block local requests through the proxy.
   831 			 *                    Default false.
   858 			 *                    Default false.
   832 			 */
   859 			 */
   833 			return apply_filters( 'block_local_requests', false );
   860 			return apply_filters( 'block_local_requests', false );
   834 		}
   861 		}
   835 
   862 
   836 		if ( !defined('WP_ACCESSIBLE_HOSTS') )
   863 		if ( ! defined( 'WP_ACCESSIBLE_HOSTS' ) ) {
   837 			return true;
   864 			return true;
       
   865 		}
   838 
   866 
   839 		static $accessible_hosts = null;
   867 		static $accessible_hosts = null;
   840 		static $wildcard_regex = array();
   868 		static $wildcard_regex   = array();
   841 		if ( null === $accessible_hosts ) {
   869 		if ( null === $accessible_hosts ) {
   842 			$accessible_hosts = preg_split('|,\s*|', WP_ACCESSIBLE_HOSTS);
   870 			$accessible_hosts = preg_split( '|,\s*|', WP_ACCESSIBLE_HOSTS );
   843 
   871 
   844 			if ( false !== strpos(WP_ACCESSIBLE_HOSTS, '*') ) {
   872 			if ( false !== strpos( WP_ACCESSIBLE_HOSTS, '*' ) ) {
   845 				$wildcard_regex = array();
   873 				$wildcard_regex = array();
   846 				foreach ( $accessible_hosts as $host )
   874 				foreach ( $accessible_hosts as $host ) {
   847 					$wildcard_regex[] = str_replace( '\*', '.+', preg_quote( $host, '/' ) );
   875 					$wildcard_regex[] = str_replace( '\*', '.+', preg_quote( $host, '/' ) );
   848 				$wildcard_regex = '/^(' . implode('|', $wildcard_regex) . ')$/i';
   876 				}
   849 			}
   877 				$wildcard_regex = '/^(' . implode( '|', $wildcard_regex ) . ')$/i';
   850 		}
   878 			}
   851 
   879 		}
   852 		if ( !empty($wildcard_regex) )
   880 
   853 			return !preg_match($wildcard_regex, $check['host']);
   881 		if ( ! empty( $wildcard_regex ) ) {
   854 		else
   882 			return ! preg_match( $wildcard_regex, $check['host'] );
   855 			return !in_array( $check['host'], $accessible_hosts ); //Inverse logic, If it's in the array, then we can't access it.
   883 		} else {
       
   884 			return ! in_array( $check['host'], $accessible_hosts ); //Inverse logic, If it's in the array, then we can't access it.
       
   885 		}
   856 
   886 
   857 	}
   887 	}
   858 
   888 
   859 	/**
   889 	/**
   860 	 * Used as a wrapper for PHP's parse_url() function that handles edgecases in < PHP 5.4.7.
   890 	 * Used as a wrapper for PHP's parse_url() function that handles edgecases in < PHP 5.4.7.
   876 	 *
   906 	 *
   877 	 * If an Absolute URL is provided, no processing of that URL is done.
   907 	 * If an Absolute URL is provided, no processing of that URL is done.
   878 	 *
   908 	 *
   879 	 * @since 3.4.0
   909 	 * @since 3.4.0
   880 	 *
   910 	 *
   881 	 * @static
       
   882 	 *
       
   883 	 * @param string $maybe_relative_path The URL which might be relative
   911 	 * @param string $maybe_relative_path The URL which might be relative
   884 	 * @param string $url                 The URL which $maybe_relative_path is relative to
   912 	 * @param string $url                 The URL which $maybe_relative_path is relative to
   885 	 * @return string An Absolute URL, in a failure condition where the URL cannot be parsed, the relative URL will be returned.
   913 	 * @return string An Absolute URL, in a failure condition where the URL cannot be parsed, the relative URL will be returned.
   886 	 */
   914 	 */
   887 	public static function make_absolute_url( $maybe_relative_path, $url ) {
   915 	public static function make_absolute_url( $maybe_relative_path, $url ) {
   888 		if ( empty( $url ) )
   916 		if ( empty( $url ) ) {
   889 			return $maybe_relative_path;
   917 			return $maybe_relative_path;
       
   918 		}
   890 
   919 
   891 		if ( ! $url_parts = wp_parse_url( $url ) ) {
   920 		if ( ! $url_parts = wp_parse_url( $url ) ) {
   892 			return $maybe_relative_path;
   921 			return $maybe_relative_path;
   893 		}
   922 		}
   894 
   923 
   904 		$absolute_path = $url_parts['scheme'] . '://';
   933 		$absolute_path = $url_parts['scheme'] . '://';
   905 
   934 
   906 		// Schemeless URL's will make it this far, so we check for a host in the relative url and convert it to a protocol-url
   935 		// Schemeless URL's will make it this far, so we check for a host in the relative url and convert it to a protocol-url
   907 		if ( isset( $relative_url_parts['host'] ) ) {
   936 		if ( isset( $relative_url_parts['host'] ) ) {
   908 			$absolute_path .= $relative_url_parts['host'];
   937 			$absolute_path .= $relative_url_parts['host'];
   909 			if ( isset( $relative_url_parts['port'] ) )
   938 			if ( isset( $relative_url_parts['port'] ) ) {
   910 				$absolute_path .= ':' . $relative_url_parts['port'];
   939 				$absolute_path .= ':' . $relative_url_parts['port'];
       
   940 			}
   911 		} else {
   941 		} else {
   912 			$absolute_path .= $url_parts['host'];
   942 			$absolute_path .= $url_parts['host'];
   913 			if ( isset( $url_parts['port'] ) )
   943 			if ( isset( $url_parts['port'] ) ) {
   914 				$absolute_path .= ':' . $url_parts['port'];
   944 				$absolute_path .= ':' . $url_parts['port'];
       
   945 			}
   915 		}
   946 		}
   916 
   947 
   917 		// Start off with the Absolute URL path.
   948 		// Start off with the Absolute URL path.
   918 		$path = ! empty( $url_parts['path'] ) ? $url_parts['path'] : '/';
   949 		$path = ! empty( $url_parts['path'] ) ? $url_parts['path'] : '/';
   919 
   950 
   920 		// If it's a root-relative path, then great.
   951 		// If it's a root-relative path, then great.
   921 		if ( ! empty( $relative_url_parts['path'] ) && '/' == $relative_url_parts['path'][0] ) {
   952 		if ( ! empty( $relative_url_parts['path'] ) && '/' == $relative_url_parts['path'][0] ) {
   922 			$path = $relative_url_parts['path'];
   953 			$path = $relative_url_parts['path'];
   923 
   954 
   924 		// Else it's a relative path.
   955 			// Else it's a relative path.
   925 		} elseif ( ! empty( $relative_url_parts['path'] ) ) {
   956 		} elseif ( ! empty( $relative_url_parts['path'] ) ) {
   926 			// Strip off any file components from the absolute path.
   957 			// Strip off any file components from the absolute path.
   927 			$path = substr( $path, 0, strrpos( $path, '/' ) + 1 );
   958 			$path = substr( $path, 0, strrpos( $path, '/' ) + 1 );
   928 
   959 
   929 			// Build the new path.
   960 			// Build the new path.
   937 			// Strip any final leading ../ from the path.
   968 			// Strip any final leading ../ from the path.
   938 			$path = preg_replace( '!^/(\.\./)+!', '', $path );
   969 			$path = preg_replace( '!^/(\.\./)+!', '', $path );
   939 		}
   970 		}
   940 
   971 
   941 		// Add the Query string.
   972 		// Add the Query string.
   942 		if ( ! empty( $relative_url_parts['query'] ) )
   973 		if ( ! empty( $relative_url_parts['query'] ) ) {
   943 			$path .= '?' . $relative_url_parts['query'];
   974 			$path .= '?' . $relative_url_parts['query'];
       
   975 		}
   944 
   976 
   945 		return $absolute_path . '/' . ltrim( $path, '/' );
   977 		return $absolute_path . '/' . ltrim( $path, '/' );
   946 	}
   978 	}
   947 
   979 
   948 	/**
   980 	/**
   949 	 * Handles HTTP Redirects and follows them if appropriate.
   981 	 * Handles HTTP Redirects and follows them if appropriate.
   950 	 *
   982 	 *
   951 	 * @since 3.7.0
   983 	 * @since 3.7.0
   952 	 * @static
       
   953 	 *
   984 	 *
   954 	 * @param string $url The URL which was requested.
   985 	 * @param string $url The URL which was requested.
   955 	 * @param array $args The Arguments which were used to make the request.
   986 	 * @param array $args The Arguments which were used to make the request.
   956 	 * @param array $response The Response of the HTTP request.
   987 	 * @param array $response The Response of the HTTP request.
   957 	 * @return false|object False if no redirect is present, a WP_HTTP or WP_Error result otherwise.
   988 	 * @return false|object False if no redirect is present, a WP_HTTP or WP_Error result otherwise.
   958 	 */
   989 	 */
   959 	public static function handle_redirects( $url, $args, $response ) {
   990 	public static function handle_redirects( $url, $args, $response ) {
   960 		// If no redirects are present, or, redirects were not requested, perform no action.
   991 		// If no redirects are present, or, redirects were not requested, perform no action.
   961 		if ( ! isset( $response['headers']['location'] ) || 0 === $args['_redirection'] )
   992 		if ( ! isset( $response['headers']['location'] ) || 0 === $args['_redirection'] ) {
   962 			return false;
   993 			return false;
       
   994 		}
   963 
   995 
   964 		// Only perform redirections on redirection http codes.
   996 		// Only perform redirections on redirection http codes.
   965 		if ( $response['response']['code'] > 399 || $response['response']['code'] < 300 )
   997 		if ( $response['response']['code'] > 399 || $response['response']['code'] < 300 ) {
   966 			return false;
   998 			return false;
       
   999 		}
   967 
  1000 
   968 		// Don't redirect if we've run out of redirects.
  1001 		// Don't redirect if we've run out of redirects.
   969 		if ( $args['redirection']-- <= 0 )
  1002 		if ( $args['redirection']-- <= 0 ) {
   970 			return new WP_Error( 'http_request_failed', __('Too many redirects.') );
  1003 			return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) );
       
  1004 		}
   971 
  1005 
   972 		$redirect_location = $response['headers']['location'];
  1006 		$redirect_location = $response['headers']['location'];
   973 
  1007 
   974 		// If there were multiple Location headers, use the last header specified.
  1008 		// If there were multiple Location headers, use the last header specified.
   975 		if ( is_array( $redirect_location ) )
  1009 		if ( is_array( $redirect_location ) ) {
   976 			$redirect_location = array_pop( $redirect_location );
  1010 			$redirect_location = array_pop( $redirect_location );
       
  1011 		}
   977 
  1012 
   978 		$redirect_location = WP_Http::make_absolute_url( $redirect_location, $url );
  1013 		$redirect_location = WP_Http::make_absolute_url( $redirect_location, $url );
   979 
  1014 
   980 		// POST requests should not POST to a redirected location.
  1015 		// POST requests should not POST to a redirected location.
   981 		if ( 'POST' == $args['method'] ) {
  1016 		if ( 'POST' == $args['method'] ) {
   982 			if ( in_array( $response['response']['code'], array( 302, 303 ) ) )
  1017 			if ( in_array( $response['response']['code'], array( 302, 303 ) ) ) {
   983 				$args['method'] = 'GET';
  1018 				$args['method'] = 'GET';
       
  1019 			}
   984 		}
  1020 		}
   985 
  1021 
   986 		// Include valid cookies in the redirect process.
  1022 		// Include valid cookies in the redirect process.
   987 		if ( ! empty( $response['cookies'] ) ) {
  1023 		if ( ! empty( $response['cookies'] ) ) {
   988 			foreach ( $response['cookies'] as $cookie ) {
  1024 			foreach ( $response['cookies'] as $cookie ) {
   989 				if ( $cookie->test( $redirect_location ) )
  1025 				if ( $cookie->test( $redirect_location ) ) {
   990 					$args['cookies'][] = $cookie;
  1026 					$args['cookies'][] = $cookie;
       
  1027 				}
   991 			}
  1028 			}
   992 		}
  1029 		}
   993 
  1030 
   994 		return wp_remote_request( $redirect_location, $args );
  1031 		return wp_remote_request( $redirect_location, $args );
   995 	}
  1032 	}
  1003 	 * an IP address.
  1040 	 * an IP address.
  1004 	 *
  1041 	 *
  1005 	 * @link http://home.deds.nl/~aeron/regex/ for IPv6 regex
  1042 	 * @link http://home.deds.nl/~aeron/regex/ for IPv6 regex
  1006 	 *
  1043 	 *
  1007 	 * @since 3.7.0
  1044 	 * @since 3.7.0
  1008 	 * @static
       
  1009 	 *
  1045 	 *
  1010 	 * @param string $maybe_ip A suspected IP address
  1046 	 * @param string $maybe_ip A suspected IP address
  1011 	 * @return integer|bool Upon success, '4' or '6' to represent a IPv4 or IPv6 address, false upon failure
  1047 	 * @return integer|bool Upon success, '4' or '6' to represent a IPv4 or IPv6 address, false upon failure
  1012 	 */
  1048 	 */
  1013 	public static function is_ip_address( $maybe_ip ) {
  1049 	public static function is_ip_address( $maybe_ip ) {
  1014 		if ( preg_match( '/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $maybe_ip ) )
  1050 		if ( preg_match( '/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $maybe_ip ) ) {
  1015 			return 4;
  1051 			return 4;
  1016 
  1052 		}
  1017 		if ( false !== strpos( $maybe_ip, ':' ) && preg_match( '/^(((?=.*(::))(?!.*\3.+\3))\3?|([\dA-F]{1,4}(\3|:\b|$)|\2))(?4){5}((?4){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i', trim( $maybe_ip, ' []' ) ) )
  1053 
       
  1054 		if ( false !== strpos( $maybe_ip, ':' ) && preg_match( '/^(((?=.*(::))(?!.*\3.+\3))\3?|([\dA-F]{1,4}(\3|:\b|$)|\2))(?4){5}((?4){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i', trim( $maybe_ip, ' []' ) ) ) {
  1018 			return 6;
  1055 			return 6;
       
  1056 		}
  1019 
  1057 
  1020 		return false;
  1058 		return false;
  1021 	}
  1059 	}
  1022 
  1060 
  1023 }
  1061 }