| 941 | | * HTTP request method uses HTTP extension to retrieve the url. |
| 942 | | * |
| 943 | | * Requires the HTTP extension to be installed. This would be the preferred transport since it can |
| 944 | | * handle a lot of the problems that forces the others to use the HTTP version 1.0. Even if PHP 5.2+ |
| 945 | | * is being used, it doesn't mean that the HTTP extension will be enabled. |
| 946 | | * |
| 947 | | * @package WordPress |
| 948 | | * @subpackage HTTP |
| 949 | | * @since 2.7.0 |
| 950 | | */ |
| 951 | | class WP_Http_ExtHttp { |
| 952 | | /** |
| 953 | | * Send a HTTP request to a URI using HTTP extension. |
| 954 | | * |
| 955 | | * Does not support non-blocking. |
| 956 | | * |
| 957 | | * @access public |
| 958 | | * @since 2.7 |
| 959 | | * |
| 960 | | * @param string $url |
| 961 | | * @param str|array $args Optional. Override the defaults. |
| 962 | | * @return array 'headers', 'body', 'cookies' and 'response' keys. |
| 963 | | */ |
| 964 | | function request($url, $args = array()) { |
| 965 | | $defaults = array( |
| 966 | | 'method' => 'GET', 'timeout' => 5, |
| 967 | | 'redirection' => 5, 'httpversion' => '1.0', |
| 968 | | 'blocking' => true, |
| 969 | | 'headers' => array(), 'body' => null, 'cookies' => array() |
| 970 | | ); |
| 971 | | |
| 972 | | $r = wp_parse_args( $args, $defaults ); |
| 973 | | |
| 974 | | if ( isset($r['headers']['User-Agent']) ) { |
| 975 | | $r['user-agent'] = $r['headers']['User-Agent']; |
| 976 | | unset($r['headers']['User-Agent']); |
| 977 | | } else if ( isset($r['headers']['user-agent']) ) { |
| 978 | | $r['user-agent'] = $r['headers']['user-agent']; |
| 979 | | unset($r['headers']['user-agent']); |
| 980 | | } |
| 981 | | |
| 982 | | // Construct Cookie: header if any cookies are set |
| 983 | | WP_Http::buildCookieHeader( $r ); |
| 984 | | |
| 985 | | switch ( $r['method'] ) { |
| 986 | | case 'POST': |
| 987 | | $r['method'] = HTTP_METH_POST; |
| 988 | | break; |
| 989 | | case 'HEAD': |
| 990 | | $r['method'] = HTTP_METH_HEAD; |
| 991 | | break; |
| 992 | | case 'PUT': |
| 993 | | $r['method'] = HTTP_METH_PUT; |
| 994 | | break; |
| 995 | | case 'GET': |
| 996 | | default: |
| 997 | | $r['method'] = HTTP_METH_GET; |
| 998 | | } |
| 999 | | |
| 1000 | | $arrURL = parse_url($url); |
| 1001 | | |
| 1002 | | if ( 'http' != $arrURL['scheme'] && 'https' != $arrURL['scheme'] ) |
| 1003 | | $url = preg_replace('|^' . preg_quote($arrURL['scheme'], '|') . '|', 'http', $url); |
| 1004 | | |
| 1005 | | $is_local = isset($args['local']) && $args['local']; |
| 1006 | | $ssl_verify = isset($args['sslverify']) && $args['sslverify']; |
| 1007 | | if ( $is_local ) |
| 1008 | | $ssl_verify = apply_filters('https_local_ssl_verify', $ssl_verify); |
| 1009 | | elseif ( ! $is_local ) |
| 1010 | | $ssl_verify = apply_filters('https_ssl_verify', $ssl_verify); |
| 1011 | | |
| 1012 | | $r['timeout'] = (int) ceil( $r['timeout'] ); |
| 1013 | | |
| 1014 | | $options = array( |
| 1015 | | 'timeout' => $r['timeout'], |
| 1016 | | 'connecttimeout' => $r['timeout'], |
| 1017 | | 'redirect' => $r['redirection'], |
| 1018 | | 'useragent' => $r['user-agent'], |
| 1019 | | 'headers' => $r['headers'], |
| 1020 | | 'ssl' => array( |
| 1021 | | 'verifypeer' => $ssl_verify, |
| 1022 | | 'verifyhost' => $ssl_verify |
| 1023 | | ) |
| 1024 | | ); |
| 1025 | | |
| 1026 | | // The HTTP extensions offers really easy proxy support. |
| 1027 | | $proxy = new WP_HTTP_Proxy(); |
| 1028 | | |
| 1029 | | if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { |
| 1030 | | $options['proxyhost'] = $proxy->host(); |
| 1031 | | $options['proxyport'] = $proxy->port(); |
| 1032 | | $options['proxytype'] = HTTP_PROXY_HTTP; |
| 1033 | | |
| 1034 | | if ( $proxy->use_authentication() ) { |
| 1035 | | $options['proxyauth'] = $proxy->authentication(); |
| 1036 | | $options['proxyauthtype'] = HTTP_AUTH_ANY; |
| 1037 | | } |
| 1038 | | } |
| 1039 | | |
| 1040 | | if ( !WP_DEBUG ) //Emits warning level notices for max redirects and timeouts |
| 1041 | | $strResponse = @http_request($r['method'], $url, $r['body'], $options, $info); |
| 1042 | | else |
| 1043 | | $strResponse = http_request($r['method'], $url, $r['body'], $options, $info); //Emits warning level notices for max redirects and timeouts |
| 1044 | | |
| 1045 | | // Error may still be set, Response may return headers or partial document, and error |
| 1046 | | // contains a reason the request was aborted, eg, timeout expired or max-redirects reached. |
| 1047 | | if ( false === $strResponse || ! empty($info['error']) ) |
| 1048 | | return new WP_Error('http_request_failed', $info['response_code'] . ': ' . $info['error']); |
| 1049 | | |
| 1050 | | if ( ! $r['blocking'] ) |
| 1051 | | return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() ); |
| 1052 | | |
| 1053 | | $headers_body = WP_HTTP::processResponse($strResponse); |
| 1054 | | $theHeaders = $headers_body['headers']; |
| 1055 | | $theBody = $headers_body['body']; |
| 1056 | | unset($headers_body); |
| 1057 | | |
| 1058 | | $theHeaders = WP_Http::processHeaders($theHeaders); |
| 1059 | | |
| 1060 | | if ( ! empty( $theBody ) && isset( $theHeaders['headers']['transfer-encoding'] ) && 'chunked' == $theHeaders['headers']['transfer-encoding'] ) { |
| 1061 | | if ( !WP_DEBUG ) |
| 1062 | | $theBody = @http_chunked_decode($theBody); |
| 1063 | | else |
| 1064 | | $theBody = http_chunked_decode($theBody); |
| 1065 | | } |
| 1066 | | |
| 1067 | | if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders['headers']) ) |
| 1068 | | $theBody = http_inflate( $theBody ); |
| 1069 | | |
| 1070 | | if ( $r['stream'] ) { |
| 1071 | | if ( !WP_DEBUG ) |
| 1072 | | $stream_handle = @fopen( $r['filename'], 'w+' ); |
| 1073 | | else |
| 1074 | | $stream_handle = fopen( $r['filename'], 'w+' ); |
| 1075 | | |
| 1076 | | if ( ! $stream_handle ) |
| 1077 | | return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); |
| 1078 | | |
| 1079 | | fwrite( $stream_handle, $theBody ); |
| 1080 | | fclose( $stream_handle ); |
| 1081 | | $theBody = ''; |
| 1082 | | } |
| 1083 | | |
| 1084 | | $theResponse = array(); |
| 1085 | | $theResponse['code'] = $info['response_code']; |
| 1086 | | $theResponse['message'] = get_status_header_desc($info['response_code']); |
| 1087 | | |
| 1088 | | return array( 'headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $theResponse, 'cookies' => $theHeaders['cookies'], 'filename' => $r['filename'] ); |
| 1089 | | } |
| 1090 | | |
| 1091 | | /** |
| 1092 | | * Whether this class can be used for retrieving an URL. |
| 1093 | | * |
| 1094 | | * @static |
| 1095 | | * @since 2.7.0 |
| 1096 | | * |
| 1097 | | * @return boolean False means this class can not be used, true means it can. |
| 1098 | | */ |
| 1099 | | function test($args = array()) { |
| 1100 | | return apply_filters('use_http_extension_transport', function_exists('http_request'), $args ); |
| 1101 | | } |
| 1102 | | } |
| 1103 | | |
| 1104 | | /** |