Ticket #4011: 4011.2.diff
File 4011.2.diff, 40.5 KB (added by , 16 years ago) |
---|
-
http.php
13 13 */ 14 14 15 15 /** 16 * Implementation for deflate and gzip transfer encodings.17 *18 * Includes RFC 1950, RFC 1951, and RFC 1952.19 *20 * @since unknown21 * @package WordPress22 * @subpackage HTTP23 */24 class WP_Http_Encoding {25 26 /**27 * Compress raw string using the deflate format.28 *29 * Supports the RFC 1951 standard.30 *31 * @since unknown32 *33 * @param string $raw String to compress.34 * @param int $level Optional, default is 9. Compression level, 9 is highest.35 * @param string $supports Optional, not used. When implemented it will choose the right compression based on what the server supports.36 * @return string|bool False on failure.37 */38 function compress( $raw, $level = 9, $supports = null ) {39 return gzdeflate( $raw, $level );40 }41 42 /**43 * Decompression of deflated string.44 *45 * Will attempt to decompress using the RFC 1950 standard, and if that fails46 * then the RFC 1951 standard deflate will be attempted. Finally, the RFC47 * 1952 standard gzip decode will be attempted. If all fail, then the48 * original compressed string will be returned.49 *50 * @since unknown51 *52 * @param string $compressed String to decompress.53 * @param int $length The optional length of the compressed data.54 * @return string|bool False on failure.55 */56 function decompress( $compressed, $length = null ) {57 $decompressed = gzinflate( $compressed );58 59 if( false !== $decompressed )60 return $decompressed;61 62 $decompressed = gzuncompress( $compressed );63 64 if( false !== $decompressed )65 return $decompressed;66 67 $decompressed = gzdecode( $compressed );68 69 if( false !== $decompressed )70 return $decompressed;71 72 return $compressed;73 }74 75 /**76 * What encoding types to accept and their priority values.77 *78 * @since unknown79 *80 * @return string Types of encoding to accept.81 */82 function accept_encoding() {83 $type = array();84 if( function_exists( 'gzinflate' ) )85 $type[] = 'deflate;q=1.0';86 87 if( function_exists( 'gzuncompress' ) )88 $type[] = 'compress;q=0.5';89 90 if( function_exists( 'gzdecode' ) )91 $type[] = 'gzip;q=0.5';92 93 return implode(', ', $type);94 }95 96 /**97 * What enconding the content used when it was compressed to send in the headers.98 *99 * @since unknown100 *101 * @return string Content-Encoding string to send in the header.102 */103 function content_encoding() {104 return 'deflate';105 }106 107 /**108 * Whether the content be decoded based on the headers.109 *110 * @since unknown111 *112 * @param array|string $headers All of the available headers.113 * @return bool114 */115 function should_decode($headers) {116 if( is_array( $headers ) ) {117 if( array_key_exists('content-encoding', $headers) && ! empty( $headers['content-encoding'] ) )118 return true;119 } else if( is_string( $headers ) ) {120 return ( stripos($headers, 'content-encoding:') !== false );121 }122 123 return false;124 }125 126 /**127 * Whether decompression and compression are supported by the PHP version.128 *129 * Each function is tested instead of checking for the zlib extension, to130 * ensure that the functions all exist in the PHP version and aren't131 * disabled.132 *133 * @since unknown134 *135 * @return bool136 */137 function is_available() {138 return ( function_exists('gzuncompress') || function_exists('gzdeflate') ||139 function_exists('gzinflate') );140 }141 }142 143 /**144 16 * WordPress HTTP Class for managing HTTP Transports and making HTTP requests. 145 17 * 146 * This class is called for the functionality of making HTTP requests and should 147 * replace Snoopy functionality, eventually. There is no available functionality 148 * to add HTTP transport implementations, since most of the HTTP transports are 149 * added and available for use. 18 * This class is called for the functionality of making HTTP requests and should replace Snoopy 19 * functionality, eventually. There is no available functionality to add HTTP transport 20 * implementations, since most of the HTTP transports are added and available for use. 150 21 * 151 * The exception is that cURL is not available as a transport and lacking an 152 * implementation. It will be added later and should be a patch on the WordPress 153 * Trac. 22 * The exception is that cURL is not available as a transport and lacking an implementation. It will 23 * be added later and should be a patch on the WordPress Trac. 154 24 * 155 * There are no properties, because none are needed and for performance reasons. 156 * Some of the functions are static and while they do have some overhead over157 * functions in PHP4, the purpose is maintainability. When PHP5 is finally the158 * requirement, it will be easy to add the static keyword to the code. It is not159 * as easy to convert a function to a method after enough code uses the oldway.25 * There are no properties, because none are needed and for performance reasons. Some of the 26 * functions are static and while they do have some overhead over functions in PHP4, the purpose is 27 * maintainability. When PHP5 is finally the requirement, it will be easy to add the static keyword 28 * to the code. It is not as easy to convert a function to a method after enough code uses the old 29 * way. 160 30 * 161 * Debugging includes several actions, which pass different variables for 162 * debugging the HTTP API. 31 * Debugging includes several actions, which pass different variables for debugging the HTTP API. 163 32 * 164 * <strong>http_transport_get_debug</strong> - gives working, nonblocking, and 165 * blocking transports. 33 * <strong>http_transport_get_debug</strong> - gives working, nonblocking, and blocking transports. 166 34 * 167 * <strong>http_transport_post_debug</strong> - gives working, nonblocking, and 168 * blocking transports. 35 * <strong>http_transport_post_debug</strong> - gives working, nonblocking, and blocking transports. 169 36 * 170 37 * @package WordPress 171 38 * @subpackage HTTP … … 228 95 static $working_transport, $blocking_transport, $nonblocking_transport; 229 96 230 97 if ( is_null($working_transport) ) { 231 if ( true === WP_Http_ExtHttp::test() && apply_filters('use_http_extension_transport', true)) {98 if ( true === WP_Http_ExtHttp::test() ) { 232 99 $working_transport['exthttp'] = new WP_Http_ExtHttp(); 233 100 $blocking_transport[] = &$working_transport['exthttp']; 234 } else if ( true === WP_Http_Curl::test() && apply_filters('use_curl_transport', true)) {101 } else if ( true === WP_Http_Curl::test() ) { 235 102 $working_transport['curl'] = new WP_Http_Curl(); 236 103 $blocking_transport[] = &$working_transport['curl']; 237 } else if ( true === WP_Http_Streams::test() && apply_filters('use_streams_transport', true)) {104 } else if ( true === WP_Http_Streams::test() ) { 238 105 $working_transport['streams'] = new WP_Http_Streams(); 239 106 $blocking_transport[] = &$working_transport['streams']; 240 } else if ( true === WP_Http_Fopen::test() && apply_filters('use_fopen_transport', true) && ( isset($args['ssl']) && !$args['ssl'] ) ) {107 } else if ( true === WP_Http_Fopen::test() && ( isset($args['ssl']) && ! $args['ssl'] ) ) { 241 108 $working_transport['fopen'] = new WP_Http_Fopen(); 242 109 $blocking_transport[] = &$working_transport['fopen']; 243 } else if ( true === WP_Http_Fsockopen::test() && apply_filters('use_fsockopen_transport', true) && ( isset($args['ssl']) && !$args['ssl'] ) ) {110 } else if ( true === WP_Http_Fsockopen::test() && ( isset($args['ssl']) && ! $args['ssl'] ) ) { 244 111 $working_transport['fsockopen'] = new WP_Http_Fsockopen(); 245 112 $blocking_transport[] = &$working_transport['fsockopen']; 246 113 } … … 279 146 static $working_transport, $blocking_transport, $nonblocking_transport; 280 147 281 148 if ( is_null($working_transport) ) { 282 if ( true === WP_Http_ExtHttp::test() && apply_filters('use_http_extension_transport', true)) {149 if ( true === WP_Http_ExtHttp::test() ) { 283 150 $working_transport['exthttp'] = new WP_Http_ExtHttp(); 284 151 $blocking_transport[] = &$working_transport['exthttp']; 285 } else if ( true === WP_Http_Curl::test() && apply_filters('use_curl_transport', true)) {152 } else if ( true === WP_Http_Curl::test() ) { 286 153 $working_transport['curl'] = new WP_Http_Curl(); 287 154 $blocking_transport[] = &$working_transport['curl']; 288 } else if ( true === WP_Http_Streams::test() && apply_filters('use_streams_transport', true)) {155 } else if ( true === WP_Http_Streams::test() ) { 289 156 $working_transport['streams'] = new WP_Http_Streams(); 290 157 $blocking_transport[] = &$working_transport['streams']; 291 } else if ( true === WP_Http_Fsockopen::test() && apply_filters('use_fsockopen_transport', true) && ( isset($args['ssl']) && !$args['ssl'] ) ) {158 } else if ( true === WP_Http_Fsockopen::test() && ( isset($args['ssl']) && ! $args['ssl'] ) ) { 292 159 $working_transport['fsockopen'] = new WP_Http_Fsockopen(); 293 160 $blocking_transport[] = &$working_transport['fsockopen']; 294 161 } … … 311 178 /** 312 179 * Send a HTTP request to a URI. 313 180 * 314 * The body and headers are part of the arguments. The 'body' argument is 315 * for the body and will accept either a string or an array. The 'headers' 316 * argument should be an array, but a string is acceptable. If the 'body' 317 * argument is an array, then it will automatically be escaped using 318 * http_build_query(). 181 * The body and headers are part of the arguments. The 'body' argument is for the body and will 182 * accept either a string or an array. The 'headers' argument should be an array, but a string 183 * is acceptable. If the 'body' argument is an array, then it will automatically be escaped 184 * using http_build_query(). 319 185 * 320 * The only URI that are supported in the HTTP Transport implementation are 321 * the HTTP and HTTPS protocols. HTTP and HTTPS are assumed so the server 322 * might not know how to handle the send headers. Other protocols are 323 * unsupported and most likely will fail. 186 * The only URI that are supported in the HTTP Transport implementation are the HTTP and HTTPS 187 * protocols. HTTP and HTTPS are assumed so the server might not know how to handle the send 188 * headers. Other protocols are unsupported and most likely will fail. 324 189 * 325 * The defaults are 'method', 'timeout', 'redirection', 'httpversion', 326 * ' blocking' and 'user-agent'.190 * The defaults are 'method', 'timeout', 'redirection', 'httpversion', 'blocking' and 191 * 'user-agent'. 327 192 * 328 * Accepted 'method' values are 'GET', 'POST', and 'HEAD', some transports 329 * technically allow others, but should not be assumed. The 'timeout' is 330 * used to sent how long the connection should stay open before failing when 331 * no response. 'redirection' is used to track how many redirects were taken 332 * and used to sent the amount for other transports, but not all transports 193 * Accepted 'method' values are 'GET', 'POST', and 'HEAD', some transports technically allow 194 * others, but should not be assumed. The 'timeout' is used to sent how long the connection 195 * should stay open before failing when no response. 'redirection' is used to track how many 196 * redirects were taken and used to sent the amount for other transports, but not all transports 333 197 * accept setting that value. 334 198 * 335 * The 'httpversion' option is used to sent the HTTP version and accepted 336 * values are '1.0', and '1.1' and should be a string. Version 1.1 is not 337 * supported, because of chunk response. The 'user-agent' option is the 338 * user-agent and is used to replace the default user-agent, which is 199 * The 'httpversion' option is used to sent the HTTP version and accepted values are '1.0', and 200 * '1.1' and should be a string. Version 1.1 is not supported, because of chunk response. The 201 * 'user-agent' option is the user-agent and is used to replace the default user-agent, which is 339 202 * 'WordPress/WP_Version', where WP_Version is the value from $wp_version. 340 203 * 341 * 'blocking' is the default, which is used to tell the transport, whether 342 * it should halt PHP while it performs the request or continue regardless. 343 * Actually, that isn't entirely correct. Blocking mode really just means 344 * whether the fread should just pull what it can whenever it gets bytes or 345 * if it should wait until it has enough in the buffer to read or finishes 346 * reading the entire content. It doesn't actually always mean that PHP will 347 * continue going after making the request. 204 * 'blocking' is the default, which is used to tell the transport, whether it should halt PHP 205 * while it performs the request or continue regardless. Actually, that isn't entirely correct. 206 * Blocking mode really just means whether the fread should just pull what it can whenever it 207 * gets bytes or if it should wait until it has enough in the buffer to read or finishes reading 208 * the entire content. It doesn't actually always mean that PHP will continue going after making 209 * the request. 348 210 * 349 211 * @access public 350 212 * @since 2.7.0 … … 400 262 $r['user-agent'] = $r['headers']['user-agent']; 401 263 unset($r['headers']['user-agent']); 402 264 } 403 265 404 266 // Construct Cookie: header if any cookies are set 405 267 WP_Http::buildCookieHeader( $r ); 406 268 … … 514 376 /** 515 377 * Transform header string into an array. 516 378 * 517 * If an array is given then it is assumed to be raw header data with 518 * numeric keys with the headers as the values. No headers must be passed 519 * that were already processed. 379 * If an array is given then it is assumed to be raw header data with numeric keys with the 380 * headers as the values. No headers must be passed that were already processed. 520 381 * 521 382 * @access public 522 383 * @static … … 561 422 562 423 return array('response' => $response, 'headers' => $newheaders, 'cookies' => $cookies); 563 424 } 564 425 565 426 /** 566 427 * Takes the arguments for a ::request() and checks for the cookie array. 567 * If it's found, then it's assumed to contain WP_Http_Cookie objects, which568 * are each parsed into strings and added to the Cookie: header (within the569 * arguments array). Edits the array by reference.570 428 * 429 * If it's found, then it's assumed to contain WP_Http_Cookie objects, which are each parsed 430 * into strings and added to the Cookie: header (within the arguments array). Edits the array by 431 * reference. 432 * 571 433 * @access public 434 * @version 2.8.0 572 435 * @static 573 436 * 574 437 * @param array $r Full array of args passed into ::request() … … 583 446 $r['headers']['cookie'] = $cookies_header; 584 447 } 585 448 } 586 449 587 450 /** 588 451 * Decodes chunk transfer-encoding, based off the HTTP 1.1 specification. 589 452 * 590 * Based off the HTTP http_encoding_dechunk function. Does not support 591 * UTF-8. Does not support returning footer headers. Shouldn't be too 592 * difficult to support it though. 453 * Based off the HTTP http_encoding_dechunk function. Does not support UTF-8. Does not support 454 * returning footer headers. Shouldn't be too difficult to support it though. 593 455 * 594 456 * @todo Add support for footer chunked headers. 595 457 * @access public … … 635 497 /** 636 498 * HTTP request method uses fsockopen function to retrieve the url. 637 499 * 638 * This would be the preferred method, but the fsockopen implementation has the 639 * most overhead of allthe HTTP transport implementations.500 * This would be the preferred method, but the fsockopen implementation has the most overhead of all 501 * the HTTP transport implementations. 640 502 * 641 503 * @package WordPress 642 504 * @subpackage HTTP … … 696 558 $arrURL['port'] = apply_filters('http_request_port', $arrURL['port']); 697 559 } 698 560 699 // There are issues with the HTTPS and SSL protocols that cause errors 700 // that can be safelyignored and should be ignored.561 // There are issues with the HTTPS and SSL protocols that cause errors that can be safely 562 // ignored and should be ignored. 701 563 if ( true === $secure_transport ) 702 564 $error_reporting = error_reporting(0); 703 565 … … 710 572 711 573 $endDelay = time(); 712 574 713 // If the delay is greater than the timeout then fsockopen should't be 714 // used, because it willcause a long delay.575 // If the delay is greater than the timeout then fsockopen should't be used, because it will 576 // cause a long delay. 715 577 $elapseDelay = ($endDelay-$startDelay) > $r['timeout']; 716 578 if ( true === $elapseDelay ) 717 579 add_option( 'disable_fsockopen', $endDelay, null, true ); … … 719 581 if ( false === $handle ) 720 582 return new WP_Error('http_request_failed', $iError . ': ' . $strError); 721 583 722 // WordPress supports PHP 4.3, which has this function. Removed sanity 723 // checking forperformance reasons.584 // WordPress supports PHP 4.3, which has this function. Removed sanity checking for 585 // performance reasons. 724 586 stream_set_timeout($handle, $r['timeout'] ); 725 587 726 588 $requestPath = $arrURL['path'] . ( isset($arrURL['query']) ? '?' . $arrURL['query'] : '' ); … … 798 660 if ( false !== ($option = get_option( 'disable_fsockopen' )) && time()-$option < 43200 ) // 12 hours 799 661 return false; 800 662 801 if ( function_exists( 'fsockopen' ) )663 if ( function_exists( 'fsockopen' ) && apply_filters('use_fsockopen_transport', true) ) 802 664 return true; 803 665 804 666 return false; … … 808 670 /** 809 671 * HTTP request method uses fopen function to retrieve the url. 810 672 * 811 * Requires PHP version greater than 4.3.0 for stream support. Does not allow 812 * for $context support, but should still be okay, to write the headers, before813 * getting the response. Also requires that'allow_url_fopen' to be enabled.673 * Requires PHP version greater than 4.3.0 for stream support. Does not allow for $context support, 674 * but should still be okay, to write the headers, before getting the response. Also requires that 675 * 'allow_url_fopen' to be enabled. 814 676 * 815 677 * @package WordPress 816 678 * @subpackage HTTP … … 820 682 /** 821 683 * Send a HTTP request to a URI using fopen(). 822 684 * 823 * This transport does not support sending of headers and body, therefore 824 * should not be used inthe instances, where there is a body and headers.685 * This transport does not support sending of headers and body, therefore should not be used in 686 * the instances, where there is a body and headers. 825 687 * 826 688 * Notes: Does not support non-blocking mode. Ignores 'redirection' option. 827 689 * … … 911 773 if ( ! function_exists('fopen') || (function_exists('ini_get') && true != ini_get('allow_url_fopen')) ) 912 774 return false; 913 775 914 return true;776 return apply_filters('use_fopen_transport', true); 915 777 } 916 778 } 917 779 918 780 /** 919 781 * HTTP request method uses Streams to retrieve the url. 920 782 * 921 * Requires PHP 5.0+ and uses fopen with stream context. Requires that 922 * 'allow_url_fopen' PHP settingto be enabled.783 * Requires PHP 5.0+ and uses fopen with stream context. Requires that 'allow_url_fopen' PHP setting 784 * to be enabled. 923 785 * 924 786 * Second preferred method for getting the URL, for PHP 5. 925 787 * … … 955 817 $r['user-agent'] = $r['headers']['user-agent']; 956 818 unset($r['headers']['user-agent']); 957 819 } 958 820 959 821 // Construct Cookie: header if any cookies are set 960 822 WP_Http::buildCookieHeader( $r ); 961 823 … … 984 846 'header' => $strHeaders, 985 847 'timeout' => $r['timeout'], 986 848 'ssl' => array( 987 988 989 849 'verify_peer' => apply_filters('https_ssl_verify', $r['sslverify']), 850 'verify_host' => apply_filters('https_ssl_verify', $r['sslverify']) 851 ) 990 852 ) 991 853 ); 992 854 855 $proxy = new WP_HTTP_Proxy(); 856 857 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { 858 // WTF happens when the user stupidly puts http:// in the host? Bad things. Really, 859 // really bad things happen. Not exactly unleashing demons from hell, but you know. 860 // Just as bad probably. Actually, none of the other transports should work in that case 861 // so no sanitization is done. If there is, it should be done in the 862 // WP_HTTP_Proxy::host(). 863 // 864 // On second thought, why is it tcp protocol? Why not http? What if the proxy is http 865 // and not tcp? Even though, technically, http is tcp, but just a specialized form of 866 // tcp. Behavior is undefined, so it is probably good that not a lot of users will be 867 // affected by FUBAR behavior. 868 // 869 // Is it another WTF? that this multiline comment isn't using multiline comment syntax? 870 $arrContext['http']['proxy'] = 'tcp://'.$proxy->host().':'$proxy->port(); 871 872 // Yeah, this may or may not work. Good luck. 873 if ( $proxy->use_authentication() ) { 874 $arrContext['http']['header'] .= $proxy->authentication_header() . "\r\n"; 875 } 876 } 877 993 878 if ( ! is_null($r['body']) && ! empty($r['body'] ) ) 994 879 $arrContext['http']['content'] = $r['body']; 995 880 … … 1003 888 if ( ! $handle) 1004 889 return new WP_Error('http_request_failed', sprintf(__('Could not open handle for fopen() to %s'), $url)); 1005 890 1006 // WordPress supports PHP 4.3, which has this function. Removed sanity 1007 // checking forperformance reasons.891 // WordPress supports PHP 4.3, which has this function. Removed sanity checking for 892 // performance reasons. 1008 893 stream_set_timeout($handle, $r['timeout'] ); 1009 894 1010 895 if ( ! $r['blocking'] ) { … … 1049 934 if ( version_compare(PHP_VERSION, '5.0', '<') ) 1050 935 return false; 1051 936 1052 return true;937 return apply_filters('use_streams_transport', true); 1053 938 } 1054 939 } 1055 940 1056 941 /** 1057 942 * HTTP request method uses HTTP extension to retrieve the url. 1058 943 * 1059 * Requires the HTTP extension to be installed. This would be the preferred 1060 * transport since it can handle a lot of the problems that forces the others to 1061 * use the HTTP version 1.0. Even if PHP 5.2+ is being used, it doesn't mean 1062 * that the HTTP extension will be enabled. 944 * Requires the HTTP extension to be installed. This would be the preferred transport since it can 945 * handle a lot of the problems that forces the others to use the HTTP version 1.0. Even if PHP 5.2+ 946 * is being used, it doesn't mean that the HTTP extension will be enabled. 1063 947 * 1064 948 * @package WordPress 1065 949 * @subpackage HTTP … … 1095 979 $r['user-agent'] = $r['headers']['user-agent']; 1096 980 unset($r['headers']['user-agent']); 1097 981 } 1098 982 1099 983 // Construct Cookie: header if any cookies are set 1100 984 WP_Http::buildCookieHeader( $r ); 1101 985 … … 1128 1012 ) 1129 1013 ); 1130 1014 1015 // The HTTP extensions offers really easy proxy support. 1016 $proxy = new WP_HTTP_Proxy(); 1017 1018 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { 1019 $options['proxyhost'] = $proxy->host(); 1020 $options['proxyport'] = $proxy->port(); 1021 $options['proxytype'] = HTTP_PROXY_HTTP; 1022 1023 if ( $proxy->use_authentication() ) { 1024 $options['proxyauth'] = $proxy->authentication(); 1025 $options['proxyauthtype'] = HTTP_AUTH_BASIC; 1026 } 1027 } 1028 1131 1029 if ( !defined('WP_DEBUG') || ( defined('WP_DEBUG') && false === WP_DEBUG ) ) //Emits warning level notices for max redirects and timeouts 1132 1030 $strResponse = @http_request($r['method'], $url, $r['body'], $options, $info); 1133 1031 else 1134 1032 $strResponse = http_request($r['method'], $url, $r['body'], $options, $info); //Emits warning level notices for max redirects and timeouts 1135 1033 1136 if ( false === $strResponse || ! empty($info['error']) ) //Error may still be set, Response may return headers or partial document, and error contains a reason the request was aborted, eg, timeout expired or max-redirects reached 1034 // Error may still be set, Response may return headers or partial document, and error 1035 // contains a reason the request was aborted, eg, timeout expired or max-redirects reached. 1036 if ( false === $strResponse || ! empty($info['error']) ) 1137 1037 return new WP_Error('http_request_failed', $info['response_code'] . ': ' . $info['error']); 1138 1038 1139 1039 if ( ! $r['blocking'] ) … … 1168 1068 * @return boolean False means this class can not be used, true means it can. 1169 1069 */ 1170 1070 function test() { 1171 if ( function_exists('http_request') )1071 if ( function_exists('http_request') && apply_filters('use_http_extension_transport', true) ) 1172 1072 return true; 1173 1073 1174 1074 return false; … … 1185 1085 * @since 2.7 1186 1086 */ 1187 1087 class WP_Http_Curl { 1088 1188 1089 /** 1189 1090 * Send a HTTP request to a URI using cURL extension. 1190 1091 * … … 1212 1113 $r['user-agent'] = $r['headers']['user-agent']; 1213 1114 unset($r['headers']['user-agent']); 1214 1115 } 1215 1216 // Construct Cookie: header if any cookies are set 1116 1117 // Construct Cookie: header if any cookies are set. 1217 1118 WP_Http::buildCookieHeader( $r ); 1218 1119 1219 // cURL extension will sometimes fail when the timeout is less than 1 as 1220 // it may round downto 0, which gives it unlimited timeout.1120 // cURL extension will sometimes fail when the timeout is less than 1 as it may round down 1121 // to 0, which gives it unlimited timeout. 1221 1122 if ( $r['timeout'] > 0 && $r['timeout'] < 1 ) 1222 1123 $r['timeout'] = 1; 1223 1124 1224 1125 $handle = curl_init(); 1225 1126 1127 // cURL offers really easy proxy support. 1128 $proxy = new WP_HTTP_Proxy(); 1129 1130 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { 1131 curl_setopt( $handle, CURLOPT_HTTPPROXYTUNNEL, true ); 1132 1133 $isPHP5 = version_compare(PHP_VERSION, '5.0.0', '>='); 1134 1135 if ( $isPHP5 ) { 1136 curl_setopt( $handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP ); 1137 curl_setopt( $handle, CURLOPT_PROXY, $proxy->host() ); 1138 curl_setopt( $handle, CURLOPT_PROXYPORT, $proxy->port() ); 1139 } else { 1140 curl_setopt( $handle, CURLOPT_PROXY, $proxy->host() .':'. $proxy->port() ); 1141 } 1142 1143 if ( $proxy->use_authentication() ) { 1144 if ( $isPHP5 ) 1145 curl_setopt( $handle, CURLOPT_PROXYAUTH, CURLAUTH_BASIC ); 1146 1147 curl_setopt( $handle, CURLOPT_PROXYUSERPWD, $proxy->authentication() ); 1148 } 1149 } 1150 1226 1151 curl_setopt( $handle, CURLOPT_URL, $url); 1227 1152 curl_setopt( $handle, CURLOPT_RETURNTRANSFER, true ); 1228 1153 curl_setopt( $handle, CURLOPT_SSL_VERIFYHOST, apply_filters('https_ssl_verify', $r['sslverify']) ); … … 1265 1190 else 1266 1191 curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); 1267 1192 1268 // Cookies are not handled by the HTTP API currently. Allow for plugin 1269 // authors to handle it themselves... Although, it is somewhat pointless 1270 // without some reference. 1193 // Cookies are not handled by the HTTP API currently. Allow for plugin authors to handle it 1194 // themselves... Although, it is somewhat pointless without some reference. 1271 1195 do_action_ref_array( 'http_api_curl', array(&$handle) ); 1272 1196 1273 // We don't need to return the body, so don't. Just execute request 1274 // and return. 1197 // We don't need to return the body, so don't. Just execute request and return. 1275 1198 if ( ! $r['blocking'] ) { 1276 1199 curl_exec( $handle ); 1277 1200 curl_close( $handle ); … … 1320 1243 * @return boolean False means this class can not be used, true means it can. 1321 1244 */ 1322 1245 function test() { 1323 if ( function_exists('curl_init') && function_exists('curl_exec') )1246 if ( function_exists('curl_init') && function_exists('curl_exec') && apply_filters('use_curl_transport', true) ) 1324 1247 return true; 1325 1248 1326 1249 return false; 1327 1250 } 1328 1251 } 1329 1252 1253 /** 1254 * Adds Proxy support to the WordPress HTTP API. 1255 * 1256 * Proxy support is fringe enough that it isn't support in WordPress by default, meaning no plans 1257 * were made to implement it. Most WordPress users are not going to benefit with its support, but 1258 * enough people have made a stink out of the lack of it that it should be supported. 1259 * 1260 * There are caveats to proxy support. It requires that defines be made in the wp-config.php file to 1261 * enable proxy support. There are also a few filters that plugins can hook into for some of the 1262 * constants. 1263 * 1264 * The constants are as follows: 1265 * <ol> 1266 * <li>WP_PROXY_HOST - Enable proxy support and host for connecting.</li> 1267 * <li>WP_PROXY_PORT - Proxy port for connection. No default, must be defined.</li> 1268 * <li>WP_PROXY_USERNAME - Proxy username, if it requires authentication.</li> 1269 * <li>WP_PROXY_PASSWORD - Proxy password, if it requires authentication.</li> 1270 * <li>WP_PROXY_BYPASS_HOSTS - Will prevent the hosts in this list from going through the proxy. 1271 * You do not need to have localhost and the blog host in this list, because they will not be passed 1272 * through the proxy.</li> 1273 * </ol> 1274 * 1275 * An example can be as seen below. 1276 * <code> 1277 * define('WP_PROXY_HOST', '192.168.84.101'); 1278 * define('WP_PROXY_PORT', '8080'); 1279 * define('WP_PROXY_BYPASS_HOSTS', array('localhost', 'www.example.com')); 1280 * </code> 1281 * 1282 * @link http://core.trac.wordpress.org/ticket/4011 Proxy support ticket in WordPress. 1283 * @since unknown 1284 */ 1285 class WP_HTTP_Proxy { 1330 1286 1287 function WP_HTTP_Proxy() { 1288 $this->__construct(); 1289 } 1290 1291 function __construct() { 1292 1293 } 1294 1295 /** 1296 * Whether proxy connection should be used. 1297 * 1298 * @since unknown 1299 * @use WP_PROXY_HOST 1300 * @use WP_PROXY_PORT 1301 * 1302 * @return bool 1303 */ 1304 function is_enabled() { 1305 return ( defined('WP_PROXY_HOST') && defined('WP_PROXY_PORT') ); 1306 } 1307 1308 /** 1309 * Whether authentication should be used. 1310 * 1311 * @since unknown 1312 * @use WP_PROXY_USERNAME 1313 * @use WP_PROXY_PASSWORD 1314 * 1315 * @return bool 1316 */ 1317 function use_authentication() { 1318 return ( defined('WP_PROXY_USERNAME') && defined('WP_PROXY_PASSWORD') ); 1319 } 1320 1321 /** 1322 * Retrieve the host for the proxy server. 1323 * 1324 * @since unknown 1325 * 1326 * @return string 1327 */ 1328 function host() 1329 { 1330 if( defined('WP_PROXY_HOST') ) 1331 return WP_PROXY_HOST; 1332 1333 return ''; 1334 } 1335 1336 /** 1337 * Retrieve the port for the proxy server. 1338 * 1339 * @since unknown 1340 * 1341 * @return string 1342 */ 1343 function port() 1344 { 1345 if( defined('WP_PROXY_PORT') ) 1346 return WP_PROXY_PORT; 1347 1348 return ''; 1349 } 1350 1351 /** 1352 * Retrieve the username for proxy authentication. 1353 * 1354 * @since unknown 1355 * 1356 * @return string 1357 */ 1358 function username() 1359 { 1360 if( defined('WP_PROXY_USERNAME') ) 1361 return WP_PROXY_USERNAME; 1362 1363 return ''; 1364 } 1365 1366 /** 1367 * Retrieve the password for proxy authentication. 1368 * 1369 * @since unknown 1370 * 1371 * @return string 1372 */ 1373 function password() 1374 { 1375 if( defined('WP_PROXY_PASSWORD') ) 1376 return WP_PROXY_PASSWORD; 1377 1378 return ''; 1379 } 1380 1381 /** 1382 * Retrieve authentication string for proxy authentication. 1383 * 1384 * @since unknown 1385 * 1386 * @return string 1387 */ 1388 function authentication() { 1389 return $this->username() .':'. $this->password(); 1390 } 1391 1392 /** 1393 * Retrieve header string for proxy authentication. 1394 * 1395 * @since unknown 1396 * 1397 * @return string 1398 */ 1399 function authentication_header() { 1400 return 'Proxy-Authentication: Basic '. base64_encode( $this->authentication() ); 1401 } 1402 1403 /** 1404 * Whether URL should be sent through the proxy server. 1405 * 1406 * We want to keep localhost and the blog URL from being sent through the proxy server, because 1407 * some proxies can not handle this. We also have the constant available for defining other 1408 * hosts that won't be sent through the proxy. 1409 * 1410 * @uses WP_PROXY_BYPASS_HOSTS 1411 * @since unknown 1412 * 1413 * @param string $uri URI to check. 1414 * @return bool True, to send through the proxy and false if, the proxy should not be used. 1415 */ 1416 function send_through_proxy( $uri ) { 1417 // parse_url() only handles http, https type URLs, and will emit E_WARNING on failure. 1418 // This will be displayed on blogs, which is not reasonable. 1419 $check = @parse_url($uri); 1420 1421 // Malformed URL, can not process, but this could mean ssl, so let through anyway. 1422 if( $check === false ) 1423 return true; 1424 1425 $home = parse_url( get_bloginfo('site_url') ); 1426 1427 if ( $uri == 'localhost' || $uri == $home['host'] ) 1428 return false; 1429 1430 if ( defined('WP_PROXY_BYPASS_HOSTS') && is_array( WP_PROXY_BYPASS_HOSTS ) && in_array( $check['host'], WP_PROXY_BYPASS_HOSTS ) ) { 1431 return false; 1432 } 1433 1434 return true; 1435 } 1436 } 1437 1438 1331 1439 /** 1332 * Internal representation of a cookie.1440 * Internal representation of a single cookie. 1333 1441 * 1334 * Returned cookies are represented using this class, and when cookies are 1335 * set, if they are not already a WP_Http_Cookie() object, then they are turned 1336 * into one. 1442 * Returned cookies are represented using this class, and when cookies are set, if they are not 1443 * already a WP_Http_Cookie() object, then they are turned into one. 1337 1444 * 1445 * @todo The WordPress convention is to use underscores instead of camelCase for function and method 1446 * names. Need to switch to use underscores instead for the methods. 1447 * 1338 1448 * @package WordPress 1339 1449 * @subpackage HTTP 1450 * @since 2.8.0 1451 * @author Beau Lebens 1340 1452 */ 1341 1453 class WP_Http_Cookie { 1342 var $name, 1343 $value, 1344 $expires, 1345 $path, 1346 $domain; 1347 1454 1348 1455 /** 1349 * PHP4 style Constructor - Calls PHP5 Style Constructor 1456 * Cookie name. 1457 * 1458 * @since 2.8.0 1459 * @var string 1350 1460 */ 1461 var $name; 1462 1463 /** 1464 * Cookie value. 1465 * 1466 * @since 2.8.0 1467 * @var string 1468 */ 1469 var $value; 1470 1471 /** 1472 * When the cookie expires. 1473 * 1474 * @since 2.8.0 1475 * @var string 1476 */ 1477 var $expires; 1478 1479 /** 1480 * Cookie URL path. 1481 * 1482 * @since 2.8.0 1483 * @var string 1484 */ 1485 var $path; 1486 1487 /** 1488 * Cookie Domain. 1489 * 1490 * @since 2.8.0 1491 * @var string 1492 */ 1493 var $domain; 1494 1495 /** 1496 * PHP4 style Constructor - Calls PHP5 Style Constructor. 1497 * 1498 * @access public 1499 * @since 2.8.0 1500 * @param string|array $data Raw cookie data. 1501 */ 1351 1502 function WP_Http_Cookie( $data ) { 1352 return$this->__construct( $data );1503 $this->__construct( $data ); 1353 1504 } 1354 1505 1355 1506 /** 1356 1507 * Sets up this cookie object. 1357 1508 * 1509 * The parameter $data should be either an associative array containing the indices names below 1510 * or a header string detailing it. 1511 * 1512 * If it's an array, it should include the following elements: 1513 * <ol> 1514 * <li>Name</li> 1515 * <li>Value - should NOT be urlencoded already.</li> 1516 * <li>Expires - (optional) String or int (UNIX timestamp).</li> 1517 * <li>Path (optional)</li> 1518 * <li>Domain (optional)</li> 1519 * </ol> 1520 * 1358 1521 * @access public 1522 * @since 2.8.0 1359 1523 * 1360 * @param mixed $data Either an associative array describing the cookie, or a header-string detailing it. 1361 * If it's an array, it should include the following elements: 1362 * - name 1363 * - value [should NOT be urlencoded already] 1364 * - expires (optional) String or int (UNIX timestamp) 1365 * - path (optional) 1366 * - domain (optional) 1524 * @param string|array $data Raw cookie data. 1367 1525 */ 1368 1526 function __construct( $data ) { 1369 1527 if ( is_string( $data ) ) { 1370 1528 // Assume it's a header string direct from a previous request 1371 1529 $pairs = explode( ';', $data ); 1372 1530 1373 1531 // Special handling for first pair; name=value. Also be careful of "=" in value 1374 1532 $name = trim( substr( $pairs[0], 0, strpos( $pairs[0], '=' ) ) ); 1375 1533 $value = substr( $pairs[0], strpos( $pairs[0], '=' ) + 1 ); 1376 1534 $this->name = $name; 1377 1535 $this->value = urldecode( $value ); 1378 1536 array_shift( $pairs ); //Removes name=value from items. 1379 1537 1380 1538 // Set everything else as a property 1381 1539 foreach ( $pairs as $pair ) { 1382 1540 if ( empty($pair) ) //Handles the cookie ending in ; which results in a empty final pair 1383 1541 continue; 1542 1384 1543 list( $key, $val ) = explode( '=', $pair ); 1385 1544 $key = strtolower( trim( $key ) ); 1386 1545 if ( 'expires' == $key ) … … 1390 1549 } else { 1391 1550 if ( !isset( $data['name'] ) ) 1392 1551 return false; 1393 1552 1394 1553 // Set properties based directly on parameters 1395 1554 $this->name = $data['name']; 1396 1555 $this->value = isset( $data['value'] ) ? $data['value'] : ''; 1397 1556 $this->path = isset( $data['path'] ) ? $data['path'] : ''; 1398 1557 $this->domain = isset( $data['domain'] ) ? $data['domain'] : ''; 1558 1399 1559 if ( isset( $data['expires'] ) ) 1400 1560 $this->expires = is_int( $data['expires'] ) ? $data['expires'] : strtotime( $data['expires'] ); 1401 1561 else 1402 1562 $this->expires = null; 1403 1563 } 1404 1564 } 1405 1565 1406 1566 /** 1407 1567 * Confirms that it's OK to send this cookie to the URL checked against. 1408 1568 * 1409 1569 * Decision is based on RFC 2109/2965, so look there for details on validity. 1410 1570 * 1411 1571 * @access public 1572 * @since 2.8.0 1412 1573 * 1413 1574 * @param string $url URL you intend to send this cookie to 1414 1575 * @return boolean TRUE if allowed, FALSE otherwise. … … 1417 1578 // Expires - if expired then nothing else matters 1418 1579 if ( time() > $this->expires ) 1419 1580 return false; 1420 1581 1421 1582 // Get details on the URL we're thinking about sending to 1422 1583 $url = parse_url( $url ); 1423 1584 $url['port'] = isset( $url['port'] ) ? $url['port'] : 80; 1424 1585 $url['path'] = isset( $url['path'] ) ? $url['path'] : '/'; 1425 1426 1586 1587 // Values to use for comparison against the URL 1427 1588 $path = isset( $this->path ) ? $this->path : '/'; 1428 1589 $port = isset( $this->port ) ? $this->port : 80; 1429 1590 $domain = isset( $this->domain ) ? strtolower( $this->domain ) : strtolower( $url['host'] ); 1430 1591 if ( false === stripos( $domain, '.' ) ) 1431 1592 $domain .= '.local'; 1432 1593 1433 1594 // Host - very basic check that the request URL ends with the domain restriction (minus leading dot) 1434 1595 $domain = substr( $domain, 0, 1 ) == '.' ? substr( $domain, 1 ) : $domain; 1435 1596 if ( substr( $url['host'], -strlen( $domain ) ) != $domain ) 1436 1597 return false; 1437 1598 1438 1599 // Port - supports "port-lists" in the format: "80,8000,8080" 1439 1600 if ( !in_array( $url['port'], explode( ',', $port) ) ) 1440 1601 return false; 1441 1602 1442 1603 // Path - request path must start with path restriction 1443 1604 if ( substr( $url['path'], 0, strlen( $path ) ) != $path ) 1444 1605 return false; 1445 1606 1446 1607 return true; 1447 1608 } 1448 1609 1610 /** 1611 * Convert cookie name and value back to header string. 1612 * 1613 * @access public 1614 * @since 2.8.0 1615 * 1616 * @return string Header encoded cookie name and value. 1617 */ 1449 1618 function getHeaderValue() { 1450 1619 if ( empty( $this->name ) || empty( $this->value ) ) 1451 1620 return ''; 1452 1621 1453 1622 return $this->name . '=' . urlencode( $this->value ); 1454 1623 } 1455 1624 1625 /** 1626 * Retrieve cookie header for usage in the rest of the WordPress HTTP API. 1627 * 1628 * @access public 1629 * @since 2.8.0 1630 * 1631 * @return string 1632 */ 1456 1633 function getFullHeader() { 1457 1634 return 'Cookie: ' . $this->getHeaderValue(); 1458 1635 } 1459 1636 } 1460 1637 1461 1638 /** 1639 * Implementation for deflate and gzip transfer encodings. 1640 * 1641 * Includes RFC 1950, RFC 1951, and RFC 1952. 1642 * 1643 * @since 2.8 1644 * @package WordPress 1645 * @subpackage HTTP 1646 */ 1647 class WP_Http_Encoding { 1648 1649 /** 1650 * Compress raw string using the deflate format. 1651 * 1652 * Supports the RFC 1951 standard. 1653 * 1654 * @since 2.8 1655 * 1656 * @param string $raw String to compress. 1657 * @param int $level Optional, default is 9. Compression level, 9 is highest. 1658 * @param string $supports Optional, not used. When implemented it will choose the right compression based on what the server supports. 1659 * @return string|bool False on failure. 1660 */ 1661 function compress( $raw, $level = 9, $supports = null ) { 1662 return gzdeflate( $raw, $level ); 1663 } 1664 1665 /** 1666 * Decompression of deflated string. 1667 * 1668 * Will attempt to decompress using the RFC 1950 standard, and if that fails 1669 * then the RFC 1951 standard deflate will be attempted. Finally, the RFC 1670 * 1952 standard gzip decode will be attempted. If all fail, then the 1671 * original compressed string will be returned. 1672 * 1673 * @since 2.8 1674 * 1675 * @param string $compressed String to decompress. 1676 * @param int $length The optional length of the compressed data. 1677 * @return string|bool False on failure. 1678 */ 1679 function decompress( $compressed, $length = null ) { 1680 $decompressed = gzinflate( $compressed ); 1681 1682 if( false !== $decompressed ) 1683 return $decompressed; 1684 1685 $decompressed = gzuncompress( $compressed ); 1686 1687 if( false !== $decompressed ) 1688 return $decompressed; 1689 1690 $decompressed = gzdecode( $compressed ); 1691 1692 if( false !== $decompressed ) 1693 return $decompressed; 1694 1695 return $compressed; 1696 } 1697 1698 /** 1699 * What encoding types to accept and their priority values. 1700 * 1701 * @since 2.8 1702 * 1703 * @return string Types of encoding to accept. 1704 */ 1705 function accept_encoding() { 1706 $type = array(); 1707 if( function_exists( 'gzinflate' ) ) 1708 $type[] = 'deflate;q=1.0'; 1709 1710 if( function_exists( 'gzuncompress' ) ) 1711 $type[] = 'compress;q=0.5'; 1712 1713 if( function_exists( 'gzdecode' ) ) 1714 $type[] = 'gzip;q=0.5'; 1715 1716 return implode(', ', $type); 1717 } 1718 1719 /** 1720 * What enconding the content used when it was compressed to send in the headers. 1721 * 1722 * @since 2.8 1723 * 1724 * @return string Content-Encoding string to send in the header. 1725 */ 1726 function content_encoding() { 1727 return 'deflate'; 1728 } 1729 1730 /** 1731 * Whether the content be decoded based on the headers. 1732 * 1733 * @since 2.8 1734 * 1735 * @param array|string $headers All of the available headers. 1736 * @return bool 1737 */ 1738 function should_decode($headers) { 1739 if( is_array( $headers ) ) { 1740 if( array_key_exists('content-encoding', $headers) && ! empty( $headers['content-encoding'] ) ) 1741 return true; 1742 } else if( is_string( $headers ) ) { 1743 return ( stripos($headers, 'content-encoding:') !== false ); 1744 } 1745 1746 return false; 1747 } 1748 1749 /** 1750 * Whether decompression and compression are supported by the PHP version. 1751 * 1752 * Each function is tested instead of checking for the zlib extension, to 1753 * ensure that the functions all exist in the PHP version and aren't 1754 * disabled. 1755 * 1756 * @since 2.8 1757 * 1758 * @return bool 1759 */ 1760 function is_available() { 1761 return ( function_exists('gzuncompress') || function_exists('gzdeflate') || 1762 function_exists('gzinflate') ); 1763 } 1764 } 1765 1766 /** 1462 1767 * Returns the initialized WP_Http Object 1463 1768 * 1464 1769 * @since 2.7.0