121 |
121 |
122 /* |
122 /* |
123 * CURLOPT_TIMEOUT and CURLOPT_CONNECTTIMEOUT expect integers. Have to use ceil since. |
123 * CURLOPT_TIMEOUT and CURLOPT_CONNECTTIMEOUT expect integers. Have to use ceil since. |
124 * a value of 0 will allow an unlimited timeout. |
124 * a value of 0 will allow an unlimited timeout. |
125 */ |
125 */ |
126 $timeout = (int) ceil( $r['timeout'] ); |
126 $timeout = (int) ceil( $parsed_args['timeout'] ); |
127 curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, $timeout ); |
127 curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, $timeout ); |
128 curl_setopt( $handle, CURLOPT_TIMEOUT, $timeout ); |
128 curl_setopt( $handle, CURLOPT_TIMEOUT, $timeout ); |
129 |
129 |
130 curl_setopt( $handle, CURLOPT_URL, $url ); |
130 curl_setopt( $handle, CURLOPT_URL, $url ); |
131 curl_setopt( $handle, CURLOPT_RETURNTRANSFER, true ); |
131 curl_setopt( $handle, CURLOPT_RETURNTRANSFER, true ); |
132 curl_setopt( $handle, CURLOPT_SSL_VERIFYHOST, ( $ssl_verify === true ) ? 2 : false ); |
132 curl_setopt( $handle, CURLOPT_SSL_VERIFYHOST, ( true === $ssl_verify ) ? 2 : false ); |
133 curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, $ssl_verify ); |
133 curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, $ssl_verify ); |
134 |
134 |
135 if ( $ssl_verify ) { |
135 if ( $ssl_verify ) { |
136 curl_setopt( $handle, CURLOPT_CAINFO, $r['sslcertificates'] ); |
136 curl_setopt( $handle, CURLOPT_CAINFO, $parsed_args['sslcertificates'] ); |
137 } |
137 } |
138 |
138 |
139 curl_setopt( $handle, CURLOPT_USERAGENT, $r['user-agent'] ); |
139 curl_setopt( $handle, CURLOPT_USERAGENT, $parsed_args['user-agent'] ); |
140 |
140 |
141 /* |
141 /* |
142 * The option doesn't work with safe mode or when open_basedir is set, and there's |
142 * The option doesn't work with safe mode or when open_basedir is set, and there's |
143 * a bug #17490 with redirected POST requests, so handle redirections outside Curl. |
143 * a bug #17490 with redirected POST requests, so handle redirections outside Curl. |
144 */ |
144 */ |
145 curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, false ); |
145 curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, false ); |
146 if ( defined( 'CURLOPT_PROTOCOLS' ) ) { // PHP 5.2.10 / cURL 7.19.4 |
146 curl_setopt( $handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS ); |
147 curl_setopt( $handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS ); |
147 |
148 } |
148 switch ( $parsed_args['method'] ) { |
149 |
|
150 switch ( $r['method'] ) { |
|
151 case 'HEAD': |
149 case 'HEAD': |
152 curl_setopt( $handle, CURLOPT_NOBODY, true ); |
150 curl_setopt( $handle, CURLOPT_NOBODY, true ); |
153 break; |
151 break; |
154 case 'POST': |
152 case 'POST': |
155 curl_setopt( $handle, CURLOPT_POST, true ); |
153 curl_setopt( $handle, CURLOPT_POST, true ); |
156 curl_setopt( $handle, CURLOPT_POSTFIELDS, $r['body'] ); |
154 curl_setopt( $handle, CURLOPT_POSTFIELDS, $parsed_args['body'] ); |
157 break; |
155 break; |
158 case 'PUT': |
156 case 'PUT': |
159 curl_setopt( $handle, CURLOPT_CUSTOMREQUEST, 'PUT' ); |
157 curl_setopt( $handle, CURLOPT_CUSTOMREQUEST, 'PUT' ); |
160 curl_setopt( $handle, CURLOPT_POSTFIELDS, $r['body'] ); |
158 curl_setopt( $handle, CURLOPT_POSTFIELDS, $parsed_args['body'] ); |
161 break; |
159 break; |
162 default: |
160 default: |
163 curl_setopt( $handle, CURLOPT_CUSTOMREQUEST, $r['method'] ); |
161 curl_setopt( $handle, CURLOPT_CUSTOMREQUEST, $parsed_args['method'] ); |
164 if ( ! is_null( $r['body'] ) ) { |
162 if ( ! is_null( $parsed_args['body'] ) ) { |
165 curl_setopt( $handle, CURLOPT_POSTFIELDS, $r['body'] ); |
163 curl_setopt( $handle, CURLOPT_POSTFIELDS, $parsed_args['body'] ); |
166 } |
164 } |
167 break; |
165 break; |
168 } |
166 } |
169 |
167 |
170 if ( true === $r['blocking'] ) { |
168 if ( true === $parsed_args['blocking'] ) { |
171 curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( $this, 'stream_headers' ) ); |
169 curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( $this, 'stream_headers' ) ); |
172 curl_setopt( $handle, CURLOPT_WRITEFUNCTION, array( $this, 'stream_body' ) ); |
170 curl_setopt( $handle, CURLOPT_WRITEFUNCTION, array( $this, 'stream_body' ) ); |
173 } |
171 } |
174 |
172 |
175 curl_setopt( $handle, CURLOPT_HEADER, false ); |
173 curl_setopt( $handle, CURLOPT_HEADER, false ); |
176 |
174 |
177 if ( isset( $r['limit_response_size'] ) ) { |
175 if ( isset( $parsed_args['limit_response_size'] ) ) { |
178 $this->max_body_length = intval( $r['limit_response_size'] ); |
176 $this->max_body_length = intval( $parsed_args['limit_response_size'] ); |
179 } else { |
177 } else { |
180 $this->max_body_length = false; |
178 $this->max_body_length = false; |
181 } |
179 } |
182 |
180 |
183 // If streaming to a file open a file handle, and setup our curl streaming handler. |
181 // If streaming to a file open a file handle, and setup our curl streaming handler. |
184 if ( $r['stream'] ) { |
182 if ( $parsed_args['stream'] ) { |
185 if ( ! WP_DEBUG ) { |
183 if ( ! WP_DEBUG ) { |
186 $this->stream_handle = @fopen( $r['filename'], 'w+' ); |
184 $this->stream_handle = @fopen( $parsed_args['filename'], 'w+' ); |
187 } else { |
185 } else { |
188 $this->stream_handle = fopen( $r['filename'], 'w+' ); |
186 $this->stream_handle = fopen( $parsed_args['filename'], 'w+' ); |
189 } |
187 } |
190 if ( ! $this->stream_handle ) { |
188 if ( ! $this->stream_handle ) { |
191 return new WP_Error( |
189 return new WP_Error( |
192 'http_request_failed', |
190 'http_request_failed', |
193 sprintf( |
191 sprintf( |
194 /* translators: 1: fopen(), 2: file name */ |
192 /* translators: 1: fopen(), 2: File name. */ |
195 __( 'Could not open handle for %1$s to %2$s.' ), |
193 __( 'Could not open handle for %1$s to %2$s.' ), |
196 'fopen()', |
194 'fopen()', |
197 $r['filename'] |
195 $parsed_args['filename'] |
198 ) |
196 ) |
199 ); |
197 ); |
200 } |
198 } |
201 } else { |
199 } else { |
202 $this->stream_handle = false; |
200 $this->stream_handle = false; |
203 } |
201 } |
204 |
202 |
205 if ( ! empty( $r['headers'] ) ) { |
203 if ( ! empty( $parsed_args['headers'] ) ) { |
206 // cURL expects full header strings in each element. |
204 // cURL expects full header strings in each element. |
207 $headers = array(); |
205 $headers = array(); |
208 foreach ( $r['headers'] as $name => $value ) { |
206 foreach ( $parsed_args['headers'] as $name => $value ) { |
209 $headers[] = "{$name}: $value"; |
207 $headers[] = "{$name}: $value"; |
210 } |
208 } |
211 curl_setopt( $handle, CURLOPT_HTTPHEADER, $headers ); |
209 curl_setopt( $handle, CURLOPT_HTTPHEADER, $headers ); |
212 } |
210 } |
213 |
211 |
214 if ( $r['httpversion'] == '1.0' ) { |
212 if ( '1.0' === $parsed_args['httpversion'] ) { |
215 curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 ); |
213 curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 ); |
216 } else { |
214 } else { |
217 curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); |
215 curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); |
218 } |
216 } |
219 |
217 |
223 * Cookies are not currently handled by the HTTP API. This action allows |
221 * Cookies are not currently handled by the HTTP API. This action allows |
224 * plugins to handle cookies themselves. |
222 * plugins to handle cookies themselves. |
225 * |
223 * |
226 * @since 2.8.0 |
224 * @since 2.8.0 |
227 * |
225 * |
228 * @param resource $handle The cURL handle returned by curl_init() (passed by reference). |
226 * @param resource $handle The cURL handle returned by curl_init() (passed by reference). |
229 * @param array $r The HTTP request arguments. |
227 * @param array $parsed_args The HTTP request arguments. |
230 * @param string $url The request URL. |
228 * @param string $url The request URL. |
231 */ |
229 */ |
232 do_action_ref_array( 'http_api_curl', array( &$handle, $r, $url ) ); |
230 do_action_ref_array( 'http_api_curl', array( &$handle, $parsed_args, $url ) ); |
233 |
231 |
234 // We don't need to return the body, so don't. Just execute request and return. |
232 // We don't need to return the body, so don't. Just execute request and return. |
235 if ( ! $r['blocking'] ) { |
233 if ( ! $parsed_args['blocking'] ) { |
236 curl_exec( $handle ); |
234 curl_exec( $handle ); |
237 |
235 |
238 if ( $curl_error = curl_error( $handle ) ) { |
236 $curl_error = curl_error( $handle ); |
|
237 if ( $curl_error ) { |
239 curl_close( $handle ); |
238 curl_close( $handle ); |
240 return new WP_Error( 'http_request_failed', $curl_error ); |
239 return new WP_Error( 'http_request_failed', $curl_error ); |
241 } |
240 } |
242 if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array( 301, 302 ) ) ) { |
241 if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array( 301, 302 ), true ) ) { |
243 curl_close( $handle ); |
242 curl_close( $handle ); |
244 return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); |
243 return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); |
245 } |
244 } |
246 |
245 |
247 curl_close( $handle ); |
246 curl_close( $handle ); |
269 |
268 |
270 // If an error occurred, or, no response. |
269 // If an error occurred, or, no response. |
271 if ( $curl_error || ( 0 == strlen( $theBody ) && empty( $theHeaders['headers'] ) ) ) { |
270 if ( $curl_error || ( 0 == strlen( $theBody ) && empty( $theHeaders['headers'] ) ) ) { |
272 if ( CURLE_WRITE_ERROR /* 23 */ == $curl_error ) { |
271 if ( CURLE_WRITE_ERROR /* 23 */ == $curl_error ) { |
273 if ( ! $this->max_body_length || $this->max_body_length != $bytes_written_total ) { |
272 if ( ! $this->max_body_length || $this->max_body_length != $bytes_written_total ) { |
274 if ( $r['stream'] ) { |
273 if ( $parsed_args['stream'] ) { |
275 curl_close( $handle ); |
274 curl_close( $handle ); |
276 fclose( $this->stream_handle ); |
275 fclose( $this->stream_handle ); |
277 return new WP_Error( 'http_request_failed', __( 'Failed to write request to temporary file.' ) ); |
276 return new WP_Error( 'http_request_failed', __( 'Failed to write request to temporary file.' ) ); |
278 } else { |
277 } else { |
279 curl_close( $handle ); |
278 curl_close( $handle ); |
280 return new WP_Error( 'http_request_failed', curl_error( $handle ) ); |
279 return new WP_Error( 'http_request_failed', curl_error( $handle ) ); |
281 } |
280 } |
282 } |
281 } |
283 } else { |
282 } else { |
284 if ( $curl_error = curl_error( $handle ) ) { |
283 $curl_error = curl_error( $handle ); |
|
284 if ( $curl_error ) { |
285 curl_close( $handle ); |
285 curl_close( $handle ); |
286 return new WP_Error( 'http_request_failed', $curl_error ); |
286 return new WP_Error( 'http_request_failed', $curl_error ); |
287 } |
287 } |
288 } |
288 } |
289 if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array( 301, 302 ) ) ) { |
289 if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array( 301, 302 ), true ) ) { |
290 curl_close( $handle ); |
290 curl_close( $handle ); |
291 return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); |
291 return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); |
292 } |
292 } |
293 } |
293 } |
294 |
294 |
295 curl_close( $handle ); |
295 curl_close( $handle ); |
296 |
296 |
297 if ( $r['stream'] ) { |
297 if ( $parsed_args['stream'] ) { |
298 fclose( $this->stream_handle ); |
298 fclose( $this->stream_handle ); |
299 } |
299 } |
300 |
300 |
301 $response = array( |
301 $response = array( |
302 'headers' => $theHeaders['headers'], |
302 'headers' => $theHeaders['headers'], |
303 'body' => null, |
303 'body' => null, |
304 'response' => $theHeaders['response'], |
304 'response' => $theHeaders['response'], |
305 'cookies' => $theHeaders['cookies'], |
305 'cookies' => $theHeaders['cookies'], |
306 'filename' => $r['filename'], |
306 'filename' => $parsed_args['filename'], |
307 ); |
307 ); |
308 |
308 |
309 // Handle redirects. |
309 // Handle redirects. |
310 if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) ) { |
310 $redirect_response = WP_HTTP::handle_redirects( $url, $parsed_args, $response ); |
|
311 if ( false !== $redirect_response ) { |
311 return $redirect_response; |
312 return $redirect_response; |
312 } |
313 } |
313 |
314 |
314 if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode( $theHeaders['headers'] ) ) { |
315 if ( true === $parsed_args['decompress'] && true === WP_Http_Encoding::should_decode( $theHeaders['headers'] ) ) { |
315 $theBody = WP_Http_Encoding::decompress( $theBody ); |
316 $theBody = WP_Http_Encoding::decompress( $theBody ); |
316 } |
317 } |
317 |
318 |
318 $response['body'] = $theBody; |
319 $response['body'] = $theBody; |
319 |
320 |