Changeset 25224 for trunk/src/wp-includes/class-http.php
- Timestamp:
- 09/04/2013 04:48:21 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/class-http.php
r25222 r25224 82 82 'decompress' => true, 83 83 'sslverify' => true, 84 'sslcertificates' => ABSPATH . WPINC . '/certificates/ca-bundle.crt', 84 85 'stream' => false, 85 86 'filename' => null, … … 215 216 */ 216 217 public function _get_first_available_transport( $args, $url = null ) { 217 $request_order = apply_filters( 'http_api_transports', array( 'curl', 'streams', 'fsockopen' ), $args, $url );218 $request_order = apply_filters( 'http_api_transports', array( 'streams' ), $args, $url ); 218 219 219 220 // Loop over each transport on each HTTP request looking for one which will serve this request's needs … … 237 238 * Also caches the transport instance to be used later. 238 239 * 239 * The order for blocking requests is cURL, Streams, and finally Fsockopen. 240 * The order for non-blocking requests is cURL, Streams and Fsockopen(). 240 * The order for requests is cURL, and then PHP Streams. 241 241 * 242 242 * @since 3.2.0 … … 633 633 return wp_remote_request( $redirect_location, $args ); 634 634 } 635 636 /** 637 * Determines if a specified string represents an IP address or not. 638 * 639 * This function also detects the type of the IP address, returning either 640 * '4' or '6' to represent a IPv4 and IPv6 address respectively. 641 * This does not verify if the IP is a valid IP, only that it appears to be 642 * an IP address. 643 * 644 * @see http://home.deds.nl/~aeron/regex/ for IPv6 regex 645 * 646 * @since 3.7.0 647 * @static 648 * 649 * @param string $maybe_ip A suspected IP address 650 * @return integer|bool Upon success, '4' or '6' to represent a IPv4 or IPv6 address, false upon failure 651 */ 652 static function is_ip_address( $maybe_ip ) { 653 if ( preg_match( '/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $maybe_ip ) ) 654 return 4; 655 656 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, ' []' ) ) ) 657 return 6; 658 659 return false; 660 } 661 635 662 } 636 663 637 664 /** 638 * HTTP request method uses fsockopen function to retrieve the url. 639 * 640 * This would be the preferred method, but the fsockopen implementation has the most overhead of all 641 * the HTTP transport implementations. 665 * HTTP request method uses PHP Streams to retrieve the url. 642 666 * 643 667 * @package WordPress 644 668 * @subpackage HTTP 645 * @since 2.7.0669 * @since 3.7.0 646 670 */ 647 class WP_Http_Fsockopen { 648 /** 649 * Send a HTTP request to a URI using fsockopen(). 650 * 651 * Does not support non-blocking mode. 671 class WP_Http_Streams { 672 /** 673 * Send a HTTP request to a URI using PHP Streams. 652 674 * 653 675 * @see WP_Http::request For default options descriptions. 654 676 * 655 * @since 2.7677 * @since 3.7.0 656 678 * @access public 657 679 * @param string $url URI resource. 658 * @param str |array $args Optional. Override the defaults.680 * @param string|array $args Optional. Override the defaults. 659 681 * @return array 'headers', 'body', 'response', 'cookies' and 'filename' keys. 660 682 */ … … 680 702 WP_Http::buildCookieHeader( $r ); 681 703 682 $iError = null; // Store error number683 $strError = null; // Store error string684 685 704 $arrURL = parse_url($url); 686 705 687 $fsockopen_host = $arrURL['host']; 688 689 $secure_transport = false; 690 706 $connect_host = $arrURL['host']; 707 708 $secure_transport = ( $arrURL['scheme'] == 'ssl' || $arrURL['scheme'] == 'https' ); 691 709 if ( ! isset( $arrURL['port'] ) ) { 692 if ( ( $arrURL['scheme'] == 'ssl' || $arrURL['scheme'] == 'https' ) && extension_loaded('openssl') ) { 693 $fsockopen_host = "ssl://$fsockopen_host"; 710 if ( $arrURL['scheme'] == 'ssl' || $arrURL['scheme'] == 'https' ) { 694 711 $arrURL['port'] = 443; 695 712 $secure_transport = true; … … 707 724 } 708 725 709 // fsockopen has issues with 'localhost' with IPv6 with certain versions of PHP, It attempts to connect to ::1,726 // Certain versions of PHP have issues with 'localhost' and IPv6, It attempts to connect to ::1, 710 727 // which fails when the server is not set up for it. For compatibility, always connect to the IPv4 address. 711 if ( 'localhost' == strtolower($fsockopen_host) ) 712 $fsockopen_host = '127.0.0.1'; 713 714 // There are issues with the HTTPS and SSL protocols that cause errors that can be safely 715 // ignored and should be ignored. 716 if ( true === $secure_transport ) 717 $error_reporting = error_reporting(0); 718 719 $startDelay = time(); 728 if ( 'localhost' == strtolower( $connect_host ) ) 729 $connect_host = '127.0.0.1'; 730 731 $connect_host = $secure_transport ? 'ssl://' . $connect_host : 'tcp://' . $connect_host; 732 733 $is_local = isset( $r['local'] ) && $r['local']; 734 $ssl_verify = isset( $r['sslverify'] ) && $r['sslverify']; 735 if ( $is_local ) 736 $ssl_verify = apply_filters( 'https_local_ssl_verify', $ssl_verify ); 737 elseif ( ! $is_local ) 738 $ssl_verify = apply_filters( 'https_ssl_verify', $ssl_verify ); 720 739 721 740 $proxy = new WP_HTTP_Proxy(); 722 741 742 $context = stream_context_create( array( 743 'ssl' => array( 744 'verify_peer' => $ssl_verify, 745 //'CN_match' => $arrURL['host'], // This is handled by self::verify_ssl_certficate() 746 'capture_peer_cert' => $ssl_verify, 747 'SNI_enabled' => true, 748 'cafile' => $r['sslcertificates'], 749 'allow_self_signed' => ! $ssl_verify, 750 ) 751 ) ); 752 753 $timeout = (int) floor( $r['timeout'] ); 754 $utimeout = $timeout == $r['timeout'] ? 0 : 1000000 * $r['timeout'] % 1000000; 755 $connect_timeout = max( $timeout, 1 ); 756 757 $connection_error = null; // Store error number 758 $connection_error_str = null; // Store error string 759 723 760 if ( !WP_DEBUG ) { 761 // In the event that the SSL connection fails, silence the many PHP Warnings 762 if ( $secure_transport ) 763 $error_reporting = error_reporting(0); 764 724 765 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) 725 $handle = @ fsockopen( $proxy->host(), $proxy->port(), $iError, $strError, $r['timeout']);766 $handle = @stream_socket_client( 'tcp://' . $proxy->host() . ':' . $proxy->port(), $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); 726 767 else 727 $handle = @fsockopen( $fsockopen_host, $arrURL['port'], $iError, $strError, $r['timeout'] ); 768 $handle = @stream_socket_client( $connect_host . ':' . $arrURL['port'], $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); 769 770 if ( $secure_transport ) 771 error_reporting( $error_reporting ); 772 728 773 } else { 729 774 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) 730 $handle = fsockopen( $proxy->host(), $proxy->port(), $iError, $strError, $r['timeout']);775 $handle = stream_socket_client( 'tcp://' . $proxy->host() . ':' . $proxy->port(), $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); 731 776 else 732 $handle = fsockopen( $fsockopen_host, $arrURL['port'], $iError, $strError, $r['timeout'] ); 733 } 734 735 $endDelay = time(); 736 737 // If the delay is greater than the timeout then fsockopen shouldn't be used, because it will 738 // cause a long delay. 739 $elapseDelay = ($endDelay-$startDelay) > $r['timeout']; 740 if ( true === $elapseDelay ) 741 add_option( 'disable_fsockopen', $endDelay, null, true ); 742 743 if ( false === $handle ) 744 return new WP_Error('http_request_failed', $iError . ': ' . $strError); 745 746 $timeout = (int) floor( $r['timeout'] ); 747 $utimeout = $timeout == $r['timeout'] ? 0 : 1000000 * $r['timeout'] % 1000000; 777 $handle = stream_socket_client( $connect_host . ':' . $arrURL['port'], $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); 778 } 779 780 if ( false === $handle ) { 781 // SSL connection failed due to expired/invalid cert, or, OpenSSL configuration is broken 782 if ( $secure_transport && 0 === $connection_error && '' === $connection_error_str ) 783 return new WP_Error( 'http_request_failed', __( 'The SSL Certificate for the host could not be verified.' ) ); 784 785 return new WP_Error('http_request_failed', $connection_error . ': ' . $connection_error_str ); 786 } 787 788 // Verify that the SSL certificate is valid for this request 789 if ( $secure_transport && $ssl_verify && ! $proxy->is_enabled() ) { 790 if ( ! self::verify_ssl_certficate( $handle, $arrURL['host'] ) ) 791 return new WP_Error( 'http_request_failed', __( 'The SSL Certificate for the host could not be verified.' ) ); 792 } 793 748 794 stream_set_timeout( $handle, $timeout, $utimeout ); 749 795 … … 784 830 785 831 if ( ! $r['blocking'] ) { 786 fclose($handle); 832 stream_set_blocking( $handle, 0 ); 833 fclose( $handle ); 787 834 return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() ); 788 835 } … … 847 894 fclose( $handle ); 848 895 849 if ( true === $secure_transport )850 error_reporting($error_reporting);851 852 896 $arrHeaders = WP_Http::processHeaders( $process['headers'], $url ); 853 897 … … 880 924 881 925 /** 926 * Verifies the received SSL certificate against it's Common Names and subjectAltName fields 927 * 928 * PHP's SSL verifications only verify that it's a valid Certificate, it doesn't verify if 929 * the certificate is valid for the hostname which was requested. 930 * This function verifies the requested hostname against certificate's subjectAltName field, 931 * if that is empty, or contains no DNS entries, a fallback to the Common Name field is used. 932 * 933 * IP Address support is included if the request is being made to an IP address. 934 * 935 * @since 3.7.0 936 * @static 937 * 938 * @param stream $stream The PHP Stream which the SSL request is being made over 939 * @param string $host The hostname being requested 940 * @return bool If the cerficiate presented in $stream is valid for $host 941 */ 942 static function verify_ssl_certficate( $stream, $host ) { 943 $context_options = stream_context_get_options( $stream ); 944 945 if ( empty( $context_options['ssl']['peer_certificate'] ) ) 946 return false; 947 948 $cert = openssl_x509_parse( $context_options['ssl']['peer_certificate'] ); 949 if ( ! $cert ) 950 return false; 951 952 // If the request is being made to an IP address, we'll validate against IP fields in the cert (if they exist) 953 $host_type = ( WP_HTTP::is_ip_address( $host ) ? 'ip' : 'dns' ); 954 955 $certificate_hostnames = array(); 956 if ( ! empty( $cert['extensions']['subjectAltName'] ) ) { 957 $match_against = preg_split( '/,\s*/', $cert['extensions']['subjectAltName'] ); 958 foreach ( $match_against as $match ) { 959 list( $match_type, $match_host ) = explode( ':', $match ); 960 if ( $host_type == strtolower( trim( $match_type ) ) ) // IP: or DNS: 961 $certificate_hostnames[] = strtolower( trim( $match_host ) ); 962 } 963 } elseif ( !empty( $cert['subject']['CN'] ) ) { 964 // Only use the CN when the certificate includes no subjectAltName extension 965 $certificate_hostnames[] = strtolower( $cert['subject']['CN'] ); 966 } 967 968 // Exact hostname/IP matches 969 if ( in_array( strtolower( $host ), $certificate_hostnames ) ) 970 return true; 971 972 // IP's can't be wildcards, Stop processing 973 if ( 'ip' == $host_type ) 974 return false; 975 976 // Test to see if the domain is at least 2 deep for wildcard support 977 if ( substr_count( $host, '.' ) < 2 ) 978 return false; 979 980 // Wildcard subdomains certs (*.example.com) are valid for a.example.com but not a.b.example.com 981 $wildcard_host = preg_replace( '/^[^.]+\./', '*.', $host ); 982 983 return in_array( strtolower( $wildcard_host ), $certificate_hostnames ); 984 } 985 986 /** 882 987 * Whether this class can be used for retrieving an URL. 883 988 * 884 * @since 2.7.0885 989 * @static 990 * @access public 991 * @since 3.7.0 992 * 886 993 * @return boolean False means this class can not be used, true means it can. 887 994 */ 888 995 public static function test( $args = array() ) { 889 if ( ! function_exists( ' fsockopen' ) )996 if ( ! function_exists( 'stream_socket_client' ) ) 890 997 return false; 891 998 892 if ( false !== ( $option = get_option( 'disable_fsockopen' ) ) && time() - $option < 12 * HOUR_IN_SECONDS )893 return false;894 895 999 $is_ssl = isset( $args['ssl'] ) && $args['ssl']; 896 1000 897 if ( $is_ssl && ! extension_loaded( 'openssl' ) ) 898 return false; 899 900 return apply_filters( 'use_fsockopen_transport', true, $args ); 1001 if ( $is_ssl ) { 1002 if ( ! extension_loaded( 'openssl' ) ) 1003 return false; 1004 if ( ! function_exists( 'openssl_x509_parse' ) ) 1005 return false; 1006 } 1007 1008 return apply_filters( 'use_streams_transport', true, $args ); 901 1009 } 902 1010 } 903 1011 904 1012 /** 905 * HTTP request method uses Streams to retrieve the url. 906 * 907 * Requires PHP 5.0+ and uses fopen with stream context. Requires that 'allow_url_fopen' PHP setting 908 * to be enabled. 909 * 910 * Second preferred method for getting the URL, for PHP 5. 1013 * Deprecated HTTP Transport method which used fsockopen. 1014 * This class is not used, and is included for backwards compatibility only. 1015 * All code should make use of WP_HTTP directly through it's API. 1016 * 1017 * @see WP_HTTP::request 1018 * 1019 * @package WordPress 1020 * @subpackage HTTP 1021 * @since 3.7.0 1022 */ 1023 class WP_HTTP_Fsockopen extends WP_HTTP_Streams { 1024 // For backwards compatibility for users who are using the class directly 1025 } 1026 1027 /** 1028 * HTTP request method uses Curl extension to retrieve the url. 1029 * 1030 * Requires the Curl extension to be installed. 911 1031 * 912 1032 * @package WordPress … … 914 1034 * @since 2.7.0 915 1035 */ 916 class WP_Http_Streams { 917 /** 918 * Send a HTTP request to a URI using streams with fopen(). 1036 class WP_Http_Curl { 1037 1038 /** 1039 * Temporary header storage for during requests. 1040 * 1041 * @since 3.2.0 1042 * @access private 1043 * @var string 1044 */ 1045 private $headers = ''; 1046 1047 /** 1048 * Temporary body storage for during requests. 1049 * 1050 * @since 3.6.0 1051 * @access private 1052 * @var string 1053 */ 1054 private $body = ''; 1055 1056 /** 1057 * The maximum amount of data to recieve from the remote server 1058 * 1059 * @since 3.6.0 1060 * @access private 1061 * @var int 1062 */ 1063 private $max_body_length = false; 1064 1065 /** 1066 * The file resource used for streaming to file. 1067 * 1068 * @since 3.6.0 1069 * @access private 1070 * @var resource 1071 */ 1072 private $stream_handle = false; 1073 1074 /** 1075 * Send a HTTP request to a URI using cURL extension. 919 1076 * 920 1077 * @access public … … 943 1100 } 944 1101 945 // Construct Cookie: header if any cookies are set946 WP_Http::buildCookieHeader( $r );947 948 $arrURL = parse_url($url);949 950 if ( false === $arrURL )951 return new WP_Error('http_request_failed', sprintf(__('Malformed URL: %s'), $url));952 953 if ( 'http' != $arrURL['scheme'] && 'https' != $arrURL['scheme'] )954 $url = preg_replace('|^' . preg_quote($arrURL['scheme'], '|') . '|', 'http', $url);955 956 // Convert Header array to string.957 $strHeaders = '';958 if ( is_array( $r['headers'] ) )959 foreach ( $r['headers'] as $name => $value )960 $strHeaders .= "{$name}: $value\r\n";961 else if ( is_string( $r['headers'] ) )962 $strHeaders = $r['headers'];963 964 $is_local = isset($args['local']) && $args['local'];965 $ssl_verify = isset($args['sslverify']) && $args['sslverify'];966 if ( $is_local )967 $ssl_verify = apply_filters('https_local_ssl_verify', $ssl_verify);968 elseif ( ! $is_local )969 $ssl_verify = apply_filters('https_ssl_verify', $ssl_verify);970 971 $arrContext = array('http' =>972 array(973 'method' => strtoupper($r['method']),974 'user_agent' => $r['user-agent'],975 'max_redirects' => 0, // Follow no redirects976 'follow_redirects' => false,977 'protocol_version' => (float) $r['httpversion'],978 'header' => $strHeaders,979 'ignore_errors' => true, // Return non-200 requests.980 'timeout' => $r['timeout'],981 'ssl' => array(982 'verify_peer' => $ssl_verify,983 'verify_host' => $ssl_verify984 )985 )986 );987 988 $proxy = new WP_HTTP_Proxy();989 990 if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {991 $arrContext['http']['proxy'] = 'tcp://' . $proxy->host() . ':' . $proxy->port();992 $arrContext['http']['request_fulluri'] = true;993 994 // We only support Basic authentication so this will only work if that is what your proxy supports.995 if ( $proxy->use_authentication() )996 $arrContext['http']['header'] .= $proxy->authentication_header() . "\r\n";997 }998 999 if ( ! is_null( $r['body'] ) )1000 $arrContext['http']['content'] = $r['body'];1001 1002 $context = stream_context_create($arrContext);1003 1004 if ( !WP_DEBUG )1005 $handle = @fopen($url, 'r', false, $context);1006 else1007 $handle = fopen($url, 'r', false, $context);1008 1009 if ( ! $handle )1010 return new WP_Error('http_request_failed', sprintf(__('Could not open handle for fopen() to %s'), $url));1011 1012 $timeout = (int) floor( $r['timeout'] );1013 $utimeout = $timeout == $r['timeout'] ? 0 : 1000000 * $r['timeout'] % 1000000;1014 stream_set_timeout( $handle, $timeout, $utimeout );1015 1016 if ( ! $r['blocking'] ) {1017 stream_set_blocking($handle, 0);1018 fclose($handle);1019 return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() );1020 }1021 1022 $max_bytes = isset( $r['limit_response_size'] ) ? intval( $r['limit_response_size'] ) : -1;1023 if ( $r['stream'] ) {1024 if ( ! WP_DEBUG )1025 $stream_handle = @fopen( $r['filename'], 'w+' );1026 else1027 $stream_handle = fopen( $r['filename'], 'w+' );1028 1029 if ( ! $stream_handle )1030 return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) );1031 1032 stream_copy_to_stream( $handle, $stream_handle, $max_bytes );1033 1034 fclose( $stream_handle );1035 $strResponse = '';1036 } else {1037 $strResponse = stream_get_contents( $handle, $max_bytes );1038 }1039 1040 $meta = stream_get_meta_data( $handle );1041 1042 fclose( $handle );1043 1044 $processedHeaders = array();1045 if ( isset( $meta['wrapper_data']['headers'] ) )1046 $processedHeaders = WP_Http::processHeaders( $meta['wrapper_data']['headers'], $url );1047 else1048 $processedHeaders = WP_Http::processHeaders( $meta['wrapper_data'], $url );1049 1050 $response = array(1051 'headers' => $processedHeaders['headers'],1052 'body' => null,1053 'response' => $processedHeaders['response'],1054 'cookies' => $processedHeaders['cookies'],1055 'filename' => $r['filename']1056 );1057 1058 // Handle redirects1059 if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) )1060 return $redirect_response;1061 1062 if ( ! empty( $strResponse ) && isset( $processedHeaders['headers']['transfer-encoding'] ) && 'chunked' == $processedHeaders['headers']['transfer-encoding'] )1063 $strResponse = WP_Http::chunkTransferDecode($strResponse);1064 1065 if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($processedHeaders['headers']) )1066 $strResponse = WP_Http_Encoding::decompress( $strResponse );1067 1068 $response['body'] = $strResponse;1069 1070 return $response;1071 }1072 1073 /**1074 * Whether this class can be used for retrieving an URL.1075 *1076 * @static1077 * @access public1078 * @since 2.7.01079 *1080 * @return boolean False means this class can not be used, true means it can.1081 */1082 public static function test( $args = array() ) {1083 if ( ! function_exists( 'fopen' ) )1084 return false;1085 1086 if ( ! function_exists( 'ini_get' ) || true != ini_get( 'allow_url_fopen' ) )1087 return false;1088 1089 $is_ssl = isset( $args['ssl'] ) && $args['ssl'];1090 1091 if ( $is_ssl && ! extension_loaded( 'openssl' ) )1092 return false;1093 1094 return apply_filters( 'use_streams_transport', true, $args );1095 }1096 }1097 1098 /**1099 * HTTP request method uses Curl extension to retrieve the url.1100 *1101 * Requires the Curl extension to be installed.1102 *1103 * @package WordPress1104 * @subpackage HTTP1105 * @since 2.71106 */1107 class WP_Http_Curl {1108 1109 /**1110 * Temporary header storage for during requests.1111 *1112 * @since 3.2.01113 * @access private1114 * @var string1115 */1116 private $headers = '';1117 1118 /**1119 * Temporary body storage for during requests.1120 *1121 * @since 3.6.01122 * @access private1123 * @var string1124 */1125 private $body = '';1126 1127 /**1128 * The maximum amount of data to recieve from the remote server1129 *1130 * @since 3.6.01131 * @access private1132 * @var int1133 */1134 private $max_body_length = false;1135 1136 /**1137 * The file resource used for streaming to file.1138 *1139 * @since 3.6.01140 * @access private1141 * @var resource1142 */1143 private $stream_handle = false;1144 1145 /**1146 * Send a HTTP request to a URI using cURL extension.1147 *1148 * @access public1149 * @since 2.7.01150 *1151 * @param string $url1152 * @param str|array $args Optional. Override the defaults.1153 * @return array 'headers', 'body', 'response', 'cookies' and 'filename' keys.1154 */1155 function request($url, $args = array()) {1156 $defaults = array(1157 'method' => 'GET', 'timeout' => 5,1158 'redirection' => 5, 'httpversion' => '1.0',1159 'blocking' => true,1160 'headers' => array(), 'body' => null, 'cookies' => array()1161 );1162 1163 $r = wp_parse_args( $args, $defaults );1164 1165 if ( isset($r['headers']['User-Agent']) ) {1166 $r['user-agent'] = $r['headers']['User-Agent'];1167 unset($r['headers']['User-Agent']);1168 } else if ( isset($r['headers']['user-agent']) ) {1169 $r['user-agent'] = $r['headers']['user-agent'];1170 unset($r['headers']['user-agent']);1171 }1172 1173 1102 // Construct Cookie: header if any cookies are set. 1174 1103 WP_Http::buildCookieHeader( $r ); … … 1208 1137 curl_setopt( $handle, CURLOPT_SSL_VERIFYHOST, ( $ssl_verify === true ) ? 2 : false ); 1209 1138 curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, $ssl_verify ); 1139 curl_setopt( $handle, CURLOPT_CAINFO, $r['sslcertificates'] ); 1210 1140 curl_setopt( $handle, CURLOPT_USERAGENT, $r['user-agent'] ); 1211 1141 // The option doesn't work with safe mode or when open_basedir is set, and there's a
Note: See TracChangeset
for help on using the changeset viewer.