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 | | /** |