1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Author: Sterling Hughes <sterling@php.net> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: interface.c 289934 2009-10-26 12:57:01Z iliaa $ */
20 :
21 : #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
22 :
23 : #ifdef HAVE_CONFIG_H
24 : #include "config.h"
25 : #endif
26 :
27 : #include "php.h"
28 :
29 : #if HAVE_CURL
30 :
31 : #include <stdio.h>
32 : #include <string.h>
33 :
34 : #ifdef PHP_WIN32
35 : #include <winsock2.h>
36 : #include <sys/types.h>
37 : #endif
38 :
39 : #include <curl/curl.h>
40 : #include <curl/easy.h>
41 :
42 : /* As of curl 7.11.1 this is no longer defined inside curl.h */
43 : #ifndef HttpPost
44 : #define HttpPost curl_httppost
45 : #endif
46 :
47 : /* {{{ cruft for thread safe SSL crypto locks */
48 : #if defined(ZTS) && defined(HAVE_CURL_SSL)
49 : # ifdef PHP_WIN32
50 : # define PHP_CURL_NEED_OPENSSL_TSL
51 : # include <openssl/crypto.h>
52 : # else /* !PHP_WIN32 */
53 : # if defined(HAVE_CURL_OPENSSL)
54 : # if defined(HAVE_OPENSSL_CRYPTO_H)
55 : # define PHP_CURL_NEED_OPENSSL_TSL
56 : # include <openssl/crypto.h>
57 : # else
58 : # warning \
59 : "libcurl was compiled with OpenSSL support, but configure could not find " \
60 : "openssl/crypto.h; thus no SSL crypto locking callbacks will be set, which may " \
61 : "cause random crashes on SSL requests"
62 : # endif
63 : # elif defined(HAVE_CURL_GNUTLS)
64 : # if defined(HAVE_GCRYPT_H)
65 : # define PHP_CURL_NEED_GNUTLS_TSL
66 : # include <gcrypt.h>
67 : # else
68 : # warning \
69 : "libcurl was compiled with GnuTLS support, but configure could not find " \
70 : "gcrypt.h; thus no SSL crypto locking callbacks will be set, which may " \
71 : "cause random crashes on SSL requests"
72 : # endif
73 : # else
74 : # warning \
75 : "libcurl was compiled with SSL support, but configure could not determine which" \
76 : "library was used; thus no SSL crypto locking callbacks will be set, which may " \
77 : "cause random crashes on SSL requests"
78 : # endif /* HAVE_CURL_OPENSSL || HAVE_CURL_GNUTLS */
79 : # endif /* PHP_WIN32 */
80 : #endif /* ZTS && HAVE_CURL_SSL */
81 : /* }}} */
82 :
83 : #define SMART_STR_PREALLOC 4096
84 :
85 : #include "ext/standard/php_smart_str.h"
86 : #include "ext/standard/info.h"
87 : #include "ext/standard/file.h"
88 : #include "ext/standard/url.h"
89 : #include "php_curl.h"
90 :
91 : int le_curl;
92 : int le_curl_multi_handle;
93 :
94 : #ifdef PHP_CURL_NEED_OPENSSL_TSL /* {{{ */
95 : static MUTEX_T *php_curl_openssl_tsl = NULL;
96 :
97 : static void php_curl_ssl_lock(int mode, int n, const char * file, int line)
98 : {
99 : if (mode & CRYPTO_LOCK) {
100 : tsrm_mutex_lock(php_curl_openssl_tsl[n]);
101 : } else {
102 : tsrm_mutex_unlock(php_curl_openssl_tsl[n]);
103 : }
104 : }
105 :
106 : static unsigned long php_curl_ssl_id(void)
107 : {
108 : return (unsigned long) tsrm_thread_id();
109 : }
110 : #endif
111 : /* }}} */
112 :
113 : #ifdef PHP_CURL_NEED_GNUTLS_TSL /* {{{ */
114 : static int php_curl_ssl_mutex_create(void **m)
115 : {
116 : if (*((MUTEX_T *) m) = tsrm_mutex_alloc()) {
117 : return SUCCESS;
118 : } else {
119 : return FAILURE;
120 : }
121 : }
122 :
123 : static int php_curl_ssl_mutex_destroy(void **m)
124 : {
125 : tsrm_mutex_free(*((MUTEX_T *) m));
126 : return SUCCESS;
127 : }
128 :
129 : static int php_curl_ssl_mutex_lock(void **m)
130 : {
131 : return tsrm_mutex_lock(*((MUTEX_T *) m));
132 : }
133 :
134 : static int php_curl_ssl_mutex_unlock(void **m)
135 : {
136 : return tsrm_mutex_unlock(*((MUTEX_T *) m));
137 : }
138 :
139 : static struct gcry_thread_cbs php_curl_gnutls_tsl = {
140 : GCRY_THREAD_OPTION_USER,
141 : NULL,
142 : php_curl_ssl_mutex_create,
143 : php_curl_ssl_mutex_destroy,
144 : php_curl_ssl_mutex_lock,
145 : php_curl_ssl_mutex_unlock
146 : };
147 : #endif
148 : /* }}} */
149 :
150 : static void _php_curl_close_ex(php_curl *ch TSRMLS_DC);
151 : static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC);
152 :
153 : #define SAVE_CURL_ERROR(__handle, __err) (__handle)->err.no = (int) __err;
154 :
155 : #define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s), (long) v);
156 : #define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s), (double) v);
157 : #define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s), (char *) (v ? v : ""), 1);
158 : #define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s), (zval *) v);
159 :
160 : #if defined(PHP_WIN32) || defined(__GNUC__)
161 : # define php_curl_ret(__ret) RETVAL_FALSE; return __ret;
162 : #else
163 : # define php_curl_ret(__ret) RETVAL_FALSE; return;
164 : #endif
165 :
166 : static int php_curl_option_url(php_curl *ch, const char *url, const int len) /* {{{ */
167 59 : {
168 59 : CURLcode error = CURLE_OK;
169 : #if LIBCURL_VERSION_NUM < 0x071100
170 59 : char *copystr = NULL;
171 : #endif
172 : TSRMLS_FETCH();
173 :
174 : /* Disable file:// if open_basedir or safe_mode are used */
175 59 : if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
176 : #if LIBCURL_VERSION_NUM >= 0x071304
177 : error = curl_easy_setopt(ch->cp, CURLOPT_PROTOCOLS, CURLPROTO_ALL & ~CURLPROTO_FILE);
178 : #else
179 : php_url *uri;
180 :
181 0 : if (!(uri = php_url_parse_ex(url, len))) {
182 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid URL '%s'", url);
183 0 : return 0;
184 : }
185 :
186 0 : if (uri->scheme && !strncasecmp("file", uri->scheme, sizeof("file"))) {
187 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Protocol 'file' disabled in cURL");
188 0 : php_url_free(uri);
189 0 : return 0;
190 : }
191 0 : php_url_free(uri);
192 : #endif
193 : }
194 : /* Strings passed to libcurl as 'char *' arguments, are copied by the library... NOTE: before 7.17.0 strings were not copied. */
195 : #if LIBCURL_VERSION_NUM >= 0x071100
196 : error = curl_easy_setopt(ch->cp, CURLOPT_URL, url);
197 : #else
198 59 : copystr = estrndup(url, len);
199 59 : error = curl_easy_setopt(ch->cp, CURLOPT_URL, copystr);
200 59 : zend_llist_add_element(&ch->to_free.str, ©str);
201 : #endif
202 :
203 59 : return (error == CURLE_OK ? 1 : 0);
204 : }
205 : /* }}} */
206 :
207 : /* {{{ arginfo */
208 : static
209 : ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_version, 0, 0, 0)
210 : ZEND_ARG_INFO(0, version)
211 : ZEND_END_ARG_INFO()
212 :
213 : static
214 : ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_init, 0, 0, 0)
215 : ZEND_ARG_INFO(0, url)
216 : ZEND_END_ARG_INFO()
217 :
218 : static
219 : ZEND_BEGIN_ARG_INFO(arginfo_curl_copy_handle, 0)
220 : ZEND_ARG_INFO(0, ch)
221 : ZEND_END_ARG_INFO()
222 :
223 : static
224 : ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt, 0)
225 : ZEND_ARG_INFO(0, ch)
226 : ZEND_ARG_INFO(0, option)
227 : ZEND_ARG_INFO(0, value)
228 : ZEND_END_ARG_INFO()
229 :
230 : static
231 : ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt_array, 0)
232 : ZEND_ARG_INFO(0, ch)
233 : ZEND_ARG_INFO(0, options)/* ARRAY_INFO(0, options, 0) */
234 : ZEND_END_ARG_INFO()
235 :
236 : static
237 : ZEND_BEGIN_ARG_INFO(arginfo_curl_exec, 0)
238 : ZEND_ARG_INFO(0, ch)
239 : ZEND_END_ARG_INFO()
240 :
241 : static
242 : ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_getinfo, 0, 0, 1)
243 : ZEND_ARG_INFO(0, ch)
244 : ZEND_ARG_INFO(0, option)
245 : ZEND_END_ARG_INFO()
246 :
247 : static
248 : ZEND_BEGIN_ARG_INFO(arginfo_curl_error, 0)
249 : ZEND_ARG_INFO(0, ch)
250 : ZEND_END_ARG_INFO()
251 :
252 : static
253 : ZEND_BEGIN_ARG_INFO(arginfo_curl_errno, 0)
254 : ZEND_ARG_INFO(0, ch)
255 : ZEND_END_ARG_INFO()
256 :
257 : static
258 : ZEND_BEGIN_ARG_INFO(arginfo_curl_close, 0)
259 : ZEND_ARG_INFO(0, ch)
260 : ZEND_END_ARG_INFO()
261 :
262 : static
263 : ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_init, 0)
264 : ZEND_END_ARG_INFO()
265 :
266 : static
267 : ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_add_handle, 0)
268 : ZEND_ARG_INFO(0, mh)
269 : ZEND_ARG_INFO(0, ch)
270 : ZEND_END_ARG_INFO()
271 :
272 : static
273 : ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_remove_handle, 0)
274 : ZEND_ARG_INFO(0, mh)
275 : ZEND_ARG_INFO(0, ch)
276 : ZEND_END_ARG_INFO()
277 :
278 : static
279 : ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_select, 0, 0, 1)
280 : ZEND_ARG_INFO(0, mh)
281 : ZEND_ARG_INFO(0, timeout)
282 : ZEND_END_ARG_INFO()
283 :
284 : static
285 : ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_exec, 0, 0, 1)
286 : ZEND_ARG_INFO(0, mh)
287 : ZEND_ARG_INFO(1, still_running)
288 : ZEND_END_ARG_INFO()
289 :
290 : static
291 : ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_getcontent, 0)
292 : ZEND_ARG_INFO(0, ch)
293 : ZEND_END_ARG_INFO()
294 :
295 : static
296 : ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_info_read, 0, 0, 1)
297 : ZEND_ARG_INFO(0, mh)
298 : ZEND_ARG_INFO(1, msgs_in_queue)
299 : ZEND_END_ARG_INFO()
300 :
301 : static
302 : ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_close, 0)
303 : ZEND_ARG_INFO(0, mh)
304 : ZEND_END_ARG_INFO()
305 : /* }}} */
306 :
307 : /* {{{ curl_functions[]
308 : */
309 : zend_function_entry curl_functions[] = {
310 : PHP_FE(curl_init, arginfo_curl_init)
311 : PHP_FE(curl_copy_handle, arginfo_curl_copy_handle)
312 : PHP_FE(curl_version, arginfo_curl_version)
313 : PHP_FE(curl_setopt, arginfo_curl_setopt)
314 : PHP_FE(curl_setopt_array, arginfo_curl_setopt_array)
315 : PHP_FE(curl_exec, arginfo_curl_exec)
316 : PHP_FE(curl_getinfo, arginfo_curl_getinfo)
317 : PHP_FE(curl_error, arginfo_curl_error)
318 : PHP_FE(curl_errno, arginfo_curl_errno)
319 : PHP_FE(curl_close, arginfo_curl_close)
320 : PHP_FE(curl_multi_init, arginfo_curl_multi_init)
321 : PHP_FE(curl_multi_add_handle, arginfo_curl_multi_add_handle)
322 : PHP_FE(curl_multi_remove_handle, arginfo_curl_multi_remove_handle)
323 : PHP_FE(curl_multi_select, arginfo_curl_multi_select)
324 : PHP_FE(curl_multi_exec, arginfo_curl_multi_exec)
325 : PHP_FE(curl_multi_getcontent, arginfo_curl_multi_getcontent)
326 : PHP_FE(curl_multi_info_read, arginfo_curl_multi_info_read)
327 : PHP_FE(curl_multi_close, arginfo_curl_multi_close)
328 : {NULL, NULL, NULL}
329 : };
330 : /* }}} */
331 :
332 : /* {{{ curl_module_entry
333 : */
334 : zend_module_entry curl_module_entry = {
335 : STANDARD_MODULE_HEADER,
336 : "curl",
337 : curl_functions,
338 : PHP_MINIT(curl),
339 : PHP_MSHUTDOWN(curl),
340 : NULL,
341 : NULL,
342 : PHP_MINFO(curl),
343 : NO_VERSION_YET,
344 : STANDARD_MODULE_PROPERTIES
345 : };
346 : /* }}} */
347 :
348 : #ifdef COMPILE_DL_CURL
349 : ZEND_GET_MODULE (curl)
350 : #endif
351 :
352 : /* {{{ PHP_MINFO_FUNCTION
353 : */
354 : PHP_MINFO_FUNCTION(curl)
355 6 : {
356 6 : php_info_print_table_start();
357 6 : php_info_print_table_row(2, "cURL support", "enabled");
358 6 : php_info_print_table_row(2, "cURL Information", curl_version());
359 6 : php_info_print_table_end();
360 6 : }
361 : /* }}} */
362 :
363 : #define REGISTER_CURL_CONSTANT(__c) REGISTER_LONG_CONSTANT(#__c, __c, CONST_CS | CONST_PERSISTENT)
364 :
365 : /* {{{ PHP_MINIT_FUNCTION
366 : */
367 : PHP_MINIT_FUNCTION(curl)
368 13565 : {
369 13565 : le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, "curl", module_number);
370 13565 : le_curl_multi_handle = zend_register_list_destructors_ex(_php_curl_multi_close, NULL, "curl_multi", module_number);
371 :
372 : /* See http://curl.haxx.se/lxr/source/docs/libcurl/symbols-in-versions
373 : or curl src/docs/libcurl/symbols-in-versions for a (almost) complete list
374 : of options and which version they were introduced */
375 :
376 : /* Constants for curl_setopt() */
377 13565 : REGISTER_CURL_CONSTANT(CURLOPT_DNS_USE_GLOBAL_CACHE);
378 13565 : REGISTER_CURL_CONSTANT(CURLOPT_DNS_CACHE_TIMEOUT);
379 13565 : REGISTER_CURL_CONSTANT(CURLOPT_PORT);
380 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FILE);
381 13565 : REGISTER_CURL_CONSTANT(CURLOPT_READDATA);
382 13565 : REGISTER_CURL_CONSTANT(CURLOPT_INFILE);
383 13565 : REGISTER_CURL_CONSTANT(CURLOPT_INFILESIZE);
384 13565 : REGISTER_CURL_CONSTANT(CURLOPT_URL);
385 13565 : REGISTER_CURL_CONSTANT(CURLOPT_PROXY);
386 13565 : REGISTER_CURL_CONSTANT(CURLOPT_VERBOSE);
387 13565 : REGISTER_CURL_CONSTANT(CURLOPT_HEADER);
388 13565 : REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER);
389 13565 : REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS);
390 13565 : REGISTER_CURL_CONSTANT(CURLOPT_NOBODY);
391 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR);
392 13565 : REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD);
393 13565 : REGISTER_CURL_CONSTANT(CURLOPT_POST);
394 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FTPLISTONLY);
395 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FTPAPPEND);
396 13565 : REGISTER_CURL_CONSTANT(CURLOPT_NETRC);
397 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FOLLOWLOCATION);
398 : #if CURLOPT_FTPASCII != 0
399 : REGISTER_CURL_CONSTANT(CURLOPT_FTPASCII);
400 : #endif
401 13565 : REGISTER_CURL_CONSTANT(CURLOPT_PUT);
402 : #if CURLOPT_MUTE != 0
403 13565 : REGISTER_CURL_CONSTANT(CURLOPT_MUTE);
404 : #endif
405 13565 : REGISTER_CURL_CONSTANT(CURLOPT_USERPWD);
406 13565 : REGISTER_CURL_CONSTANT(CURLOPT_PROXYUSERPWD);
407 13565 : REGISTER_CURL_CONSTANT(CURLOPT_RANGE);
408 13565 : REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT);
409 : #if LIBCURL_VERSION_NUM > 0x071002
410 : REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT_MS);
411 : #endif
412 13565 : REGISTER_CURL_CONSTANT(CURLOPT_POSTFIELDS);
413 13565 : REGISTER_CURL_CONSTANT(CURLOPT_REFERER);
414 13565 : REGISTER_CURL_CONSTANT(CURLOPT_USERAGENT);
415 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FTPPORT);
416 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPSV);
417 13565 : REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_LIMIT);
418 13565 : REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_TIME);
419 13565 : REGISTER_CURL_CONSTANT(CURLOPT_RESUME_FROM);
420 13565 : REGISTER_CURL_CONSTANT(CURLOPT_COOKIE);
421 13565 : REGISTER_CURL_CONSTANT(CURLOPT_COOKIESESSION);
422 13565 : REGISTER_CURL_CONSTANT(CURLOPT_AUTOREFERER);
423 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSLCERT);
424 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTPASSWD);
425 13565 : REGISTER_CURL_CONSTANT(CURLOPT_WRITEHEADER);
426 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYHOST);
427 13565 : REGISTER_CURL_CONSTANT(CURLOPT_COOKIEFILE);
428 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSLVERSION);
429 13565 : REGISTER_CURL_CONSTANT(CURLOPT_TIMECONDITION);
430 13565 : REGISTER_CURL_CONSTANT(CURLOPT_TIMEVALUE);
431 13565 : REGISTER_CURL_CONSTANT(CURLOPT_CUSTOMREQUEST);
432 13565 : REGISTER_CURL_CONSTANT(CURLOPT_STDERR);
433 13565 : REGISTER_CURL_CONSTANT(CURLOPT_TRANSFERTEXT);
434 13565 : REGISTER_CURL_CONSTANT(CURLOPT_RETURNTRANSFER);
435 13565 : REGISTER_CURL_CONSTANT(CURLOPT_QUOTE);
436 13565 : REGISTER_CURL_CONSTANT(CURLOPT_POSTQUOTE);
437 13565 : REGISTER_CURL_CONSTANT(CURLOPT_INTERFACE);
438 13565 : REGISTER_CURL_CONSTANT(CURLOPT_KRB4LEVEL);
439 13565 : REGISTER_CURL_CONSTANT(CURLOPT_HTTPPROXYTUNNEL);
440 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FILETIME);
441 13565 : REGISTER_CURL_CONSTANT(CURLOPT_WRITEFUNCTION);
442 13565 : REGISTER_CURL_CONSTANT(CURLOPT_READFUNCTION);
443 : #if CURLOPT_PASSWDFUNCTION != 0
444 13565 : REGISTER_CURL_CONSTANT(CURLOPT_PASSWDFUNCTION);
445 : #endif
446 13565 : REGISTER_CURL_CONSTANT(CURLOPT_HEADERFUNCTION);
447 13565 : REGISTER_CURL_CONSTANT(CURLOPT_MAXREDIRS);
448 13565 : REGISTER_CURL_CONSTANT(CURLOPT_MAXCONNECTS);
449 13565 : REGISTER_CURL_CONSTANT(CURLOPT_CLOSEPOLICY);
450 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FRESH_CONNECT);
451 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FORBID_REUSE);
452 13565 : REGISTER_CURL_CONSTANT(CURLOPT_RANDOM_FILE);
453 13565 : REGISTER_CURL_CONSTANT(CURLOPT_EGDSOCKET);
454 13565 : REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT);
455 : #if LIBCURL_VERSION_NUM > 0x071002
456 : REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT_MS);
457 : #endif
458 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYPEER);
459 13565 : REGISTER_CURL_CONSTANT(CURLOPT_CAINFO);
460 13565 : REGISTER_CURL_CONSTANT(CURLOPT_CAPATH);
461 13565 : REGISTER_CURL_CONSTANT(CURLOPT_COOKIEJAR);
462 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSL_CIPHER_LIST);
463 13565 : REGISTER_CURL_CONSTANT(CURLOPT_BINARYTRANSFER);
464 13565 : REGISTER_CURL_CONSTANT(CURLOPT_NOSIGNAL);
465 13565 : REGISTER_CURL_CONSTANT(CURLOPT_PROXYTYPE);
466 13565 : REGISTER_CURL_CONSTANT(CURLOPT_BUFFERSIZE);
467 13565 : REGISTER_CURL_CONSTANT(CURLOPT_HTTPGET);
468 13565 : REGISTER_CURL_CONSTANT(CURLOPT_HTTP_VERSION);
469 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSLKEY);
470 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYTYPE);
471 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYPASSWD);
472 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE);
473 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE_DEFAULT);
474 13565 : REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTTYPE);
475 13565 : REGISTER_CURL_CONSTANT(CURLOPT_CRLF);
476 13565 : REGISTER_CURL_CONSTANT(CURLOPT_ENCODING);
477 13565 : REGISTER_CURL_CONSTANT(CURLOPT_PROXYPORT);
478 13565 : REGISTER_CURL_CONSTANT(CURLOPT_UNRESTRICTED_AUTH);
479 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPRT);
480 : #if LIBCURL_VERSION_NUM > 0x070b01 /* CURLOPT_TCP_NODELAY is available since curl 7.11.2 */
481 13565 : REGISTER_CURL_CONSTANT(CURLOPT_TCP_NODELAY);
482 : #endif
483 13565 : REGISTER_CURL_CONSTANT(CURLOPT_HTTP200ALIASES);
484 13565 : REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFMODSINCE);
485 13565 : REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFUNMODSINCE);
486 13565 : REGISTER_CURL_CONSTANT(CURL_TIMECOND_LASTMOD);
487 :
488 : #if LIBCURL_VERSION_NUM > 0x070a05 /* CURLOPT_HTTPAUTH is available since curl 7.10.6 */
489 13565 : REGISTER_CURL_CONSTANT(CURLOPT_HTTPAUTH);
490 : /* http authentication options */
491 13565 : REGISTER_CURL_CONSTANT(CURLAUTH_BASIC);
492 13565 : REGISTER_CURL_CONSTANT(CURLAUTH_DIGEST);
493 13565 : REGISTER_CURL_CONSTANT(CURLAUTH_GSSNEGOTIATE);
494 13565 : REGISTER_CURL_CONSTANT(CURLAUTH_NTLM);
495 13565 : REGISTER_CURL_CONSTANT(CURLAUTH_ANY);
496 13565 : REGISTER_CURL_CONSTANT(CURLAUTH_ANYSAFE);
497 : #endif
498 :
499 : #if LIBCURL_VERSION_NUM > 0x070a06 /* CURLOPT_PROXYAUTH & CURLOPT_FTP_CREATE_MISSING_DIRS are available since curl 7.10.7 */
500 13565 : REGISTER_CURL_CONSTANT(CURLOPT_PROXYAUTH);
501 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FTP_CREATE_MISSING_DIRS);
502 : #endif
503 :
504 13565 : REGISTER_CURL_CONSTANT(CURLOPT_PRIVATE);
505 :
506 : /* Constants effecting the way CURLOPT_CLOSEPOLICY works */
507 13565 : REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
508 13565 : REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_TRAFFIC);
509 13565 : REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_SLOWEST);
510 13565 : REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_CALLBACK);
511 13565 : REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_OLDEST);
512 :
513 : /* Info constants */
514 13565 : REGISTER_CURL_CONSTANT(CURLINFO_EFFECTIVE_URL);
515 13565 : REGISTER_CURL_CONSTANT(CURLINFO_HTTP_CODE);
516 13565 : REGISTER_CURL_CONSTANT(CURLINFO_HEADER_SIZE);
517 13565 : REGISTER_CURL_CONSTANT(CURLINFO_REQUEST_SIZE);
518 13565 : REGISTER_CURL_CONSTANT(CURLINFO_TOTAL_TIME);
519 13565 : REGISTER_CURL_CONSTANT(CURLINFO_NAMELOOKUP_TIME);
520 13565 : REGISTER_CURL_CONSTANT(CURLINFO_CONNECT_TIME);
521 13565 : REGISTER_CURL_CONSTANT(CURLINFO_PRETRANSFER_TIME);
522 13565 : REGISTER_CURL_CONSTANT(CURLINFO_SIZE_UPLOAD);
523 13565 : REGISTER_CURL_CONSTANT(CURLINFO_SIZE_DOWNLOAD);
524 13565 : REGISTER_CURL_CONSTANT(CURLINFO_SPEED_DOWNLOAD);
525 13565 : REGISTER_CURL_CONSTANT(CURLINFO_SPEED_UPLOAD);
526 13565 : REGISTER_CURL_CONSTANT(CURLINFO_FILETIME);
527 13565 : REGISTER_CURL_CONSTANT(CURLINFO_SSL_VERIFYRESULT);
528 13565 : REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_DOWNLOAD);
529 13565 : REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_UPLOAD);
530 13565 : REGISTER_CURL_CONSTANT(CURLINFO_STARTTRANSFER_TIME);
531 13565 : REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_TYPE);
532 13565 : REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_TIME);
533 13565 : REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_COUNT);
534 13565 : REGISTER_CURL_CONSTANT(CURLINFO_HEADER_OUT);
535 13565 : REGISTER_CURL_CONSTANT(CURLINFO_PRIVATE);
536 :
537 : /* cURL protocol constants (curl_version) */
538 13565 : REGISTER_CURL_CONSTANT(CURL_VERSION_IPV6);
539 13565 : REGISTER_CURL_CONSTANT(CURL_VERSION_KERBEROS4);
540 13565 : REGISTER_CURL_CONSTANT(CURL_VERSION_SSL);
541 13565 : REGISTER_CURL_CONSTANT(CURL_VERSION_LIBZ);
542 :
543 : /* version constants */
544 13565 : REGISTER_CURL_CONSTANT(CURLVERSION_NOW);
545 :
546 : /* Error Constants */
547 13565 : REGISTER_CURL_CONSTANT(CURLE_OK);
548 13565 : REGISTER_CURL_CONSTANT(CURLE_UNSUPPORTED_PROTOCOL);
549 13565 : REGISTER_CURL_CONSTANT(CURLE_FAILED_INIT);
550 13565 : REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT);
551 13565 : REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT_USER);
552 13565 : REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_PROXY);
553 13565 : REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_HOST);
554 13565 : REGISTER_CURL_CONSTANT(CURLE_COULDNT_CONNECT);
555 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_SERVER_REPLY);
556 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_ACCESS_DENIED);
557 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_USER_PASSWORD_INCORRECT);
558 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASS_REPLY);
559 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_USER_REPLY);
560 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASV_REPLY);
561 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_227_FORMAT);
562 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_GET_HOST);
563 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_RECONNECT);
564 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_BINARY);
565 13565 : REGISTER_CURL_CONSTANT(CURLE_PARTIAL_FILE);
566 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_RETR_FILE);
567 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_WRITE_ERROR);
568 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_QUOTE_ERROR);
569 13565 : REGISTER_CURL_CONSTANT(CURLE_HTTP_NOT_FOUND);
570 13565 : REGISTER_CURL_CONSTANT(CURLE_WRITE_ERROR);
571 13565 : REGISTER_CURL_CONSTANT(CURLE_MALFORMAT_USER);
572 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_STOR_FILE);
573 13565 : REGISTER_CURL_CONSTANT(CURLE_READ_ERROR);
574 13565 : REGISTER_CURL_CONSTANT(CURLE_OUT_OF_MEMORY);
575 13565 : REGISTER_CURL_CONSTANT(CURLE_OPERATION_TIMEOUTED);
576 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_ASCII);
577 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_PORT_FAILED);
578 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_USE_REST);
579 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_GET_SIZE);
580 13565 : REGISTER_CURL_CONSTANT(CURLE_HTTP_RANGE_ERROR);
581 13565 : REGISTER_CURL_CONSTANT(CURLE_HTTP_POST_ERROR);
582 13565 : REGISTER_CURL_CONSTANT(CURLE_SSL_CONNECT_ERROR);
583 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_BAD_DOWNLOAD_RESUME);
584 13565 : REGISTER_CURL_CONSTANT(CURLE_FILE_COULDNT_READ_FILE);
585 13565 : REGISTER_CURL_CONSTANT(CURLE_LDAP_CANNOT_BIND);
586 13565 : REGISTER_CURL_CONSTANT(CURLE_LDAP_SEARCH_FAILED);
587 13565 : REGISTER_CURL_CONSTANT(CURLE_LIBRARY_NOT_FOUND);
588 13565 : REGISTER_CURL_CONSTANT(CURLE_FUNCTION_NOT_FOUND);
589 13565 : REGISTER_CURL_CONSTANT(CURLE_ABORTED_BY_CALLBACK);
590 13565 : REGISTER_CURL_CONSTANT(CURLE_BAD_FUNCTION_ARGUMENT);
591 13565 : REGISTER_CURL_CONSTANT(CURLE_BAD_CALLING_ORDER);
592 13565 : REGISTER_CURL_CONSTANT(CURLE_HTTP_PORT_FAILED);
593 13565 : REGISTER_CURL_CONSTANT(CURLE_BAD_PASSWORD_ENTERED);
594 13565 : REGISTER_CURL_CONSTANT(CURLE_TOO_MANY_REDIRECTS);
595 13565 : REGISTER_CURL_CONSTANT(CURLE_UNKNOWN_TELNET_OPTION);
596 13565 : REGISTER_CURL_CONSTANT(CURLE_TELNET_OPTION_SYNTAX);
597 13565 : REGISTER_CURL_CONSTANT(CURLE_OBSOLETE);
598 13565 : REGISTER_CURL_CONSTANT(CURLE_SSL_PEER_CERTIFICATE);
599 13565 : REGISTER_CURL_CONSTANT(CURLE_GOT_NOTHING);
600 13565 : REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_NOTFOUND);
601 13565 : REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_SETFAILED);
602 13565 : REGISTER_CURL_CONSTANT(CURLE_SEND_ERROR);
603 13565 : REGISTER_CURL_CONSTANT(CURLE_RECV_ERROR);
604 13565 : REGISTER_CURL_CONSTANT(CURLE_SHARE_IN_USE);
605 13565 : REGISTER_CURL_CONSTANT(CURLE_SSL_CERTPROBLEM);
606 13565 : REGISTER_CURL_CONSTANT(CURLE_SSL_CIPHER);
607 13565 : REGISTER_CURL_CONSTANT(CURLE_SSL_CACERT);
608 13565 : REGISTER_CURL_CONSTANT(CURLE_BAD_CONTENT_ENCODING);
609 : #if LIBCURL_VERSION_NUM >= 0x070a08
610 13565 : REGISTER_CURL_CONSTANT(CURLE_LDAP_INVALID_URL);
611 13565 : REGISTER_CURL_CONSTANT(CURLE_FILESIZE_EXCEEDED);
612 : #endif
613 : #if LIBCURL_VERSION_NUM >= 0x070b00
614 13565 : REGISTER_CURL_CONSTANT(CURLE_FTP_SSL_FAILED);
615 : #endif
616 13565 : REGISTER_CURL_CONSTANT(CURLPROXY_HTTP);
617 13565 : REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS4);
618 13565 : REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5);
619 :
620 13565 : REGISTER_CURL_CONSTANT(CURL_NETRC_OPTIONAL);
621 13565 : REGISTER_CURL_CONSTANT(CURL_NETRC_IGNORED);
622 13565 : REGISTER_CURL_CONSTANT(CURL_NETRC_REQUIRED);
623 :
624 13565 : REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_NONE);
625 13565 : REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_0);
626 13565 : REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_1);
627 :
628 13565 : REGISTER_CURL_CONSTANT(CURLM_CALL_MULTI_PERFORM);
629 13565 : REGISTER_CURL_CONSTANT(CURLM_OK);
630 13565 : REGISTER_CURL_CONSTANT(CURLM_BAD_HANDLE);
631 13565 : REGISTER_CURL_CONSTANT(CURLM_BAD_EASY_HANDLE);
632 13565 : REGISTER_CURL_CONSTANT(CURLM_OUT_OF_MEMORY);
633 13565 : REGISTER_CURL_CONSTANT(CURLM_INTERNAL_ERROR);
634 :
635 13565 : REGISTER_CURL_CONSTANT(CURLMSG_DONE);
636 :
637 : #if LIBCURL_VERSION_NUM >= 0x070c02
638 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FTPSSLAUTH);
639 13565 : REGISTER_CURL_CONSTANT(CURLFTPAUTH_DEFAULT);
640 13565 : REGISTER_CURL_CONSTANT(CURLFTPAUTH_SSL);
641 13565 : REGISTER_CURL_CONSTANT(CURLFTPAUTH_TLS);
642 : #endif
643 :
644 : #if LIBCURL_VERSION_NUM > 0x070b00
645 13565 : REGISTER_CURL_CONSTANT(CURLOPT_FTP_SSL);
646 13565 : REGISTER_CURL_CONSTANT(CURLFTPSSL_NONE);
647 13565 : REGISTER_CURL_CONSTANT(CURLFTPSSL_TRY);
648 13565 : REGISTER_CURL_CONSTANT(CURLFTPSSL_CONTROL);
649 13565 : REGISTER_CURL_CONSTANT(CURLFTPSSL_ALL);
650 : #endif
651 :
652 : #if LIBCURL_VERSION_NUM >= 0x071304
653 : REGISTER_CURL_CONSTANT(CURLOPT_REDIR_PROTOCOLS);
654 : REGISTER_CURL_CONSTANT(CURLOPT_PROTOCOLS);
655 : REGISTER_CURL_CONSTANT(CURLPROTO_HTTP);
656 : REGISTER_CURL_CONSTANT(CURLPROTO_HTTPS);
657 : REGISTER_CURL_CONSTANT(CURLPROTO_FTP);
658 : REGISTER_CURL_CONSTANT(CURLPROTO_FTPS);
659 : REGISTER_CURL_CONSTANT(CURLPROTO_SCP);
660 : REGISTER_CURL_CONSTANT(CURLPROTO_SFTP);
661 : REGISTER_CURL_CONSTANT(CURLPROTO_TELNET);
662 : REGISTER_CURL_CONSTANT(CURLPROTO_LDAP);
663 : REGISTER_CURL_CONSTANT(CURLPROTO_LDAPS);
664 : REGISTER_CURL_CONSTANT(CURLPROTO_DICT);
665 : REGISTER_CURL_CONSTANT(CURLPROTO_FILE);
666 : REGISTER_CURL_CONSTANT(CURLPROTO_TFTP);
667 : REGISTER_CURL_CONSTANT(CURLPROTO_ALL);
668 : #endif
669 :
670 : #ifdef PHP_CURL_NEED_OPENSSL_TSL
671 : if (!CRYPTO_get_id_callback()) {
672 : int i, c = CRYPTO_num_locks();
673 :
674 : php_curl_openssl_tsl = malloc(c * sizeof(MUTEX_T));
675 :
676 : for (i = 0; i < c; ++i) {
677 : php_curl_openssl_tsl[i] = tsrm_mutex_alloc();
678 : }
679 :
680 : CRYPTO_set_id_callback(php_curl_ssl_id);
681 : CRYPTO_set_locking_callback(php_curl_ssl_lock);
682 : }
683 : #endif
684 : #ifdef PHP_CURL_NEED_GNUTLS_TSL
685 : gcry_control(GCRYCTL_SET_THREAD_CBS, &php_curl_gnutls_tsl);
686 : #endif
687 :
688 13565 : if (curl_global_init(CURL_GLOBAL_SSL) != CURLE_OK) {
689 0 : return FAILURE;
690 : }
691 :
692 : #ifdef PHP_CURL_URL_WRAPPERS
693 : # if HAVE_CURL_VERSION_INFO
694 : {
695 13565 : curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
696 13565 : char **p = (char **)info->protocols;
697 :
698 149215 : while (*p != NULL) {
699 : /* Do not enable cURL "file" protocol and make sure cURL is always used when --with-curlwrappers is enabled */
700 122085 : if (strncasecmp(*p, "file", sizeof("file")-1) != 0) {
701 108520 : php_unregister_url_stream_wrapper(*p TSRMLS_CC);
702 108520 : php_register_url_stream_wrapper(*p, &php_curl_wrapper TSRMLS_CC);
703 : }
704 122085 : (void) *p++;
705 : }
706 : }
707 : # else
708 : php_unregister_url_stream_wrapper("http");
709 : php_register_url_stream_wrapper("http", &php_curl_wrapper TSRMLS_CC);
710 : php_unregister_url_stream_wrapper("https");
711 : php_register_url_stream_wrapper("https", &php_curl_wrapper TSRMLS_CC);
712 : php_unregister_url_stream_wrapper("ftp");
713 : php_register_url_stream_wrapper("ftp", &php_curl_wrapper TSRMLS_CC);
714 : php_unregister_url_stream_wrapper("ftps");
715 : php_register_url_stream_wrapper("ftps", &php_curl_wrapper TSRMLS_CC);
716 : php_unregister_url_stream_wrapper("ldap");
717 : php_register_url_stream_wrapper("ldap", &php_curl_wrapper TSRMLS_CC);
718 : # endif
719 : #endif
720 :
721 13565 : return SUCCESS;
722 : }
723 : /* }}} */
724 :
725 : /* {{{ PHP_MSHUTDOWN_FUNCTION
726 : */
727 : PHP_MSHUTDOWN_FUNCTION(curl)
728 13597 : {
729 : #ifdef PHP_CURL_URL_WRAPPERS
730 13597 : php_unregister_url_stream_wrapper("http" TSRMLS_CC);
731 13597 : php_unregister_url_stream_wrapper("https" TSRMLS_CC);
732 13597 : php_unregister_url_stream_wrapper("ftp" TSRMLS_CC);
733 13597 : php_unregister_url_stream_wrapper("ldap" TSRMLS_CC);
734 : #endif
735 13597 : curl_global_cleanup();
736 : #ifdef PHP_CURL_NEED_OPENSSL_TSL
737 : if (php_curl_openssl_tsl) {
738 : int i, c = CRYPTO_num_locks();
739 :
740 : CRYPTO_set_id_callback(NULL);
741 : CRYPTO_set_locking_callback(NULL);
742 :
743 : for (i = 0; i < c; ++i) {
744 : tsrm_mutex_free(php_curl_openssl_tsl[i]);
745 : }
746 :
747 : free(php_curl_openssl_tsl);
748 : php_curl_openssl_tsl = NULL;
749 : }
750 : #endif
751 13597 : return SUCCESS;
752 : }
753 : /* }}} */
754 :
755 : /* {{{ curl_write
756 : */
757 : static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx)
758 45 : {
759 45 : php_curl *ch = (php_curl *) ctx;
760 45 : php_curl_write *t = ch->handlers->write;
761 45 : size_t length = size * nmemb;
762 : TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
763 :
764 : #if PHP_CURL_DEBUG
765 : fprintf(stderr, "curl_write() called\n");
766 : fprintf(stderr, "data = %s, size = %d, nmemb = %d, ctx = %x\n", data, size, nmemb, ctx);
767 : #endif
768 :
769 45 : switch (t->method) {
770 : case PHP_CURL_STDOUT:
771 10 : PHPWRITE(data, length);
772 10 : break;
773 : case PHP_CURL_FILE:
774 2 : return fwrite(data, size, nmemb, t->fp);
775 : case PHP_CURL_RETURN:
776 32 : if (length > 0) {
777 32 : smart_str_appendl(&t->buf, data, (int) length);
778 : }
779 32 : break;
780 : case PHP_CURL_USER: {
781 : zval **argv[2];
782 1 : zval *retval_ptr = NULL;
783 1 : zval *handle = NULL;
784 1 : zval *zdata = NULL;
785 : int error;
786 : zend_fcall_info fci;
787 :
788 1 : MAKE_STD_ZVAL(handle);
789 1 : ZVAL_RESOURCE(handle, ch->id);
790 1 : zend_list_addref(ch->id);
791 1 : argv[0] = &handle;
792 :
793 1 : MAKE_STD_ZVAL(zdata);
794 1 : ZVAL_STRINGL(zdata, data, length, 1);
795 1 : argv[1] = &zdata;
796 :
797 1 : fci.size = sizeof(fci);
798 1 : fci.function_table = EG(function_table);
799 1 : fci.object_pp = NULL;
800 1 : fci.function_name = t->func_name;
801 1 : fci.retval_ptr_ptr = &retval_ptr;
802 1 : fci.param_count = 2;
803 1 : fci.params = argv;
804 1 : fci.no_separation = 0;
805 1 : fci.symbol_table = NULL;
806 :
807 1 : ch->in_callback = 1;
808 1 : error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
809 1 : ch->in_callback = 0;
810 1 : if (error == FAILURE) {
811 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION");
812 0 : length = -1;
813 1 : } else if (retval_ptr) {
814 1 : if (Z_TYPE_P(retval_ptr) != IS_LONG) {
815 0 : convert_to_long_ex(&retval_ptr);
816 : }
817 1 : length = Z_LVAL_P(retval_ptr);
818 1 : zval_ptr_dtor(&retval_ptr);
819 : }
820 :
821 1 : zval_ptr_dtor(argv[0]);
822 1 : zval_ptr_dtor(argv[1]);
823 : break;
824 : }
825 : }
826 :
827 43 : return length;
828 : }
829 : /* }}} */
830 :
831 : /* {{{ curl_read
832 : */
833 : static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
834 4 : {
835 4 : php_curl *ch = (php_curl *) ctx;
836 4 : php_curl_read *t = ch->handlers->read;
837 4 : int length = 0;
838 :
839 4 : switch (t->method) {
840 : case PHP_CURL_DIRECT:
841 2 : if (t->fp) {
842 2 : length = fread(data, size, nmemb, t->fp);
843 : }
844 2 : break;
845 : case PHP_CURL_USER: {
846 : zval **argv[3];
847 2 : zval *handle = NULL;
848 2 : zval *zfd = NULL;
849 2 : zval *zlength = NULL;
850 : zval *retval_ptr;
851 : int error;
852 : zend_fcall_info fci;
853 : TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
854 :
855 2 : MAKE_STD_ZVAL(handle);
856 2 : MAKE_STD_ZVAL(zfd);
857 2 : MAKE_STD_ZVAL(zlength);
858 :
859 2 : ZVAL_RESOURCE(handle, ch->id);
860 2 : zend_list_addref(ch->id);
861 2 : ZVAL_RESOURCE(zfd, t->fd);
862 2 : zend_list_addref(t->fd);
863 2 : ZVAL_LONG(zlength, (int) size * nmemb);
864 :
865 2 : argv[0] = &handle;
866 2 : argv[1] = &zfd;
867 2 : argv[2] = &zlength;
868 :
869 2 : fci.size = sizeof(fci);
870 2 : fci.function_table = EG(function_table);
871 2 : fci.function_name = t->func_name;
872 2 : fci.object_pp = NULL;
873 2 : fci.retval_ptr_ptr = &retval_ptr;
874 2 : fci.param_count = 3;
875 2 : fci.params = argv;
876 2 : fci.no_separation = 0;
877 2 : fci.symbol_table = NULL;
878 :
879 2 : ch->in_callback = 1;
880 2 : error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
881 2 : ch->in_callback = 0;
882 2 : if (error == FAILURE) {
883 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_READFUNCTION");
884 : #if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */
885 0 : length = CURL_READFUNC_ABORT;
886 : #endif
887 2 : } else if (retval_ptr) {
888 2 : if (Z_TYPE_P(retval_ptr) == IS_STRING) {
889 2 : length = MIN(size * nmemb, Z_STRLEN_P(retval_ptr));
890 2 : memcpy(data, Z_STRVAL_P(retval_ptr), length);
891 : }
892 2 : zval_ptr_dtor(&retval_ptr);
893 : }
894 :
895 2 : zval_ptr_dtor(argv[0]);
896 2 : zval_ptr_dtor(argv[1]);
897 2 : zval_ptr_dtor(argv[2]);
898 : break;
899 : }
900 : }
901 :
902 4 : return length;
903 : }
904 : /* }}} */
905 :
906 : /* {{{ curl_write_header
907 : */
908 : static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx)
909 272 : {
910 272 : php_curl *ch = (php_curl *) ctx;
911 272 : php_curl_write *t = ch->handlers->write_header;
912 272 : size_t length = size * nmemb;
913 : TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
914 :
915 272 : switch (t->method) {
916 : case PHP_CURL_STDOUT:
917 : /* Handle special case write when we're returning the entire transfer
918 : */
919 0 : if (ch->handlers->write->method == PHP_CURL_RETURN && length > 0) {
920 0 : smart_str_appendl(&ch->handlers->write->buf, data, (int) length);
921 : } else {
922 0 : PHPWRITE(data, length);
923 : }
924 0 : break;
925 : case PHP_CURL_FILE:
926 0 : return fwrite(data, size, nmemb, t->fp);
927 : case PHP_CURL_USER: {
928 : zval **argv[2];
929 1 : zval *handle = NULL;
930 1 : zval *zdata = NULL;
931 : zval *retval_ptr;
932 : int error;
933 : zend_fcall_info fci;
934 :
935 1 : MAKE_STD_ZVAL(handle);
936 1 : MAKE_STD_ZVAL(zdata);
937 :
938 1 : ZVAL_RESOURCE(handle, ch->id);
939 1 : zend_list_addref(ch->id);
940 1 : ZVAL_STRINGL(zdata, data, length, 1);
941 :
942 1 : argv[0] = &handle;
943 1 : argv[1] = &zdata;
944 :
945 1 : fci.size = sizeof(fci);
946 1 : fci.function_table = EG(function_table);
947 1 : fci.function_name = t->func_name;
948 1 : fci.symbol_table = NULL;
949 1 : fci.object_pp = NULL;
950 1 : fci.retval_ptr_ptr = &retval_ptr;
951 1 : fci.param_count = 2;
952 1 : fci.params = argv;
953 1 : fci.no_separation = 0;
954 :
955 1 : ch->in_callback = 1;
956 1 : error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
957 1 : ch->in_callback = 0;
958 1 : if (error == FAILURE) {
959 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION");
960 0 : length = -1;
961 1 : } else if (retval_ptr) {
962 1 : if (Z_TYPE_P(retval_ptr) != IS_LONG) {
963 1 : convert_to_long_ex(&retval_ptr);
964 : }
965 1 : length = Z_LVAL_P(retval_ptr);
966 1 : zval_ptr_dtor(&retval_ptr);
967 : }
968 1 : zval_ptr_dtor(argv[0]);
969 1 : zval_ptr_dtor(argv[1]);
970 1 : break;
971 : }
972 :
973 : case PHP_CURL_IGNORE:
974 271 : return length;
975 :
976 : default:
977 0 : return -1;
978 : }
979 :
980 1 : return length;
981 : }
982 : /* }}} */
983 :
984 : static int curl_debug(CURL *cp, curl_infotype type, char *buf, size_t buf_len, void *ctx) /* {{{ */
985 0 : {
986 0 : php_curl *ch = (php_curl *) ctx;
987 :
988 0 : if (type == CURLINFO_HEADER_OUT) {
989 0 : if (ch->header.str_len) {
990 0 : efree(ch->header.str);
991 : }
992 0 : if (buf_len > 0) {
993 0 : ch->header.str = estrndup(buf, buf_len);
994 0 : ch->header.str_len = buf_len;
995 : }
996 : }
997 :
998 0 : return 0;
999 : }
1000 : /* }}} */
1001 :
1002 : #if CURLOPT_PASSWDFUNCTION != 0
1003 : /* {{{ curl_passwd
1004 : */
1005 : static size_t curl_passwd(void *ctx, char *prompt, char *buf, int buflen)
1006 0 : {
1007 0 : php_curl *ch = (php_curl *) ctx;
1008 0 : zval *func = ch->handlers->passwd;
1009 : zval *argv[3];
1010 0 : zval *retval = NULL;
1011 : int error;
1012 0 : int ret = -1;
1013 : TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
1014 :
1015 0 : MAKE_STD_ZVAL(argv[0]);
1016 0 : MAKE_STD_ZVAL(argv[1]);
1017 0 : MAKE_STD_ZVAL(argv[2]);
1018 :
1019 0 : ZVAL_RESOURCE(argv[0], ch->id);
1020 0 : zend_list_addref(ch->id);
1021 0 : ZVAL_STRING(argv[1], prompt, 1);
1022 0 : ZVAL_LONG(argv[2], buflen);
1023 :
1024 0 : error = call_user_function(EG(function_table), NULL, func, retval, 2, argv TSRMLS_CC);
1025 0 : if (error == FAILURE) {
1026 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_PASSWDFUNCTION");
1027 0 : } else if (Z_TYPE_P(retval) == IS_STRING) {
1028 0 : if (Z_STRLEN_P(retval) > buflen) {
1029 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Returned password is too long for libcurl to handle");
1030 : } else {
1031 0 : strlcpy(buf, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
1032 : }
1033 : } else {
1034 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "User handler '%s' did not return a string", Z_STRVAL_P(func));
1035 : }
1036 :
1037 0 : zval_ptr_dtor(&argv[0]);
1038 0 : zval_ptr_dtor(&argv[1]);
1039 0 : zval_ptr_dtor(&argv[2]);
1040 0 : zval_ptr_dtor(&retval);
1041 :
1042 0 : return ret;
1043 : }
1044 : /* }}} */
1045 : #endif
1046 :
1047 : #if LIBCURL_VERSION_NUM < 0x071101
1048 : /* {{{ curl_free_string
1049 : */
1050 : static void curl_free_string(void **string)
1051 64 : {
1052 64 : efree(*string);
1053 64 : }
1054 : /* }}} */
1055 : #endif
1056 :
1057 : /* {{{ curl_free_post
1058 : */
1059 : static void curl_free_post(void **post)
1060 1 : {
1061 1 : curl_formfree((struct HttpPost *) *post);
1062 1 : }
1063 : /* }}} */
1064 :
1065 : /* {{{ curl_free_slist
1066 : */
1067 : static void curl_free_slist(void **slist)
1068 3 : {
1069 3 : curl_slist_free_all((struct curl_slist *) *slist);
1070 3 : }
1071 : /* }}} */
1072 :
1073 : /* {{{ proto array curl_version([int version])
1074 : Return cURL version information. */
1075 : PHP_FUNCTION(curl_version)
1076 27 : {
1077 : curl_version_info_data *d;
1078 27 : long uversion = CURLVERSION_NOW;
1079 :
1080 27 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &uversion) == FAILURE) {
1081 8 : return;
1082 : }
1083 :
1084 19 : d = curl_version_info(uversion);
1085 19 : if (d == NULL) {
1086 0 : RETURN_FALSE;
1087 : }
1088 :
1089 19 : array_init(return_value);
1090 :
1091 19 : CAAL("version_number", d->version_num);
1092 19 : CAAL("age", d->age);
1093 19 : CAAL("features", d->features);
1094 19 : CAAL("ssl_version_number", d->ssl_version_num);
1095 19 : CAAS("version", d->version);
1096 19 : CAAS("host", d->host);
1097 19 : CAAS("ssl_version", d->ssl_version);
1098 19 : CAAS("libz_version", d->libz_version);
1099 : /* Add an array of protocols */
1100 : {
1101 19 : char **p = (char **) d->protocols;
1102 19 : zval *protocol_list = NULL;
1103 :
1104 19 : MAKE_STD_ZVAL(protocol_list);
1105 19 : array_init(protocol_list);
1106 :
1107 209 : while (*p != NULL) {
1108 171 : add_next_index_string(protocol_list, *p, 1);
1109 171 : p++;
1110 : }
1111 19 : CAAZ("protocols", protocol_list);
1112 : }
1113 : }
1114 : /* }}} */
1115 :
1116 : /* {{{ alloc_curl_handle
1117 : */
1118 : static void alloc_curl_handle(php_curl **ch)
1119 74 : {
1120 74 : *ch = emalloc(sizeof(php_curl));
1121 74 : (*ch)->handlers = ecalloc(1, sizeof(php_curl_handlers));
1122 74 : (*ch)->handlers->write = ecalloc(1, sizeof(php_curl_write));
1123 74 : (*ch)->handlers->write_header = ecalloc(1, sizeof(php_curl_write));
1124 74 : (*ch)->handlers->read = ecalloc(1, sizeof(php_curl_read));
1125 :
1126 74 : (*ch)->in_callback = 0;
1127 74 : (*ch)->header.str_len = 0;
1128 :
1129 74 : memset(&(*ch)->err, 0, sizeof((*ch)->err));
1130 :
1131 : #if LIBCURL_VERSION_NUM < 0x071101
1132 74 : zend_llist_init(&(*ch)->to_free.str, sizeof(char *), (llist_dtor_func_t) curl_free_string, 0);
1133 : #endif
1134 74 : zend_llist_init(&(*ch)->to_free.slist, sizeof(struct curl_slist), (llist_dtor_func_t) curl_free_slist, 0);
1135 74 : zend_llist_init(&(*ch)->to_free.post, sizeof(struct HttpPost), (llist_dtor_func_t) curl_free_post, 0);
1136 74 : }
1137 : /* }}} */
1138 :
1139 : /* {{{ proto resource curl_init([string url])
1140 : Initialize a cURL session */
1141 : PHP_FUNCTION(curl_init)
1142 65 : {
1143 : php_curl *ch;
1144 : zval **url;
1145 : zval *clone;
1146 : CURL *cp;
1147 65 : int argc = ZEND_NUM_ARGS();
1148 :
1149 65 : if (argc < 0 || argc > 1 || zend_get_parameters_ex(argc, &url) == FAILURE) {
1150 0 : WRONG_PARAM_COUNT;
1151 : }
1152 :
1153 65 : if (argc > 0) {
1154 5 : convert_to_string_ex(url);
1155 : }
1156 :
1157 65 : cp = curl_easy_init();
1158 65 : if (!cp) {
1159 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize a new cURL handle");
1160 0 : RETURN_FALSE;
1161 : }
1162 :
1163 65 : alloc_curl_handle(&ch);
1164 : TSRMLS_SET_CTX(ch->thread_ctx);
1165 :
1166 65 : ch->cp = cp;
1167 :
1168 65 : ch->handlers->write->method = PHP_CURL_STDOUT;
1169 65 : ch->handlers->write->type = PHP_CURL_ASCII;
1170 65 : ch->handlers->read->method = PHP_CURL_DIRECT;
1171 65 : ch->handlers->write_header->method = PHP_CURL_IGNORE;
1172 :
1173 65 : ch->uses = 0;
1174 :
1175 65 : MAKE_STD_ZVAL(clone);
1176 65 : ch->clone = clone;
1177 :
1178 65 : curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1);
1179 65 : curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0);
1180 65 : curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str);
1181 65 : curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write);
1182 65 : curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch);
1183 65 : curl_easy_setopt(ch->cp, CURLOPT_READFUNCTION, curl_read);
1184 65 : curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch);
1185 65 : curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_header);
1186 65 : curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch);
1187 65 : curl_easy_setopt(ch->cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 1);
1188 65 : curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120);
1189 65 : curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20); /* prevent infinite redirects */
1190 : #if defined(ZTS)
1191 : curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1);
1192 : #endif
1193 :
1194 65 : if (argc > 0) {
1195 5 : if (!php_curl_option_url(ch, Z_STRVAL_PP(url), Z_STRLEN_PP(url))) {
1196 0 : _php_curl_close_ex(ch TSRMLS_CC);
1197 0 : RETURN_FALSE;
1198 : }
1199 : }
1200 :
1201 65 : ZEND_REGISTER_RESOURCE(return_value, ch, le_curl);
1202 65 : ch->id = Z_LVAL_P(return_value);
1203 : }
1204 : /* }}} */
1205 :
1206 : /* {{{ proto resource curl_copy_handle(resource ch)
1207 : Copy a cURL handle along with all of it's preferences */
1208 : PHP_FUNCTION(curl_copy_handle)
1209 9 : {
1210 : CURL *cp;
1211 : zval **zid;
1212 : php_curl *ch, *dupch;
1213 :
1214 9 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &zid) == FAILURE) {
1215 0 : WRONG_PARAM_COUNT;
1216 : }
1217 :
1218 9 : ZEND_FETCH_RESOURCE(ch, php_curl *, zid, -1, le_curl_name, le_curl);
1219 :
1220 9 : cp = curl_easy_duphandle(ch->cp);
1221 9 : if (!cp) {
1222 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot duplicate cURL handle");
1223 0 : RETURN_FALSE;
1224 : }
1225 :
1226 9 : alloc_curl_handle(&dupch);
1227 : TSRMLS_SET_CTX(dupch->thread_ctx);
1228 :
1229 9 : dupch->cp = cp;
1230 9 : dupch->uses = 0;
1231 9 : if (ch->handlers->write->stream) {
1232 0 : zval_add_ref(dupch->handlers->write->stream);
1233 0 : dupch->handlers->write->stream = ch->handlers->write->stream;
1234 : }
1235 9 : dupch->handlers->write->method = ch->handlers->write->method;
1236 9 : dupch->handlers->write->type = ch->handlers->write->type;
1237 9 : if (ch->handlers->read->stream) {
1238 0 : zval_add_ref(ch->handlers->read->stream);
1239 : }
1240 9 : dupch->handlers->read->stream = ch->handlers->read->stream;
1241 9 : dupch->handlers->read->method = ch->handlers->read->method;
1242 9 : dupch->handlers->write_header->method = ch->handlers->write_header->method;
1243 9 : if (ch->handlers->write_header->stream) {
1244 0 : zval_add_ref(ch->handlers->write_header->stream);
1245 : }
1246 9 : dupch->handlers->write_header->stream = ch->handlers->write_header->stream;
1247 :
1248 9 : dupch->handlers->write->fp = ch->handlers->write->fp;
1249 9 : dupch->handlers->write_header->fp = ch->handlers->write_header->fp;
1250 9 : dupch->handlers->read->fp = ch->handlers->read->fp;
1251 9 : dupch->handlers->read->fd = ch->handlers->read->fd;
1252 : #if CURLOPT_PASSWDDATA != 0
1253 9 : if (ch->handlers->passwd) {
1254 0 : zval_add_ref(&ch->handlers->passwd);
1255 0 : dupch->handlers->passwd = ch->handlers->passwd;
1256 0 : curl_easy_setopt(ch->cp, CURLOPT_PASSWDDATA, (void *) dupch);
1257 : }
1258 : #endif
1259 9 : if (ch->handlers->write->func_name) {
1260 0 : zval_add_ref(&ch->handlers->write->func_name);
1261 0 : dupch->handlers->write->func_name = ch->handlers->write->func_name;
1262 : }
1263 9 : if (ch->handlers->read->func_name) {
1264 0 : zval_add_ref(&ch->handlers->read->func_name);
1265 0 : dupch->handlers->read->func_name = ch->handlers->read->func_name;
1266 : }
1267 9 : if (ch->handlers->write_header->func_name) {
1268 0 : zval_add_ref(&ch->handlers->write_header->func_name);
1269 0 : dupch->handlers->write_header->func_name = ch->handlers->write_header->func_name;
1270 : }
1271 :
1272 9 : curl_easy_setopt(dupch->cp, CURLOPT_ERRORBUFFER, dupch->err.str);
1273 9 : curl_easy_setopt(dupch->cp, CURLOPT_FILE, (void *) dupch);
1274 9 : curl_easy_setopt(dupch->cp, CURLOPT_INFILE, (void *) dupch);
1275 9 : curl_easy_setopt(dupch->cp, CURLOPT_WRITEHEADER, (void *) dupch);
1276 :
1277 : #if LIBCURL_VERSION_NUM < 0x071101
1278 9 : zend_llist_copy(&dupch->to_free.str, &ch->to_free.str);
1279 : /* Don't try to free copied strings, they're free'd when the original handle is destroyed */
1280 9 : dupch->to_free.str.dtor = NULL;
1281 : #endif
1282 9 : zend_llist_copy(&dupch->to_free.slist, &ch->to_free.slist);
1283 9 : zend_llist_copy(&dupch->to_free.post, &ch->to_free.post);
1284 :
1285 : /* Keep track of cloned copies to avoid invoking curl destructors for every clone */
1286 9 : ch->clone->refcount++;
1287 9 : dupch->clone = ch->clone;
1288 :
1289 9 : ZEND_REGISTER_RESOURCE(return_value, dupch, le_curl);
1290 9 : dupch->id = Z_LVAL_P(return_value);
1291 : }
1292 : /* }}} */
1293 :
1294 : static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *return_value TSRMLS_DC) /* {{{ */
1295 129 : {
1296 129 : CURLcode error=CURLE_OK;
1297 :
1298 129 : switch (option) {
1299 : case CURLOPT_INFILESIZE:
1300 : case CURLOPT_VERBOSE:
1301 : case CURLOPT_HEADER:
1302 : case CURLOPT_NOPROGRESS:
1303 : case CURLOPT_NOBODY:
1304 : case CURLOPT_FAILONERROR:
1305 : case CURLOPT_UPLOAD:
1306 : case CURLOPT_POST:
1307 : case CURLOPT_FTPLISTONLY:
1308 : case CURLOPT_FTPAPPEND:
1309 : case CURLOPT_NETRC:
1310 : case CURLOPT_PUT:
1311 : #if CURLOPT_MUTE != 0
1312 : case CURLOPT_MUTE:
1313 : #endif
1314 : case CURLOPT_TIMEOUT:
1315 : #if LIBCURL_VERSION_NUM > 0x071002
1316 : case CURLOPT_TIMEOUT_MS:
1317 : #endif
1318 : case CURLOPT_FTP_USE_EPSV:
1319 : case CURLOPT_LOW_SPEED_LIMIT:
1320 : case CURLOPT_SSLVERSION:
1321 : case CURLOPT_LOW_SPEED_TIME:
1322 : case CURLOPT_RESUME_FROM:
1323 : case CURLOPT_TIMEVALUE:
1324 : case CURLOPT_TIMECONDITION:
1325 : case CURLOPT_TRANSFERTEXT:
1326 : case CURLOPT_HTTPPROXYTUNNEL:
1327 : case CURLOPT_FILETIME:
1328 : case CURLOPT_MAXREDIRS:
1329 : case CURLOPT_MAXCONNECTS:
1330 : case CURLOPT_CLOSEPOLICY:
1331 : case CURLOPT_FRESH_CONNECT:
1332 : case CURLOPT_FORBID_REUSE:
1333 : case CURLOPT_CONNECTTIMEOUT:
1334 : #if LIBCURL_VERSION_NUM > 0x071002
1335 : case CURLOPT_CONNECTTIMEOUT_MS:
1336 : #endif
1337 : case CURLOPT_SSL_VERIFYHOST:
1338 : case CURLOPT_SSL_VERIFYPEER:
1339 : case CURLOPT_DNS_USE_GLOBAL_CACHE:
1340 : case CURLOPT_NOSIGNAL:
1341 : case CURLOPT_PROXYTYPE:
1342 : case CURLOPT_BUFFERSIZE:
1343 : case CURLOPT_HTTPGET:
1344 : case CURLOPT_HTTP_VERSION:
1345 : case CURLOPT_CRLF:
1346 : case CURLOPT_DNS_CACHE_TIMEOUT:
1347 : case CURLOPT_PROXYPORT:
1348 : case CURLOPT_FTP_USE_EPRT:
1349 : #if LIBCURL_VERSION_NUM > 0x070a05 /* CURLOPT_HTTPAUTH is available since curl 7.10.6 */
1350 : case CURLOPT_HTTPAUTH:
1351 : #endif
1352 : #if LIBCURL_VERSION_NUM > 0x070a06 /* CURLOPT_PROXYAUTH & CURLOPT_FTP_CREATE_MISSING_DIRS are available since curl 7.10.7 */
1353 : case CURLOPT_PROXYAUTH:
1354 : case CURLOPT_FTP_CREATE_MISSING_DIRS:
1355 : #endif
1356 :
1357 : #if LIBCURL_VERSION_NUM >= 0x070c02
1358 : case CURLOPT_FTPSSLAUTH:
1359 : #endif
1360 : #if LIBCURL_VERSION_NUM > 0x070b00
1361 : case CURLOPT_FTP_SSL:
1362 : #endif
1363 : case CURLOPT_UNRESTRICTED_AUTH:
1364 : case CURLOPT_PORT:
1365 : case CURLOPT_AUTOREFERER:
1366 : case CURLOPT_COOKIESESSION:
1367 : #if LIBCURL_VERSION_NUM > 0x070b01 /* CURLOPT_TCP_NODELAY is available since curl 7.11.2 */
1368 : case CURLOPT_TCP_NODELAY:
1369 : #endif
1370 : #if LIBCURL_VERSION_NUM >= 0x71304
1371 : case CURLOPT_REDIR_PROTOCOLS:
1372 : case CURLOPT_PROTOCOLS:
1373 : #endif
1374 13 : convert_to_long_ex(zvalue);
1375 : #if LIBCURL_VERSION_NUM >= 0x71304
1376 : if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) &&
1377 : ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) && (Z_LVAL_PP(zvalue) & CURLPROTO_FILE)) {
1378 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLPROTO_FILE cannot be activated when in safe_mode or an open_basedir is set");
1379 : RETVAL_FALSE;
1380 : return 1;
1381 : }
1382 : #endif
1383 13 : error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue));
1384 13 : break;
1385 : case CURLOPT_FOLLOWLOCATION:
1386 2 : convert_to_long_ex(zvalue);
1387 2 : if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
1388 2 : if (Z_LVAL_PP(zvalue) != 0) {
1389 2 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir is set");
1390 2 : RETVAL_FALSE;
1391 2 : return 1;
1392 : }
1393 : }
1394 0 : error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue));
1395 0 : break;
1396 : case CURLOPT_PRIVATE:
1397 : case CURLOPT_URL:
1398 : case CURLOPT_PROXY:
1399 : case CURLOPT_USERPWD:
1400 : case CURLOPT_PROXYUSERPWD:
1401 : case CURLOPT_RANGE:
1402 : case CURLOPT_CUSTOMREQUEST:
1403 : case CURLOPT_USERAGENT:
1404 : case CURLOPT_FTPPORT:
1405 : case CURLOPT_COOKIE:
1406 : case CURLOPT_REFERER:
1407 : case CURLOPT_INTERFACE:
1408 : case CURLOPT_KRB4LEVEL:
1409 : case CURLOPT_EGDSOCKET:
1410 : case CURLOPT_CAINFO:
1411 : case CURLOPT_CAPATH:
1412 : case CURLOPT_SSL_CIPHER_LIST:
1413 : case CURLOPT_SSLKEY:
1414 : case CURLOPT_SSLKEYTYPE:
1415 : case CURLOPT_SSLKEYPASSWD:
1416 : case CURLOPT_SSLENGINE:
1417 : case CURLOPT_SSLENGINE_DEFAULT:
1418 : case CURLOPT_SSLCERTTYPE:
1419 : case CURLOPT_ENCODING:
1420 : {
1421 : #if LIBCURL_VERSION_NUM < 0x071100
1422 59 : char *copystr = NULL;
1423 : #endif
1424 :
1425 59 : convert_to_string_ex(zvalue);
1426 :
1427 59 : if (option == CURLOPT_URL) {
1428 54 : if (!php_curl_option_url(ch, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue))) {
1429 0 : RETVAL_FALSE;
1430 0 : return 1;
1431 : }
1432 : } else {
1433 : #if LIBCURL_VERSION_NUM >= 0x071100
1434 : /* Strings passed to libcurl as ’char *’ arguments, are copied by the library... NOTE: before 7.17.0 strings were not copied. */
1435 : error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue));
1436 : #else
1437 5 : copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
1438 5 : error = curl_easy_setopt(ch->cp, option, copystr);
1439 5 : zend_llist_add_element(&ch->to_free.str, ©str);
1440 : #endif
1441 : }
1442 59 : break;
1443 : }
1444 : case CURLOPT_FILE:
1445 : case CURLOPT_INFILE:
1446 : case CURLOPT_WRITEHEADER:
1447 : case CURLOPT_STDERR: {
1448 8 : FILE *fp = NULL;
1449 : int type;
1450 : void * what;
1451 :
1452 8 : what = zend_fetch_resource(zvalue TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream());
1453 8 : if (!what) {
1454 0 : RETVAL_FALSE;
1455 0 : return 1;
1456 : }
1457 :
1458 8 : if (FAILURE == php_stream_cast((php_stream *) what, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
1459 0 : RETVAL_FALSE;
1460 0 : return 1;
1461 : }
1462 :
1463 8 : if (!fp) {
1464 0 : RETVAL_FALSE;
1465 0 : return 1;
1466 : }
1467 :
1468 8 : error = CURLE_OK;
1469 8 : switch (option) {
1470 : case CURLOPT_FILE:
1471 3 : if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
1472 2 : zval_add_ref(zvalue);
1473 2 : ch->handlers->write->fp = fp;
1474 2 : ch->handlers->write->method = PHP_CURL_FILE;
1475 2 : ch->handlers->write->stream = *zvalue;
1476 : } else {
1477 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
1478 1 : RETVAL_FALSE;
1479 1 : return 1;
1480 : }
1481 2 : break;
1482 : case CURLOPT_WRITEHEADER:
1483 0 : if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
1484 0 : zval_add_ref(zvalue);
1485 0 : ch->handlers->write_header->fp = fp;
1486 0 : ch->handlers->write_header->method = PHP_CURL_FILE;
1487 0 : ch->handlers->write_header->stream = *zvalue;
1488 : } else {
1489 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
1490 0 : RETVAL_FALSE;
1491 0 : return 1;
1492 : }
1493 0 : break;
1494 : case CURLOPT_INFILE:
1495 2 : zval_add_ref(zvalue);
1496 2 : ch->handlers->read->fp = fp;
1497 2 : ch->handlers->read->fd = Z_LVAL_PP(zvalue);
1498 2 : ch->handlers->read->stream = *zvalue;
1499 2 : break;
1500 : case CURLOPT_STDERR:
1501 6 : if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
1502 3 : if (ch->handlers->std_err) {
1503 1 : zval_ptr_dtor(&ch->handlers->std_err);
1504 : }
1505 3 : zval_add_ref(zvalue);
1506 3 : ch->handlers->std_err = *zvalue;
1507 3 : zend_list_addref(Z_LVAL_PP(zvalue));
1508 : } else {
1509 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
1510 0 : RETVAL_FALSE;
1511 0 : return 1;
1512 : }
1513 : /* break omitted intentionally */
1514 : default:
1515 3 : error = curl_easy_setopt(ch->cp, option, fp);
1516 : break;
1517 : }
1518 :
1519 7 : break;
1520 : }
1521 : case CURLOPT_RETURNTRANSFER:
1522 31 : convert_to_long_ex(zvalue);
1523 :
1524 31 : if (Z_LVAL_PP(zvalue)) {
1525 30 : ch->handlers->write->method = PHP_CURL_RETURN;
1526 : } else {
1527 1 : ch->handlers->write->method = PHP_CURL_STDOUT;
1528 : }
1529 31 : break;
1530 : case CURLOPT_BINARYTRANSFER:
1531 1 : convert_to_long_ex(zvalue);
1532 :
1533 1 : if (Z_LVAL_PP(zvalue)) {
1534 1 : ch->handlers->write->type = PHP_CURL_BINARY;
1535 : } else {
1536 0 : ch->handlers->write->type = PHP_CURL_ASCII;
1537 : }
1538 1 : break;
1539 : case CURLOPT_WRITEFUNCTION:
1540 1 : if (ch->handlers->write->func_name) {
1541 0 : zval_ptr_dtor(&ch->handlers->write->func_name);
1542 0 : ch->handlers->write->fci_cache = empty_fcall_info_cache;
1543 : }
1544 1 : zval_add_ref(zvalue);
1545 1 : ch->handlers->write->func_name = *zvalue;
1546 1 : ch->handlers->write->method = PHP_CURL_USER;
1547 1 : break;
1548 : case CURLOPT_READFUNCTION:
1549 1 : if (ch->handlers->read->func_name) {
1550 0 : zval_ptr_dtor(&ch->handlers->read->func_name);
1551 0 : ch->handlers->read->fci_cache = empty_fcall_info_cache;
1552 : }
1553 1 : zval_add_ref(zvalue);
1554 1 : ch->handlers->read->func_name = *zvalue;
1555 1 : ch->handlers->read->method = PHP_CURL_USER;
1556 1 : break;
1557 : case CURLOPT_HEADERFUNCTION:
1558 1 : if (ch->handlers->write_header->func_name) {
1559 0 : zval_ptr_dtor(&ch->handlers->write_header->func_name);
1560 0 : ch->handlers->write_header->fci_cache = empty_fcall_info_cache;
1561 : }
1562 1 : zval_add_ref(zvalue);
1563 1 : ch->handlers->write_header->func_name = *zvalue;
1564 1 : ch->handlers->write_header->method = PHP_CURL_USER;
1565 1 : break;
1566 : #if CURLOPT_PASSWDFUNCTION != 0
1567 : case CURLOPT_PASSWDFUNCTION:
1568 0 : if (ch->handlers->passwd) {
1569 0 : zval_ptr_dtor(&ch->handlers->passwd);
1570 : }
1571 0 : zval_add_ref(zvalue);
1572 0 : ch->handlers->passwd = *zvalue;
1573 0 : error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDFUNCTION, curl_passwd);
1574 0 : error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDDATA, (void *) ch);
1575 0 : break;
1576 : #endif
1577 : case CURLOPT_POSTFIELDS:
1578 5 : if (Z_TYPE_PP(zvalue) == IS_ARRAY || Z_TYPE_PP(zvalue) == IS_OBJECT) {
1579 : zval **current;
1580 : HashTable *postfields;
1581 1 : struct HttpPost *first = NULL;
1582 1 : struct HttpPost *last = NULL;
1583 : char *postval;
1584 1 : char *string_key = NULL;
1585 : ulong num_key;
1586 : uint string_key_len;
1587 :
1588 1 : postfields = HASH_OF(*zvalue);
1589 1 : if (!postfields) {
1590 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't get HashTable in CURLOPT_POSTFIELDS");
1591 0 : RETVAL_FALSE;
1592 0 : return 1;
1593 : }
1594 :
1595 1 : for (zend_hash_internal_pointer_reset(postfields);
1596 5 : zend_hash_get_current_data(postfields, (void **) ¤t) == SUCCESS;
1597 : zend_hash_move_forward(postfields)
1598 3 : ) {
1599 :
1600 3 : SEPARATE_ZVAL(current);
1601 3 : convert_to_string_ex(current);
1602 :
1603 3 : zend_hash_get_current_key_ex(postfields, &string_key, &string_key_len, &num_key, 0, NULL);
1604 :
1605 3 : postval = Z_STRVAL_PP(current);
1606 :
1607 : /* The arguments after _NAMELENGTH and _CONTENTSLENGTH
1608 : * must be explicitly cast to long in curl_formadd
1609 : * use since curl needs a long not an int. */
1610 3 : if (*postval == '@') {
1611 : char *type, *filename;
1612 0 : ++postval;
1613 :
1614 0 : if ((type = php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + Z_STRLEN_PP(current)))) {
1615 0 : *type = '\0';
1616 : }
1617 0 : if ((filename = php_memnstr(postval, ";filename=", sizeof(";filename=") - 1, postval + Z_STRLEN_PP(current)))) {
1618 0 : *filename = '\0';
1619 : }
1620 : /* safe_mode / open_basedir check */
1621 0 : if (php_check_open_basedir(postval TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(postval, "rb+", CHECKUID_CHECK_MODE_PARAM))) {
1622 0 : RETVAL_FALSE;
1623 0 : return 1;
1624 : }
1625 0 : error = curl_formadd(&first, &last,
1626 : CURLFORM_COPYNAME, string_key,
1627 : CURLFORM_NAMELENGTH, (long)string_key_len - 1,
1628 : CURLFORM_FILENAME, filename ? filename + sizeof(";filename=") - 1 : postval,
1629 : CURLFORM_CONTENTTYPE, type ? type + sizeof(";type=") - 1 : "application/octet-stream",
1630 : CURLFORM_FILE, postval,
1631 : CURLFORM_END);
1632 0 : if (type) {
1633 0 : *type = ';';
1634 : }
1635 0 : if (filename) {
1636 0 : *filename = ';';
1637 : }
1638 : } else {
1639 3 : error = curl_formadd(&first, &last,
1640 : CURLFORM_COPYNAME, string_key,
1641 : CURLFORM_NAMELENGTH, (long)string_key_len - 1,
1642 : CURLFORM_COPYCONTENTS, postval,
1643 : CURLFORM_CONTENTSLENGTH, (long)Z_STRLEN_PP(current),
1644 : CURLFORM_END);
1645 : }
1646 : }
1647 :
1648 1 : SAVE_CURL_ERROR(ch, error);
1649 1 : if (error != CURLE_OK) {
1650 0 : RETVAL_FALSE
1651 0 : return 1;
1652 : }
1653 :
1654 1 : zend_llist_add_element(&ch->to_free.post, &first);
1655 1 : error = curl_easy_setopt(ch->cp, CURLOPT_HTTPPOST, first);
1656 :
1657 : } else {
1658 : #if LIBCURL_VERSION_NUM >= 0x071101
1659 : convert_to_string_ex(zvalue);
1660 : /* with curl 7.17.0 and later, we can use COPYPOSTFIELDS, but we have to provide size before */
1661 : error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue));
1662 : error = curl_easy_setopt(ch->cp, CURLOPT_COPYPOSTFIELDS, Z_STRVAL_PP(zvalue));
1663 : #else
1664 3 : char *post = NULL;
1665 :
1666 3 : convert_to_string_ex(zvalue);
1667 3 : post = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
1668 3 : zend_llist_add_element(&ch->to_free.str, &post);
1669 :
1670 3 : error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, post);
1671 3 : error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue));
1672 : #endif
1673 : }
1674 4 : break;
1675 : case CURLOPT_HTTPHEADER:
1676 : case CURLOPT_QUOTE:
1677 : case CURLOPT_HTTP200ALIASES:
1678 : case CURLOPT_POSTQUOTE: {
1679 : zval **current;
1680 : HashTable *ph;
1681 4 : struct curl_slist *slist = NULL;
1682 :
1683 4 : ph = HASH_OF(*zvalue);
1684 4 : if (!ph) {
1685 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must pass either an object or an array with the CURLOPT_HTTPHEADER, CURLOPT_QUOTE, CURLOPT_HTTP200ALIASES and CURLOPT_POSTQUOTE arguments");
1686 1 : RETVAL_FALSE;
1687 1 : return 1;
1688 : }
1689 :
1690 3 : for (zend_hash_internal_pointer_reset(ph);
1691 9 : zend_hash_get_current_data(ph, (void **) ¤t) == SUCCESS;
1692 : zend_hash_move_forward(ph)
1693 3 : ) {
1694 3 : SEPARATE_ZVAL(current);
1695 3 : convert_to_string_ex(current);
1696 :
1697 3 : slist = curl_slist_append(slist, Z_STRVAL_PP(current));
1698 3 : if (!slist) {
1699 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not build curl_slist");
1700 0 : RETVAL_FALSE;
1701 0 : return 1;
1702 : }
1703 : }
1704 3 : zend_llist_add_element(&ch->to_free.slist, &slist);
1705 :
1706 3 : error = curl_easy_setopt(ch->cp, option, slist);
1707 :
1708 3 : break;
1709 : }
1710 : /* the following options deal with files, therefor safe_mode & open_basedir checks
1711 : * are required.
1712 : */
1713 : case CURLOPT_COOKIEJAR:
1714 : case CURLOPT_SSLCERT:
1715 : case CURLOPT_RANDOM_FILE:
1716 : case CURLOPT_COOKIEFILE: {
1717 : #if LIBCURL_VERSION_NUM < 0x071100
1718 0 : char *copystr = NULL;
1719 : #endif
1720 :
1721 0 : convert_to_string_ex(zvalue);
1722 :
1723 0 : if (php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(Z_STRVAL_PP(zvalue), "rb+", CHECKUID_CHECK_MODE_PARAM))) {
1724 0 : RETVAL_FALSE;
1725 0 : return 1;
1726 : }
1727 :
1728 : #if LIBCURL_VERSION_NUM >= 0x071100
1729 : error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue));
1730 : #else
1731 0 : copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
1732 :
1733 0 : error = curl_easy_setopt(ch->cp, option, copystr);
1734 0 : zend_llist_add_element(&ch->to_free.str, ©str);
1735 : #endif
1736 0 : break;
1737 : }
1738 : case CURLINFO_HEADER_OUT:
1739 0 : convert_to_long_ex(zvalue);
1740 0 : if (Z_LVAL_PP(zvalue) == 1) {
1741 0 : curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug);
1742 0 : curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *)ch);
1743 0 : curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1);
1744 : } else {
1745 0 : curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL);
1746 0 : curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL);
1747 0 : curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0);
1748 : }
1749 : break;
1750 : }
1751 :
1752 125 : SAVE_CURL_ERROR(ch, error);
1753 125 : if (error != CURLE_OK) {
1754 0 : return 1;
1755 : } else {
1756 125 : return 0;
1757 : }
1758 : }
1759 : /* }}} */
1760 :
1761 : /* {{{ proto bool curl_setopt(resource ch, int option, mixed value)
1762 : Set an option for a cURL transfer */
1763 : PHP_FUNCTION(curl_setopt)
1764 130 : {
1765 : zval **zid, **zoption, **zvalue;
1766 : php_curl *ch;
1767 :
1768 130 : if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &zid, &zoption, &zvalue) == FAILURE) {
1769 6 : WRONG_PARAM_COUNT;
1770 : }
1771 :
1772 124 : ZEND_FETCH_RESOURCE(ch, php_curl *, zid, -1, le_curl_name, le_curl);
1773 :
1774 121 : convert_to_long_ex(zoption);
1775 :
1776 121 : if (!_php_curl_setopt(ch, Z_LVAL_PP(zoption), zvalue, return_value TSRMLS_CC)) {
1777 117 : RETURN_TRUE;
1778 : } else {
1779 4 : RETURN_FALSE;
1780 : }
1781 : }
1782 : /* }}} */
1783 :
1784 : /* {{{ proto bool curl_setopt_array(resource ch, array options)
1785 : Set an array of option for a cURL transfer */
1786 : PHP_FUNCTION(curl_setopt_array)
1787 4 : {
1788 : zval *zid, *arr, **entry;
1789 : php_curl *ch;
1790 : ulong option;
1791 : HashPosition pos;
1792 : char *string_key;
1793 : uint str_key_len;
1794 :
1795 4 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za", &zid, &arr) == FAILURE) {
1796 0 : return;
1797 : }
1798 :
1799 4 : ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
1800 :
1801 4 : zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
1802 16 : while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
1803 8 : if (zend_hash_get_current_key_ex(Z_ARRVAL_P(arr), &string_key, &str_key_len, &option, 0, &pos) != HASH_KEY_IS_LONG) {
1804 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array keys must be CURLOPT constants or equivalent integer values");
1805 0 : RETURN_FALSE;
1806 : }
1807 8 : if (_php_curl_setopt(ch, (long) option, entry, return_value TSRMLS_CC)) {
1808 0 : RETURN_FALSE;
1809 : }
1810 8 : zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
1811 : }
1812 4 : RETURN_TRUE;
1813 : }
1814 : /* }}} */
1815 :
1816 : /* {{{ _php_curl_cleanup_handle(ch)
1817 : Cleanup an execution phase */
1818 : void _php_curl_cleanup_handle(php_curl *ch)
1819 58 : {
1820 58 : if (ch->handlers->write->buf.len > 0) {
1821 0 : smart_str_free(&ch->handlers->write->buf);
1822 : }
1823 58 : if (ch->header.str_len) {
1824 0 : efree(ch->header.str);
1825 0 : ch->header.str_len = 0;
1826 : }
1827 :
1828 58 : memset(ch->err.str, 0, CURL_ERROR_SIZE + 1);
1829 58 : ch->err.no = 0;
1830 58 : }
1831 : /* }}} */
1832 :
1833 : /* {{{ proto bool curl_exec(resource ch)
1834 : Perform a cURL session */
1835 : PHP_FUNCTION(curl_exec)
1836 43 : {
1837 : CURLcode error;
1838 : zval **zid;
1839 : php_curl *ch;
1840 :
1841 43 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &zid) == FAILURE) {
1842 0 : WRONG_PARAM_COUNT;
1843 : }
1844 :
1845 43 : ZEND_FETCH_RESOURCE(ch, php_curl *, zid, -1, le_curl_name, le_curl);
1846 :
1847 43 : _php_curl_cleanup_handle(ch);
1848 :
1849 43 : error = curl_easy_perform(ch->cp);
1850 43 : SAVE_CURL_ERROR(ch, error);
1851 : /* CURLE_PARTIAL_FILE is returned by HEAD requests */
1852 43 : if (error != CURLE_OK && error != CURLE_PARTIAL_FILE) {
1853 11 : if (ch->handlers->write->buf.len > 0) {
1854 0 : smart_str_free(&ch->handlers->write->buf);
1855 : }
1856 11 : RETURN_FALSE;
1857 : }
1858 :
1859 32 : if (ch->handlers->write->method == PHP_CURL_RETURN && ch->handlers->write->buf.len > 0) {
1860 20 : smart_str_0(&ch->handlers->write->buf);
1861 20 : RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 1);
1862 : }
1863 :
1864 : /* flush the file handle, so any remaining data is synched to disk */
1865 12 : if (ch->handlers->write->method == PHP_CURL_FILE && ch->handlers->write->fp) {
1866 2 : fflush(ch->handlers->write->fp);
1867 : }
1868 12 : if (ch->handlers->write_header->method == PHP_CURL_FILE && ch->handlers->write_header->fp) {
1869 0 : fflush(ch->handlers->write_header->fp);
1870 : }
1871 :
1872 12 : if (ch->handlers->write->method == PHP_CURL_RETURN) {
1873 0 : RETURN_EMPTY_STRING();
1874 : } else {
1875 12 : RETURN_TRUE;
1876 : }
1877 : }
1878 : /* }}} */
1879 :
1880 : /* {{{ proto mixed curl_getinfo(resource ch [, int option])
1881 : Get information regarding a specific transfer */
1882 : PHP_FUNCTION(curl_getinfo)
1883 18 : {
1884 : zval **zid, **zoption;
1885 : php_curl *ch;
1886 18 : int option, argc = ZEND_NUM_ARGS();
1887 :
1888 18 : if (argc < 1 || argc > 2 || zend_get_parameters_ex(argc, &zid, &zoption) == FAILURE) {
1889 0 : WRONG_PARAM_COUNT;
1890 : }
1891 :
1892 18 : ZEND_FETCH_RESOURCE(ch, php_curl *, zid, -1, le_curl_name, le_curl);
1893 :
1894 18 : if (argc < 2) {
1895 : char *s_code;
1896 : long l_code;
1897 : double d_code;
1898 :
1899 14 : array_init(return_value);
1900 :
1901 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_EFFECTIVE_URL, &s_code) == CURLE_OK) {
1902 14 : CAAS("url", s_code);
1903 : }
1904 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_TYPE, &s_code) == CURLE_OK) {
1905 14 : if (s_code != NULL) {
1906 0 : CAAS("content_type", s_code);
1907 : } else {
1908 : zval *retnull;
1909 14 : MAKE_STD_ZVAL(retnull);
1910 14 : ZVAL_NULL(retnull);
1911 14 : CAAZ("content_type", retnull);
1912 : }
1913 : }
1914 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_HTTP_CODE, &l_code) == CURLE_OK) {
1915 14 : CAAL("http_code", l_code);
1916 : }
1917 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_HEADER_SIZE, &l_code) == CURLE_OK) {
1918 14 : CAAL("header_size", l_code);
1919 : }
1920 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_REQUEST_SIZE, &l_code) == CURLE_OK) {
1921 14 : CAAL("request_size", l_code);
1922 : }
1923 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_FILETIME, &l_code) == CURLE_OK) {
1924 14 : CAAL("filetime", l_code);
1925 : }
1926 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_SSL_VERIFYRESULT, &l_code) == CURLE_OK) {
1927 14 : CAAL("ssl_verify_result", l_code);
1928 : }
1929 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_COUNT, &l_code) == CURLE_OK) {
1930 14 : CAAL("redirect_count", l_code);
1931 : }
1932 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_TOTAL_TIME, &d_code) == CURLE_OK) {
1933 14 : CAAD("total_time", d_code);
1934 : }
1935 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_NAMELOOKUP_TIME, &d_code) == CURLE_OK) {
1936 14 : CAAD("namelookup_time", d_code);
1937 : }
1938 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_CONNECT_TIME, &d_code) == CURLE_OK) {
1939 14 : CAAD("connect_time", d_code);
1940 : }
1941 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_PRETRANSFER_TIME, &d_code) == CURLE_OK) {
1942 14 : CAAD("pretransfer_time", d_code);
1943 : }
1944 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_UPLOAD, &d_code) == CURLE_OK) {
1945 14 : CAAD("size_upload", d_code);
1946 : }
1947 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_DOWNLOAD, &d_code) == CURLE_OK) {
1948 14 : CAAD("size_download", d_code);
1949 : }
1950 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_DOWNLOAD, &d_code) == CURLE_OK) {
1951 14 : CAAD("speed_download", d_code);
1952 : }
1953 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_UPLOAD, &d_code) == CURLE_OK) {
1954 14 : CAAD("speed_upload", d_code);
1955 : }
1956 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d_code) == CURLE_OK) {
1957 14 : CAAD("download_content_length", d_code);
1958 : }
1959 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_UPLOAD, &d_code) == CURLE_OK) {
1960 14 : CAAD("upload_content_length", d_code);
1961 : }
1962 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_STARTTRANSFER_TIME, &d_code) == CURLE_OK) {
1963 14 : CAAD("starttransfer_time", d_code);
1964 : }
1965 14 : if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_TIME, &d_code) == CURLE_OK) {
1966 14 : CAAD("redirect_time", d_code);
1967 : }
1968 14 : if (ch->header.str_len > 0) {
1969 0 : CAAS("request_header", ch->header.str);
1970 : }
1971 : } else {
1972 4 : option = Z_LVAL_PP(zoption);
1973 4 : switch (option) {
1974 : case CURLINFO_PRIVATE:
1975 : case CURLINFO_EFFECTIVE_URL:
1976 : case CURLINFO_CONTENT_TYPE: {
1977 3 : char *s_code = NULL;
1978 :
1979 3 : if (curl_easy_getinfo(ch->cp, option, &s_code) == CURLE_OK && s_code) {
1980 3 : RETURN_STRING(s_code, 1);
1981 : } else {
1982 0 : RETURN_FALSE;
1983 : }
1984 : break;
1985 : }
1986 : case CURLINFO_HTTP_CODE:
1987 : case CURLINFO_HEADER_SIZE:
1988 : case CURLINFO_REQUEST_SIZE:
1989 : case CURLINFO_FILETIME:
1990 : case CURLINFO_SSL_VERIFYRESULT:
1991 : case CURLINFO_REDIRECT_COUNT: {
1992 1 : long code = 0;
1993 :
1994 1 : if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
1995 1 : RETURN_LONG(code);
1996 : } else {
1997 0 : RETURN_FALSE;
1998 : }
1999 : break;
2000 : }
2001 : case CURLINFO_TOTAL_TIME:
2002 : case CURLINFO_NAMELOOKUP_TIME:
2003 : case CURLINFO_CONNECT_TIME:
2004 : case CURLINFO_PRETRANSFER_TIME:
2005 : case CURLINFO_SIZE_UPLOAD:
2006 : case CURLINFO_SIZE_DOWNLOAD:
2007 : case CURLINFO_SPEED_DOWNLOAD:
2008 : case CURLINFO_SPEED_UPLOAD:
2009 : case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
2010 : case CURLINFO_CONTENT_LENGTH_UPLOAD:
2011 : case CURLINFO_STARTTRANSFER_TIME:
2012 : case CURLINFO_REDIRECT_TIME: {
2013 0 : double code = 0.0;
2014 :
2015 0 : if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
2016 0 : RETURN_DOUBLE(code);
2017 : } else {
2018 0 : RETURN_FALSE;
2019 : }
2020 : break;
2021 : }
2022 : case CURLINFO_HEADER_OUT:
2023 0 : if (ch->header.str_len > 0) {
2024 0 : RETURN_STRINGL(ch->header.str, ch->header.str_len, 1);
2025 : } else {
2026 0 : RETURN_FALSE;
2027 : }
2028 : }
2029 : }
2030 : }
2031 : /* }}} */
2032 :
2033 : /* {{{ proto string curl_error(resource ch)
2034 : Return a string contain the last error for the current session */
2035 : PHP_FUNCTION(curl_error)
2036 5 : {
2037 : zval **zid;
2038 : php_curl *ch;
2039 :
2040 5 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &zid) == FAILURE) {
2041 0 : WRONG_PARAM_COUNT;
2042 : }
2043 :
2044 5 : ZEND_FETCH_RESOURCE(ch, php_curl *, zid, -1, le_curl_name, le_curl);
2045 :
2046 5 : ch->err.str[CURL_ERROR_SIZE] = 0;
2047 5 : RETURN_STRING(ch->err.str, 1);
2048 : }
2049 : /* }}} */
2050 :
2051 : /* {{{ proto int curl_errno(resource ch)
2052 : Return an integer containing the last error number */
2053 : PHP_FUNCTION(curl_errno)
2054 4 : {
2055 : zval **zid;
2056 : php_curl *ch;
2057 :
2058 4 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &zid) == FAILURE) {
2059 0 : WRONG_PARAM_COUNT;
2060 : }
2061 :
2062 4 : ZEND_FETCH_RESOURCE(ch, php_curl *, zid, -1, le_curl_name, le_curl);
2063 :
2064 4 : RETURN_LONG(ch->err.no);
2065 : }
2066 : /* }}} */
2067 :
2068 : /* {{{ proto void curl_close(resource ch)
2069 : Close a cURL session */
2070 : PHP_FUNCTION(curl_close)
2071 45 : {
2072 : zval **zid;
2073 : php_curl *ch;
2074 :
2075 45 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &zid) == FAILURE) {
2076 0 : WRONG_PARAM_COUNT;
2077 : }
2078 :
2079 45 : ZEND_FETCH_RESOURCE(ch, php_curl *, zid, -1, le_curl_name, le_curl);
2080 :
2081 45 : if (ch->in_callback) {
2082 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempt to close cURL handle from a callback");
2083 0 : return;
2084 : }
2085 :
2086 45 : if (ch->uses) {
2087 0 : ch->uses--;
2088 : } else {
2089 45 : zend_list_delete(Z_LVAL_PP(zid));
2090 : }
2091 : }
2092 : /* }}} */
2093 :
2094 : /* {{{ _php_curl_close()
2095 : List destructor for curl handles */
2096 : static void _php_curl_close_ex(php_curl *ch TSRMLS_DC)
2097 74 : {
2098 : #if PHP_CURL_DEBUG
2099 : fprintf(stderr, "DTOR CALLED, ch = %x\n", ch);
2100 : #endif
2101 :
2102 : /* Prevent crash inside cURL if passed file has already been closed */
2103 74 : if (ch->handlers->std_err && ch->handlers->std_err->refcount <= 0) {
2104 0 : curl_easy_setopt(ch->cp, CURLOPT_STDERR, stderr);
2105 : }
2106 :
2107 74 : curl_easy_cleanup(ch->cp);
2108 : #if LIBCURL_VERSION_NUM < 0x071101
2109 74 : zend_llist_clean(&ch->to_free.str);
2110 : #endif
2111 :
2112 : /* cURL destructors should be invoked only by last curl handle */
2113 74 : if (ch->clone->refcount <= 1) {
2114 65 : zend_llist_clean(&ch->to_free.slist);
2115 65 : zend_llist_clean(&ch->to_free.post);
2116 65 : FREE_ZVAL(ch->clone);
2117 : } else {
2118 9 : ch->clone->refcount--;
2119 9 : ch->to_free.slist.dtor = NULL;
2120 9 : ch->to_free.post.dtor = NULL;
2121 9 : zend_llist_clean(&ch->to_free.slist);
2122 9 : zend_llist_clean(&ch->to_free.post);
2123 : }
2124 :
2125 74 : if (ch->handlers->write->buf.len > 0) {
2126 32 : smart_str_free(&ch->handlers->write->buf);
2127 : }
2128 74 : if (ch->handlers->write->func_name) {
2129 1 : zval_ptr_dtor(&ch->handlers->write->func_name);
2130 : }
2131 74 : if (ch->handlers->read->func_name) {
2132 1 : zval_ptr_dtor(&ch->handlers->read->func_name);
2133 : }
2134 74 : if (ch->handlers->write_header->func_name) {
2135 1 : zval_ptr_dtor(&ch->handlers->write_header->func_name);
2136 : }
2137 74 : if (ch->handlers->passwd) {
2138 0 : zval_ptr_dtor(&ch->handlers->passwd);
2139 : }
2140 74 : if (ch->handlers->std_err) {
2141 2 : zval_ptr_dtor(&ch->handlers->std_err);
2142 : }
2143 74 : if (ch->header.str_len > 0) {
2144 0 : efree(ch->header.str);
2145 : }
2146 :
2147 74 : if (ch->handlers->write_header->stream) {
2148 0 : zval_ptr_dtor(&ch->handlers->write_header->stream);
2149 : }
2150 74 : if (ch->handlers->write->stream) {
2151 2 : zval_ptr_dtor(&ch->handlers->write->stream);
2152 : }
2153 74 : if (ch->handlers->read->stream) {
2154 2 : zval_ptr_dtor(&ch->handlers->read->stream);
2155 : }
2156 :
2157 74 : efree(ch->handlers->write);
2158 74 : efree(ch->handlers->write_header);
2159 74 : efree(ch->handlers->read);
2160 74 : efree(ch->handlers);
2161 74 : efree(ch);
2162 74 : }
2163 : /* }}} */
2164 :
2165 : /* {{{ _php_curl_close()
2166 : List destructor for curl handles */
2167 : static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC)
2168 74 : {
2169 74 : php_curl *ch = (php_curl *) rsrc->ptr;
2170 74 : _php_curl_close_ex(ch TSRMLS_CC);
2171 74 : }
2172 : /* }}} */
2173 :
2174 : #endif /* HAVE_CURL */
2175 :
2176 : /*
2177 : * Local variables:
2178 : * tab-width: 4
2179 : * c-basic-offset: 4
2180 : * End:
2181 : * vim600: fdm=marker
2182 : * vim: noet sw=4 ts=4
2183 : */
|