1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 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 6 copy immediately. | 14 +----------------------------------------------------------------------+ 15 | Author: Sterling Hughes <sterling@php.net> | 16 +----------------------------------------------------------------------+ 17*/ 18 19/* $Id$ */ 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 91int le_curl; 92int le_curl_multi_handle; 93int le_curl_share_handle; 94 95#ifdef PHP_CURL_NEED_OPENSSL_TSL /* {{{ */ 96static MUTEX_T *php_curl_openssl_tsl = NULL; 97 98static void php_curl_ssl_lock(int mode, int n, const char * file, int line) 99{ 100 if (mode & CRYPTO_LOCK) { 101 tsrm_mutex_lock(php_curl_openssl_tsl[n]); 102 } else { 103 tsrm_mutex_unlock(php_curl_openssl_tsl[n]); 104 } 105} 106 107static unsigned long php_curl_ssl_id(void) 108{ 109 return (unsigned long) tsrm_thread_id(); 110} 111#endif 112/* }}} */ 113 114#ifdef PHP_CURL_NEED_GNUTLS_TSL /* {{{ */ 115static int php_curl_ssl_mutex_create(void **m) 116{ 117 if (*((MUTEX_T *) m) = tsrm_mutex_alloc()) { 118 return SUCCESS; 119 } else { 120 return FAILURE; 121 } 122} 123 124static int php_curl_ssl_mutex_destroy(void **m) 125{ 126 tsrm_mutex_free(*((MUTEX_T *) m)); 127 return SUCCESS; 128} 129 130static int php_curl_ssl_mutex_lock(void **m) 131{ 132 return tsrm_mutex_lock(*((MUTEX_T *) m)); 133} 134 135static int php_curl_ssl_mutex_unlock(void **m) 136{ 137 return tsrm_mutex_unlock(*((MUTEX_T *) m)); 138} 139 140static struct gcry_thread_cbs php_curl_gnutls_tsl = { 141 GCRY_THREAD_OPTION_USER, 142 NULL, 143 php_curl_ssl_mutex_create, 144 php_curl_ssl_mutex_destroy, 145 php_curl_ssl_mutex_lock, 146 php_curl_ssl_mutex_unlock 147}; 148#endif 149/* }}} */ 150 151static void _php_curl_close_ex(php_curl *ch TSRMLS_DC); 152static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC); 153 154 155#define SAVE_CURL_ERROR(__handle, __err) (__handle)->err.no = (int) __err; 156 157#define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s), (long) v); 158#define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s), (double) v); 159#define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s), (char *) (v ? v : ""), 1); 160#define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s), (zval *) v); 161 162#if defined(PHP_WIN32) || defined(__GNUC__) 163# define php_curl_ret(__ret) RETVAL_FALSE; return __ret; 164#else 165# define php_curl_ret(__ret) RETVAL_FALSE; return; 166#endif 167 168static int php_curl_option_url(php_curl *ch, const char *url, const int len TSRMLS_DC) /* {{{ */ 169{ 170 CURLcode error = CURLE_OK; 171#if LIBCURL_VERSION_NUM < 0x071100 172 char *copystr = NULL; 173#endif 174 /* Disable file:// if open_basedir are used */ 175 if (PG(open_basedir) && *PG(open_basedir)) { 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 if (!(uri = php_url_parse_ex(url, len))) { 182 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid URL '%s'", url); 183 return 0; 184 } 185 186 if (uri->scheme && !strncasecmp("file", uri->scheme, sizeof("file"))) { 187 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Protocol 'file' disabled in cURL"); 188 php_url_free(uri); 189 return 0; 190 } 191 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 copystr = estrndup(url, len); 199 error = curl_easy_setopt(ch->cp, CURLOPT_URL, copystr); 200 zend_llist_add_element(&ch->to_free->str, ©str); 201#endif 202 203 return (error == CURLE_OK ? 1 : 0); 204} 205/* }}} */ 206 207int _php_curl_verify_handlers(php_curl *ch, int reporterror TSRMLS_DC) /* {{{ */ 208{ 209 php_stream *stream; 210 if (!ch || !ch->handlers) { 211 return 0; 212 } 213 214 if (ch->handlers->std_err) { 215 stream = (php_stream *) zend_fetch_resource(&ch->handlers->std_err TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream()); 216 if (stream == NULL) { 217 if (reporterror) { 218 php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_STDERR resource has gone away, resetting to stderr"); 219 } 220 zval_ptr_dtor(&ch->handlers->std_err); 221 ch->handlers->std_err = NULL; 222 223 curl_easy_setopt(ch->cp, CURLOPT_STDERR, stderr); 224 } 225 } 226 if (ch->handlers->read && ch->handlers->read->stream) { 227 stream = (php_stream *) zend_fetch_resource(&ch->handlers->read->stream TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream()); 228 if (stream == NULL) { 229 if (reporterror) { 230 php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_INFILE resource has gone away, resetting to default"); 231 } 232 zval_ptr_dtor(&ch->handlers->read->stream); 233 ch->handlers->read->fd = 0; 234 ch->handlers->read->fp = 0; 235 ch->handlers->read->stream = NULL; 236 237 curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch); 238 } 239 } 240 if (ch->handlers->write_header && ch->handlers->write_header->stream) { 241 stream = (php_stream *) zend_fetch_resource(&ch->handlers->write_header->stream TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream()); 242 if (stream == NULL) { 243 if (reporterror) { 244 php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_WRITEHEADER resource has gone away, resetting to default"); 245 } 246 zval_ptr_dtor(&ch->handlers->write_header->stream); 247 ch->handlers->write_header->fp = 0; 248 ch->handlers->write_header->stream = NULL; 249 250 ch->handlers->write_header->method = PHP_CURL_IGNORE; 251 curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch); 252 } 253 } 254 if (ch->handlers->write && ch->handlers->write->stream) { 255 stream = (php_stream *) zend_fetch_resource(&ch->handlers->write->stream TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream()); 256 if (stream == NULL) { 257 if (reporterror) { 258 php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FILE resource has gone away, resetting to default"); 259 } 260 zval_ptr_dtor(&ch->handlers->write->stream); 261 ch->handlers->write->fp = 0; 262 ch->handlers->write->stream = NULL; 263 264 ch->handlers->write->method = PHP_CURL_STDOUT; 265 curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch); 266 } 267 } 268 return 1; 269} 270/* }}} */ 271 272/* {{{ arginfo */ 273ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_version, 0, 0, 0) 274 ZEND_ARG_INFO(0, version) 275ZEND_END_ARG_INFO() 276 277ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_init, 0, 0, 0) 278 ZEND_ARG_INFO(0, url) 279ZEND_END_ARG_INFO() 280 281ZEND_BEGIN_ARG_INFO(arginfo_curl_copy_handle, 0) 282 ZEND_ARG_INFO(0, ch) 283ZEND_END_ARG_INFO() 284 285ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt, 0) 286 ZEND_ARG_INFO(0, ch) 287 ZEND_ARG_INFO(0, option) 288 ZEND_ARG_INFO(0, value) 289ZEND_END_ARG_INFO() 290 291ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt_array, 0) 292 ZEND_ARG_INFO(0, ch) 293 ZEND_ARG_ARRAY_INFO(0, options, 0) 294ZEND_END_ARG_INFO() 295 296ZEND_BEGIN_ARG_INFO(arginfo_curl_exec, 0) 297 ZEND_ARG_INFO(0, ch) 298ZEND_END_ARG_INFO() 299 300ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_getinfo, 0, 0, 1) 301 ZEND_ARG_INFO(0, ch) 302 ZEND_ARG_INFO(0, option) 303ZEND_END_ARG_INFO() 304 305ZEND_BEGIN_ARG_INFO(arginfo_curl_error, 0) 306 ZEND_ARG_INFO(0, ch) 307ZEND_END_ARG_INFO() 308 309ZEND_BEGIN_ARG_INFO(arginfo_curl_errno, 0) 310 ZEND_ARG_INFO(0, ch) 311ZEND_END_ARG_INFO() 312 313ZEND_BEGIN_ARG_INFO(arginfo_curl_close, 0) 314 ZEND_ARG_INFO(0, ch) 315ZEND_END_ARG_INFO() 316 317#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */ 318ZEND_BEGIN_ARG_INFO(arginfo_curl_reset, 0) 319 ZEND_ARG_INFO(0, ch) 320ZEND_END_ARG_INFO() 321#endif 322 323#if LIBCURL_VERSION_NUM > 0x070f03 /* 7.15.4 */ 324ZEND_BEGIN_ARG_INFO(arginfo_curl_escape, 0) 325 ZEND_ARG_INFO(0, ch) 326 ZEND_ARG_INFO(0, str) 327ZEND_END_ARG_INFO() 328 329ZEND_BEGIN_ARG_INFO(arginfo_curl_unescape, 0) 330 ZEND_ARG_INFO(0, ch) 331 ZEND_ARG_INFO(0, str) 332ZEND_END_ARG_INFO() 333 334ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_setopt, 0) 335 ZEND_ARG_INFO(0, sh) 336 ZEND_ARG_INFO(0, option) 337 ZEND_ARG_INFO(0, value) 338ZEND_END_ARG_INFO() 339#endif 340 341ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_init, 0) 342ZEND_END_ARG_INFO() 343 344ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_add_handle, 0) 345 ZEND_ARG_INFO(0, mh) 346 ZEND_ARG_INFO(0, ch) 347ZEND_END_ARG_INFO() 348 349ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_remove_handle, 0) 350 ZEND_ARG_INFO(0, mh) 351 ZEND_ARG_INFO(0, ch) 352ZEND_END_ARG_INFO() 353 354ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_select, 0, 0, 1) 355 ZEND_ARG_INFO(0, mh) 356 ZEND_ARG_INFO(0, timeout) 357ZEND_END_ARG_INFO() 358 359ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_exec, 0, 0, 1) 360 ZEND_ARG_INFO(0, mh) 361 ZEND_ARG_INFO(1, still_running) 362ZEND_END_ARG_INFO() 363 364ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_getcontent, 0) 365 ZEND_ARG_INFO(0, ch) 366ZEND_END_ARG_INFO() 367 368ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_info_read, 0, 0, 1) 369 ZEND_ARG_INFO(0, mh) 370 ZEND_ARG_INFO(1, msgs_in_queue) 371ZEND_END_ARG_INFO() 372 373ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_close, 0) 374 ZEND_ARG_INFO(0, mh) 375ZEND_END_ARG_INFO() 376 377#if LIBCURL_VERSION_NUM >= 0x070c00 /* Available since 7.12.0 */ 378ZEND_BEGIN_ARG_INFO(arginfo_curl_strerror, 0) 379 ZEND_ARG_INFO(0, errornum) 380ZEND_END_ARG_INFO() 381 382ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_strerror, 0) 383 ZEND_ARG_INFO(0, errornum) 384ZEND_END_ARG_INFO() 385#endif 386 387ZEND_BEGIN_ARG_INFO(arginfo_curl_share_init, 0) 388ZEND_END_ARG_INFO() 389 390ZEND_BEGIN_ARG_INFO(arginfo_curl_share_close, 0) 391 ZEND_ARG_INFO(0, sh) 392ZEND_END_ARG_INFO() 393 394ZEND_BEGIN_ARG_INFO(arginfo_curl_share_setopt, 0) 395 ZEND_ARG_INFO(0, sh) 396 ZEND_ARG_INFO(0, option) 397 ZEND_ARG_INFO(0, value) 398ZEND_END_ARG_INFO() 399 400#if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */ 401ZEND_BEGIN_ARG_INFO(arginfo_curl_pause, 0) 402 ZEND_ARG_INFO(0, ch) 403 ZEND_ARG_INFO(0, bitmask) 404ZEND_END_ARG_INFO() 405#endif 406 407ZEND_BEGIN_ARG_INFO_EX(arginfo_curlfile_create, 0, 0, 1) 408 ZEND_ARG_INFO(0, filename) 409 ZEND_ARG_INFO(0, mimetype) 410 ZEND_ARG_INFO(0, postname) 411ZEND_END_ARG_INFO() 412/* }}} */ 413 414/* {{{ curl_functions[] 415 */ 416const zend_function_entry curl_functions[] = { 417 PHP_FE(curl_init, arginfo_curl_init) 418 PHP_FE(curl_copy_handle, arginfo_curl_copy_handle) 419 PHP_FE(curl_version, arginfo_curl_version) 420 PHP_FE(curl_setopt, arginfo_curl_setopt) 421 PHP_FE(curl_setopt_array, arginfo_curl_setopt_array) 422 PHP_FE(curl_exec, arginfo_curl_exec) 423 PHP_FE(curl_getinfo, arginfo_curl_getinfo) 424 PHP_FE(curl_error, arginfo_curl_error) 425 PHP_FE(curl_errno, arginfo_curl_errno) 426 PHP_FE(curl_close, arginfo_curl_close) 427#if LIBCURL_VERSION_NUM >= 0x070c00 /* 7.12.0 */ 428 PHP_FE(curl_strerror, arginfo_curl_strerror) 429 PHP_FE(curl_multi_strerror, arginfo_curl_multi_strerror) 430#endif 431#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */ 432 PHP_FE(curl_reset, arginfo_curl_reset) 433#endif 434#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */ 435 PHP_FE(curl_escape, arginfo_curl_escape) 436 PHP_FE(curl_unescape, arginfo_curl_unescape) 437#endif 438#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ 439 PHP_FE(curl_pause, arginfo_curl_pause) 440#endif 441 PHP_FE(curl_multi_init, arginfo_curl_multi_init) 442 PHP_FE(curl_multi_add_handle, arginfo_curl_multi_add_handle) 443 PHP_FE(curl_multi_remove_handle, arginfo_curl_multi_remove_handle) 444 PHP_FE(curl_multi_select, arginfo_curl_multi_select) 445 PHP_FE(curl_multi_exec, arginfo_curl_multi_exec) 446 PHP_FE(curl_multi_getcontent, arginfo_curl_multi_getcontent) 447 PHP_FE(curl_multi_info_read, arginfo_curl_multi_info_read) 448 PHP_FE(curl_multi_close, arginfo_curl_multi_close) 449#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */ 450 PHP_FE(curl_multi_setopt, arginfo_curl_multi_setopt) 451#endif 452 PHP_FE(curl_share_init, arginfo_curl_share_init) 453 PHP_FE(curl_share_close, arginfo_curl_share_close) 454 PHP_FE(curl_share_setopt, arginfo_curl_share_setopt) 455 PHP_FE(curl_file_create, arginfo_curlfile_create) 456 PHP_FE_END 457}; 458/* }}} */ 459 460/* {{{ curl_module_entry 461 */ 462zend_module_entry curl_module_entry = { 463 STANDARD_MODULE_HEADER, 464 "curl", 465 curl_functions, 466 PHP_MINIT(curl), 467 PHP_MSHUTDOWN(curl), 468 NULL, 469 NULL, 470 PHP_MINFO(curl), 471 NO_VERSION_YET, 472 STANDARD_MODULE_PROPERTIES 473}; 474/* }}} */ 475 476#ifdef COMPILE_DL_CURL 477ZEND_GET_MODULE (curl) 478#endif 479 480/* {{{ PHP_INI_BEGIN */ 481PHP_INI_BEGIN() 482 PHP_INI_ENTRY("curl.cainfo", "", PHP_INI_SYSTEM, NULL) 483PHP_INI_END() 484/* }}} */ 485 486/* {{{ PHP_MINFO_FUNCTION 487 */ 488PHP_MINFO_FUNCTION(curl) 489{ 490 curl_version_info_data *d; 491 char **p; 492 char str[1024]; 493 size_t n = 0; 494 495 d = curl_version_info(CURLVERSION_NOW); 496 php_info_print_table_start(); 497 php_info_print_table_row(2, "cURL support", "enabled"); 498 php_info_print_table_row(2, "cURL Information", d->version); 499 sprintf(str, "%d", d->age); 500 php_info_print_table_row(2, "Age", str); 501 502 /* To update on each new cURL release using src/main.c in cURL sources */ 503 if (d->features) { 504 struct feat { 505 const char *name; 506 int bitmask; 507 }; 508 509 unsigned int i; 510 511 static const struct feat feats[] = { 512#if LIBCURL_VERSION_NUM >= 0x070a07 /* 7.10.7 */ 513 {"AsynchDNS", CURL_VERSION_ASYNCHDNS}, 514#endif 515#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */ 516 {"CharConv", CURL_VERSION_CONV}, 517#endif 518#if LIBCURL_VERSION_NUM >= 0x070a06 /* 7.10.6 */ 519 {"Debug", CURL_VERSION_DEBUG}, 520 {"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE}, 521#endif 522#if LIBCURL_VERSION_NUM >= 0x070c00 /* 7.12.0 */ 523 {"IDN", CURL_VERSION_IDN}, 524#endif 525 {"IPv6", CURL_VERSION_IPV6}, 526 {"krb4", CURL_VERSION_KERBEROS4}, 527#if LIBCURL_VERSION_NUM >= 0x070b01 /* 7.11.1 */ 528 {"Largefile", CURL_VERSION_LARGEFILE}, 529#endif 530 {"libz", CURL_VERSION_LIBZ}, 531#if LIBCURL_VERSION_NUM >= 0x070a06 /* 7.10.6 */ 532 {"NTLM", CURL_VERSION_NTLM}, 533#endif 534#if LIBCURL_VERSION_NUM >= 0x071600 /* 7.22.0 */ 535 {"NTLMWB", CURL_VERSION_NTLM_WB}, 536#endif 537#if LIBCURL_VERSION_NUM >= 0x070a08 /* 7.10.8 */ 538 {"SPNEGO", CURL_VERSION_SPNEGO}, 539#endif 540 {"SSL", CURL_VERSION_SSL}, 541#if LIBCURL_VERSION_NUM >= 0x070d02 /* 7.13.2 */ 542 {"SSPI", CURL_VERSION_SSPI}, 543#endif 544#if LIBCURL_VERSION_NUM >= 0x071504 /* 7.21.4 */ 545 {"TLS-SRP", CURL_VERSION_TLSAUTH_SRP}, 546#endif 547 {NULL, 0} 548 }; 549 550 php_info_print_table_row(1, "Features"); 551 for(i=0; i<sizeof(feats)/sizeof(feats[0]); i++) { 552 if (feats[i].name) { 553 php_info_print_table_row(2, feats[i].name, d->features & feats[i].bitmask ? "Yes" : "No"); 554 } 555 } 556 } 557 558 n = 0; 559 p = (char **) d->protocols; 560 while (*p != NULL) { 561 n += sprintf(str + n, "%s%s", *p, *(p + 1) != NULL ? ", " : ""); 562 p++; 563 } 564 php_info_print_table_row(2, "Protocols", str); 565 566 php_info_print_table_row(2, "Host", d->host); 567 568 if (d->ssl_version) { 569 php_info_print_table_row(2, "SSL Version", d->ssl_version); 570 } 571 572 if (d->libz_version) { 573 php_info_print_table_row(2, "ZLib Version", d->libz_version); 574 } 575 576#if defined(CURLVERSION_SECOND) && CURLVERSION_NOW >= CURLVERSION_SECOND 577 if (d->ares) { 578 php_info_print_table_row(2, "ZLib Version", d->ares); 579 } 580#endif 581 582#if defined(CURLVERSION_THIRD) && CURLVERSION_NOW >= CURLVERSION_THIRD 583 if (d->libidn) { 584 php_info_print_table_row(2, "libIDN Version", d->libidn); 585 } 586#endif 587 588#if LIBCURL_VERSION_NUM >= 0x071300 589 590 if (d->iconv_ver_num) { 591 php_info_print_table_row(2, "IconV Version", d->iconv_ver_num); 592 } 593 594 if (d->libssh_version) { 595 php_info_print_table_row(2, "libSSH Version", d->libssh_version); 596 } 597#endif 598 php_info_print_table_end(); 599} 600/* }}} */ 601 602#define REGISTER_CURL_CONSTANT(__c) REGISTER_LONG_CONSTANT(#__c, __c, CONST_CS | CONST_PERSISTENT) 603 604/* {{{ PHP_MINIT_FUNCTION 605 */ 606PHP_MINIT_FUNCTION(curl) 607{ 608 le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, "curl", module_number); 609 le_curl_multi_handle = zend_register_list_destructors_ex(_php_curl_multi_close, NULL, "curl_multi", module_number); 610 le_curl_share_handle = zend_register_list_destructors_ex(_php_curl_share_close, NULL, "curl_share", module_number); 611 612 REGISTER_INI_ENTRIES(); 613 614 /* See http://curl.haxx.se/lxr/source/docs/libcurl/symbols-in-versions 615 or curl src/docs/libcurl/symbols-in-versions for a (almost) complete list 616 of options and which version they were introduced */ 617 618 /* Constants for curl_setopt() */ 619 REGISTER_CURL_CONSTANT(CURLOPT_AUTOREFERER); 620 REGISTER_CURL_CONSTANT(CURLOPT_BINARYTRANSFER); 621 REGISTER_CURL_CONSTANT(CURLOPT_BUFFERSIZE); 622 REGISTER_CURL_CONSTANT(CURLOPT_CAINFO); 623 REGISTER_CURL_CONSTANT(CURLOPT_CAPATH); 624 REGISTER_CURL_CONSTANT(CURLOPT_CLOSEPOLICY); 625 REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT); 626 REGISTER_CURL_CONSTANT(CURLOPT_COOKIE); 627 REGISTER_CURL_CONSTANT(CURLOPT_COOKIEFILE); 628 REGISTER_CURL_CONSTANT(CURLOPT_COOKIEJAR); 629 REGISTER_CURL_CONSTANT(CURLOPT_COOKIESESSION); 630 REGISTER_CURL_CONSTANT(CURLOPT_CRLF); 631 REGISTER_CURL_CONSTANT(CURLOPT_CUSTOMREQUEST); 632 REGISTER_CURL_CONSTANT(CURLOPT_DNS_CACHE_TIMEOUT); 633 REGISTER_CURL_CONSTANT(CURLOPT_DNS_USE_GLOBAL_CACHE); 634 REGISTER_CURL_CONSTANT(CURLOPT_EGDSOCKET); 635 REGISTER_CURL_CONSTANT(CURLOPT_ENCODING); 636 REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR); 637 REGISTER_CURL_CONSTANT(CURLOPT_FILE); 638 REGISTER_CURL_CONSTANT(CURLOPT_FILETIME); 639 REGISTER_CURL_CONSTANT(CURLOPT_FOLLOWLOCATION); 640 REGISTER_CURL_CONSTANT(CURLOPT_FORBID_REUSE); 641 REGISTER_CURL_CONSTANT(CURLOPT_FRESH_CONNECT); 642 REGISTER_CURL_CONSTANT(CURLOPT_FTPAPPEND); 643 REGISTER_CURL_CONSTANT(CURLOPT_FTPLISTONLY); 644 REGISTER_CURL_CONSTANT(CURLOPT_FTPPORT); 645 REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPRT); 646 REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPSV); 647 REGISTER_CURL_CONSTANT(CURLOPT_HEADER); 648 REGISTER_CURL_CONSTANT(CURLOPT_HEADERFUNCTION); 649 REGISTER_CURL_CONSTANT(CURLOPT_HTTP200ALIASES); 650 REGISTER_CURL_CONSTANT(CURLOPT_HTTPGET); 651 REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER); 652 REGISTER_CURL_CONSTANT(CURLOPT_HTTPPROXYTUNNEL); 653 REGISTER_CURL_CONSTANT(CURLOPT_HTTP_VERSION); 654 REGISTER_CURL_CONSTANT(CURLOPT_INFILE); 655 REGISTER_CURL_CONSTANT(CURLOPT_INFILESIZE); 656 REGISTER_CURL_CONSTANT(CURLOPT_INTERFACE); 657 REGISTER_CURL_CONSTANT(CURLOPT_KRB4LEVEL); 658 REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_LIMIT); 659 REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_TIME); 660 REGISTER_CURL_CONSTANT(CURLOPT_MAXCONNECTS); 661 REGISTER_CURL_CONSTANT(CURLOPT_MAXREDIRS); 662 REGISTER_CURL_CONSTANT(CURLOPT_NETRC); 663 REGISTER_CURL_CONSTANT(CURLOPT_NOBODY); 664 REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS); 665 REGISTER_CURL_CONSTANT(CURLOPT_NOSIGNAL); 666 REGISTER_CURL_CONSTANT(CURLOPT_PORT); 667 REGISTER_CURL_CONSTANT(CURLOPT_POST); 668 REGISTER_CURL_CONSTANT(CURLOPT_POSTFIELDS); 669 REGISTER_CURL_CONSTANT(CURLOPT_POSTQUOTE); 670 REGISTER_CURL_CONSTANT(CURLOPT_PREQUOTE); 671 REGISTER_CURL_CONSTANT(CURLOPT_PRIVATE); 672 REGISTER_CURL_CONSTANT(CURLOPT_PROGRESSFUNCTION); 673 REGISTER_CURL_CONSTANT(CURLOPT_PROXY); 674 REGISTER_CURL_CONSTANT(CURLOPT_PROXYPORT); 675 REGISTER_CURL_CONSTANT(CURLOPT_PROXYTYPE); 676 REGISTER_CURL_CONSTANT(CURLOPT_PROXYUSERPWD); 677 REGISTER_CURL_CONSTANT(CURLOPT_PUT); 678 REGISTER_CURL_CONSTANT(CURLOPT_QUOTE); 679 REGISTER_CURL_CONSTANT(CURLOPT_RANDOM_FILE); 680 REGISTER_CURL_CONSTANT(CURLOPT_RANGE); 681 REGISTER_CURL_CONSTANT(CURLOPT_READDATA); 682 REGISTER_CURL_CONSTANT(CURLOPT_READFUNCTION); 683 REGISTER_CURL_CONSTANT(CURLOPT_REFERER); 684 REGISTER_CURL_CONSTANT(CURLOPT_RESUME_FROM); 685 REGISTER_CURL_CONSTANT(CURLOPT_RETURNTRANSFER); 686 REGISTER_CURL_CONSTANT(CURLOPT_SHARE); 687 REGISTER_CURL_CONSTANT(CURLOPT_SSLCERT); 688 REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTPASSWD); 689 REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTTYPE); 690 REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE); 691 REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE_DEFAULT); 692 REGISTER_CURL_CONSTANT(CURLOPT_SSLKEY); 693 REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYPASSWD); 694 REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYTYPE); 695 REGISTER_CURL_CONSTANT(CURLOPT_SSLVERSION); 696 REGISTER_CURL_CONSTANT(CURLOPT_SSL_CIPHER_LIST); 697 REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYHOST); 698 REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYPEER); 699 REGISTER_CURL_CONSTANT(CURLOPT_STDERR); 700 REGISTER_CURL_CONSTANT(CURLOPT_TELNETOPTIONS); 701 REGISTER_CURL_CONSTANT(CURLOPT_TIMECONDITION); 702 REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT); 703 REGISTER_CURL_CONSTANT(CURLOPT_TIMEVALUE); 704 REGISTER_CURL_CONSTANT(CURLOPT_TRANSFERTEXT); 705 REGISTER_CURL_CONSTANT(CURLOPT_UNRESTRICTED_AUTH); 706 REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD); 707 REGISTER_CURL_CONSTANT(CURLOPT_URL); 708 REGISTER_CURL_CONSTANT(CURLOPT_USERAGENT); 709 REGISTER_CURL_CONSTANT(CURLOPT_USERPWD); 710 REGISTER_CURL_CONSTANT(CURLOPT_VERBOSE); 711 REGISTER_CURL_CONSTANT(CURLOPT_WRITEFUNCTION); 712 REGISTER_CURL_CONSTANT(CURLOPT_WRITEHEADER); 713 714 /* Constants effecting the way CURLOPT_CLOSEPOLICY works */ 715 REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_CALLBACK); 716 REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_RECENTLY_USED); 717 REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_TRAFFIC); 718 REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_OLDEST); 719 REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_SLOWEST); 720 721 /* */ 722 REGISTER_CURL_CONSTANT(CURLE_ABORTED_BY_CALLBACK); 723 REGISTER_CURL_CONSTANT(CURLE_BAD_CALLING_ORDER); 724 REGISTER_CURL_CONSTANT(CURLE_BAD_CONTENT_ENCODING); 725 REGISTER_CURL_CONSTANT(CURLE_BAD_DOWNLOAD_RESUME); 726 REGISTER_CURL_CONSTANT(CURLE_BAD_FUNCTION_ARGUMENT); 727 REGISTER_CURL_CONSTANT(CURLE_BAD_PASSWORD_ENTERED); 728 REGISTER_CURL_CONSTANT(CURLE_COULDNT_CONNECT); 729 REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_HOST); 730 REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_PROXY); 731 REGISTER_CURL_CONSTANT(CURLE_FAILED_INIT); 732 REGISTER_CURL_CONSTANT(CURLE_FILE_COULDNT_READ_FILE); 733 REGISTER_CURL_CONSTANT(CURLE_FTP_ACCESS_DENIED); 734 REGISTER_CURL_CONSTANT(CURLE_FTP_BAD_DOWNLOAD_RESUME); 735 REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_GET_HOST); 736 REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_RECONNECT); 737 REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_GET_SIZE); 738 REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_RETR_FILE); 739 REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_ASCII); 740 REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_BINARY); 741 REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_STOR_FILE); 742 REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_USE_REST); 743 REGISTER_CURL_CONSTANT(CURLE_FTP_PARTIAL_FILE); 744 REGISTER_CURL_CONSTANT(CURLE_FTP_PORT_FAILED); 745 REGISTER_CURL_CONSTANT(CURLE_FTP_QUOTE_ERROR); 746 REGISTER_CURL_CONSTANT(CURLE_FTP_USER_PASSWORD_INCORRECT); 747 REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_227_FORMAT); 748 REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASS_REPLY); 749 REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASV_REPLY); 750 REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_SERVER_REPLY); 751 REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_USER_REPLY); 752 REGISTER_CURL_CONSTANT(CURLE_FTP_WRITE_ERROR); 753 REGISTER_CURL_CONSTANT(CURLE_FUNCTION_NOT_FOUND); 754 REGISTER_CURL_CONSTANT(CURLE_GOT_NOTHING); 755 REGISTER_CURL_CONSTANT(CURLE_HTTP_NOT_FOUND); 756 REGISTER_CURL_CONSTANT(CURLE_HTTP_PORT_FAILED); 757 REGISTER_CURL_CONSTANT(CURLE_HTTP_POST_ERROR); 758 REGISTER_CURL_CONSTANT(CURLE_HTTP_RANGE_ERROR); 759 REGISTER_CURL_CONSTANT(CURLE_HTTP_RETURNED_ERROR); 760 REGISTER_CURL_CONSTANT(CURLE_LDAP_CANNOT_BIND); 761 REGISTER_CURL_CONSTANT(CURLE_LDAP_SEARCH_FAILED); 762 REGISTER_CURL_CONSTANT(CURLE_LIBRARY_NOT_FOUND); 763 REGISTER_CURL_CONSTANT(CURLE_MALFORMAT_USER); 764 REGISTER_CURL_CONSTANT(CURLE_OBSOLETE); 765 REGISTER_CURL_CONSTANT(CURLE_OK); 766 REGISTER_CURL_CONSTANT(CURLE_OPERATION_TIMEDOUT); 767 REGISTER_CURL_CONSTANT(CURLE_OPERATION_TIMEOUTED); 768 REGISTER_CURL_CONSTANT(CURLE_OUT_OF_MEMORY); 769 REGISTER_CURL_CONSTANT(CURLE_PARTIAL_FILE); 770 REGISTER_CURL_CONSTANT(CURLE_READ_ERROR); 771 REGISTER_CURL_CONSTANT(CURLE_RECV_ERROR); 772 REGISTER_CURL_CONSTANT(CURLE_SEND_ERROR); 773 REGISTER_CURL_CONSTANT(CURLE_SHARE_IN_USE); 774 REGISTER_CURL_CONSTANT(CURLE_SSL_CACERT); 775 REGISTER_CURL_CONSTANT(CURLE_SSL_CERTPROBLEM); 776 REGISTER_CURL_CONSTANT(CURLE_SSL_CIPHER); 777 REGISTER_CURL_CONSTANT(CURLE_SSL_CONNECT_ERROR); 778 REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_NOTFOUND); 779 REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_SETFAILED); 780 REGISTER_CURL_CONSTANT(CURLE_SSL_PEER_CERTIFICATE); 781 REGISTER_CURL_CONSTANT(CURLE_TELNET_OPTION_SYNTAX); 782 REGISTER_CURL_CONSTANT(CURLE_TOO_MANY_REDIRECTS); 783 REGISTER_CURL_CONSTANT(CURLE_UNKNOWN_TELNET_OPTION); 784 REGISTER_CURL_CONSTANT(CURLE_UNSUPPORTED_PROTOCOL); 785 REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT); 786 REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT_USER); 787 REGISTER_CURL_CONSTANT(CURLE_WRITE_ERROR); 788 789 /* cURL info constants */ 790 REGISTER_CURL_CONSTANT(CURLINFO_CONNECT_TIME); 791 REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_DOWNLOAD); 792 REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_UPLOAD); 793 REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_TYPE); 794 REGISTER_CURL_CONSTANT(CURLINFO_EFFECTIVE_URL); 795 REGISTER_CURL_CONSTANT(CURLINFO_FILETIME); 796 REGISTER_CURL_CONSTANT(CURLINFO_HEADER_OUT); 797 REGISTER_CURL_CONSTANT(CURLINFO_HEADER_SIZE); 798 REGISTER_CURL_CONSTANT(CURLINFO_HTTP_CODE); 799 REGISTER_CURL_CONSTANT(CURLINFO_LASTONE); 800 REGISTER_CURL_CONSTANT(CURLINFO_NAMELOOKUP_TIME); 801 REGISTER_CURL_CONSTANT(CURLINFO_PRETRANSFER_TIME); 802 REGISTER_CURL_CONSTANT(CURLINFO_PRIVATE); 803 REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_COUNT); 804 REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_TIME); 805 REGISTER_CURL_CONSTANT(CURLINFO_REQUEST_SIZE); 806 REGISTER_CURL_CONSTANT(CURLINFO_SIZE_DOWNLOAD); 807 REGISTER_CURL_CONSTANT(CURLINFO_SIZE_UPLOAD); 808 REGISTER_CURL_CONSTANT(CURLINFO_SPEED_DOWNLOAD); 809 REGISTER_CURL_CONSTANT(CURLINFO_SPEED_UPLOAD); 810 REGISTER_CURL_CONSTANT(CURLINFO_SSL_VERIFYRESULT); 811 REGISTER_CURL_CONSTANT(CURLINFO_STARTTRANSFER_TIME); 812 REGISTER_CURL_CONSTANT(CURLINFO_TOTAL_TIME); 813 814 /* Other */ 815 REGISTER_CURL_CONSTANT(CURLMSG_DONE); 816 REGISTER_CURL_CONSTANT(CURLVERSION_NOW); 817 818 /* Curl Multi Constants */ 819 REGISTER_CURL_CONSTANT(CURLM_BAD_EASY_HANDLE); 820 REGISTER_CURL_CONSTANT(CURLM_BAD_HANDLE); 821 REGISTER_CURL_CONSTANT(CURLM_CALL_MULTI_PERFORM); 822 REGISTER_CURL_CONSTANT(CURLM_INTERNAL_ERROR); 823 REGISTER_CURL_CONSTANT(CURLM_OK); 824 REGISTER_CURL_CONSTANT(CURLM_OUT_OF_MEMORY); 825 826 /* Curl proxy constants */ 827 REGISTER_CURL_CONSTANT(CURLPROXY_HTTP); 828 REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS4); 829 REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5); 830 831 /* Curl Share constants */ 832 REGISTER_CURL_CONSTANT(CURLSHOPT_NONE); 833 REGISTER_CURL_CONSTANT(CURLSHOPT_SHARE); 834 REGISTER_CURL_CONSTANT(CURLSHOPT_UNSHARE); 835 836 /* Curl Http Version constants (CURLOPT_HTTP_VERSION) */ 837 REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_0); 838 REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_1); 839 REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_NONE); 840 841 /* Curl Lock constants */ 842 REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_COOKIE); 843 REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_DNS); 844 REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_SSL_SESSION); 845 846 /* Curl NETRC constants (CURLOPT_NETRC) */ 847 REGISTER_CURL_CONSTANT(CURL_NETRC_IGNORED); 848 REGISTER_CURL_CONSTANT(CURL_NETRC_OPTIONAL); 849 REGISTER_CURL_CONSTANT(CURL_NETRC_REQUIRED); 850 851 /* Curl SSL Version constants (CURLOPT_SSLVERSION) */ 852 REGISTER_CURL_CONSTANT(CURL_SSLVERSION_DEFAULT); 853 REGISTER_CURL_CONSTANT(CURL_SSLVERSION_SSLv2); 854 REGISTER_CURL_CONSTANT(CURL_SSLVERSION_SSLv3); 855 REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1); 856 857 /* Curl TIMECOND constants (CURLOPT_TIMECONDITION) */ 858 REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFMODSINCE); 859 REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFUNMODSINCE); 860 REGISTER_CURL_CONSTANT(CURL_TIMECOND_LASTMOD); 861 REGISTER_CURL_CONSTANT(CURL_TIMECOND_NONE); 862 863 /* Curl version constants */ 864 REGISTER_CURL_CONSTANT(CURL_VERSION_IPV6); 865 REGISTER_CURL_CONSTANT(CURL_VERSION_KERBEROS4); 866 REGISTER_CURL_CONSTANT(CURL_VERSION_LIBZ); 867 REGISTER_CURL_CONSTANT(CURL_VERSION_SSL); 868 869#if LIBCURL_VERSION_NUM >= 0x070a06 /* Available since 7.10.6 */ 870 REGISTER_CURL_CONSTANT(CURLOPT_HTTPAUTH); 871 /* http authentication options */ 872 REGISTER_CURL_CONSTANT(CURLAUTH_ANY); 873 REGISTER_CURL_CONSTANT(CURLAUTH_ANYSAFE); 874 REGISTER_CURL_CONSTANT(CURLAUTH_BASIC); 875 REGISTER_CURL_CONSTANT(CURLAUTH_DIGEST); 876 REGISTER_CURL_CONSTANT(CURLAUTH_GSSNEGOTIATE); 877 REGISTER_CURL_CONSTANT(CURLAUTH_NONE); 878 REGISTER_CURL_CONSTANT(CURLAUTH_NTLM); 879#endif 880 881#if LIBCURL_VERSION_NUM >= 0x070a07 /* Available since 7.10.7 */ 882 REGISTER_CURL_CONSTANT(CURLINFO_HTTP_CONNECTCODE); 883 REGISTER_CURL_CONSTANT(CURLOPT_FTP_CREATE_MISSING_DIRS); 884 REGISTER_CURL_CONSTANT(CURLOPT_PROXYAUTH); 885#endif 886 887#if LIBCURL_VERSION_NUM >= 0x070a08 /* Available since 7.10.8 */ 888 REGISTER_CURL_CONSTANT(CURLE_FILESIZE_EXCEEDED); 889 REGISTER_CURL_CONSTANT(CURLE_LDAP_INVALID_URL); 890 REGISTER_CURL_CONSTANT(CURLINFO_HTTPAUTH_AVAIL); 891 REGISTER_CURL_CONSTANT(CURLINFO_RESPONSE_CODE); 892 REGISTER_CURL_CONSTANT(CURLINFO_PROXYAUTH_AVAIL); 893 REGISTER_CURL_CONSTANT(CURLOPT_FTP_RESPONSE_TIMEOUT); 894 REGISTER_CURL_CONSTANT(CURLOPT_IPRESOLVE); 895 REGISTER_CURL_CONSTANT(CURLOPT_MAXFILESIZE); 896 REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V4); 897 REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V6); 898 REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_WHATEVER); 899#endif 900 901#if LIBCURL_VERSION_NUM >= 0x070b00 /* Available since 7.11.0 */ 902 REGISTER_CURL_CONSTANT(CURLE_FTP_SSL_FAILED); 903 REGISTER_CURL_CONSTANT(CURLFTPSSL_ALL); 904 REGISTER_CURL_CONSTANT(CURLFTPSSL_CONTROL); 905 REGISTER_CURL_CONSTANT(CURLFTPSSL_NONE); 906 REGISTER_CURL_CONSTANT(CURLFTPSSL_TRY); 907 REGISTER_CURL_CONSTANT(CURLOPT_FTP_SSL); 908 REGISTER_CURL_CONSTANT(CURLOPT_NETRC_FILE); 909#endif 910 911#if LIBCURL_VERSION_NUM >= 0x070c02 /* Available since 7.12.2 */ 912 REGISTER_CURL_CONSTANT(CURLFTPAUTH_DEFAULT); 913 REGISTER_CURL_CONSTANT(CURLFTPAUTH_SSL); 914 REGISTER_CURL_CONSTANT(CURLFTPAUTH_TLS); 915 REGISTER_CURL_CONSTANT(CURLOPT_FTPSSLAUTH); 916#endif 917 918#if LIBCURL_VERSION_NUM >= 0x070d00 /* Available since 7.13.0 */ 919 REGISTER_CURL_CONSTANT(CURLOPT_FTP_ACCOUNT); 920#endif 921 922#if LIBCURL_VERSION_NUM >= 0x070b02 /* Available since 7.11.2 */ 923 REGISTER_CURL_CONSTANT(CURLOPT_TCP_NODELAY); 924#endif 925 926#if LIBCURL_VERSION_NUM >= 0x070c02 /* Available since 7.12.2 */ 927 REGISTER_CURL_CONSTANT(CURLINFO_OS_ERRNO); 928#endif 929 930#if LIBCURL_VERSION_NUM >= 0x070c03 /* Available since 7.12.3 */ 931 REGISTER_CURL_CONSTANT(CURLINFO_NUM_CONNECTS); 932 REGISTER_CURL_CONSTANT(CURLINFO_SSL_ENGINES); 933#endif 934 935#if LIBCURL_VERSION_NUM >= 0x070e01 /* Available since 7.14.1 */ 936 REGISTER_CURL_CONSTANT(CURLINFO_COOKIELIST); 937 REGISTER_CURL_CONSTANT(CURLOPT_COOKIELIST); 938 REGISTER_CURL_CONSTANT(CURLOPT_IGNORE_CONTENT_LENGTH); 939#endif 940 941#if LIBCURL_VERSION_NUM >= 0x070f00 /* Available since 7.15.0 */ 942 REGISTER_CURL_CONSTANT(CURLOPT_FTP_SKIP_PASV_IP); 943#endif 944 945#if LIBCURL_VERSION_NUM >= 0x070f01 /* Available since 7.15.1 */ 946 REGISTER_CURL_CONSTANT(CURLOPT_FTP_FILEMETHOD); 947#endif 948 949#if LIBCURL_VERSION_NUM >= 0x070f02 /* Available since 7.15.2 */ 950 REGISTER_CURL_CONSTANT(CURLOPT_CONNECT_ONLY); 951 REGISTER_CURL_CONSTANT(CURLOPT_LOCALPORT); 952 REGISTER_CURL_CONSTANT(CURLOPT_LOCALPORTRANGE); 953#endif 954 955#if LIBCURL_VERSION_NUM >= 0x070f03 /* Available since 7.15.3 */ 956 REGISTER_CURL_CONSTANT(CURLFTPMETHOD_MULTICWD); 957 REGISTER_CURL_CONSTANT(CURLFTPMETHOD_NOCWD); 958 REGISTER_CURL_CONSTANT(CURLFTPMETHOD_SINGLECWD); 959#endif 960 961#if LIBCURL_VERSION_NUM >- 0x070f04 /* Available since 7.15.4 */ 962 REGISTER_CURL_CONSTANT(CURLINFO_FTP_ENTRY_PATH); 963#endif 964 965#if LIBCURL_VERSION_NUM >= 0x070f05 /* Available since 7.15.5 */ 966 REGISTER_CURL_CONSTANT(CURLOPT_FTP_ALTERNATIVE_TO_USER); 967 REGISTER_CURL_CONSTANT(CURLOPT_MAX_RECV_SPEED_LARGE); 968 REGISTER_CURL_CONSTANT(CURLOPT_MAX_SEND_SPEED_LARGE); 969#endif 970 971#if LIBCURL_VERSION_NUM >= 0x071000 /* Available since 7.16.0 */ 972 REGISTER_CURL_CONSTANT(CURLOPT_SSL_SESSIONID_CACHE); 973 REGISTER_CURL_CONSTANT(CURLMOPT_PIPELINING); 974#endif 975 976#if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */ 977 REGISTER_CURL_CONSTANT(CURLE_SSH); 978 REGISTER_CURL_CONSTANT(CURLOPT_FTP_SSL_CCC); 979 REGISTER_CURL_CONSTANT(CURLOPT_SSH_AUTH_TYPES); 980 REGISTER_CURL_CONSTANT(CURLOPT_SSH_PRIVATE_KEYFILE); 981 REGISTER_CURL_CONSTANT(CURLOPT_SSH_PUBLIC_KEYFILE); 982 REGISTER_CURL_CONSTANT(CURLFTPSSL_CCC_ACTIVE); 983 REGISTER_CURL_CONSTANT(CURLFTPSSL_CCC_NONE); 984 REGISTER_CURL_CONSTANT(CURLFTPSSL_CCC_PASSIVE); 985#endif 986 987#if LIBCURL_VERSION_NUM >= 0x071002 /* Available since 7.16.2 */ 988 REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT_MS); 989 REGISTER_CURL_CONSTANT(CURLOPT_HTTP_CONTENT_DECODING); 990 REGISTER_CURL_CONSTANT(CURLOPT_HTTP_TRANSFER_DECODING); 991 REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT_MS); 992#endif 993 994#if LIBCURL_VERSION_NUM >= 0x071003 /* Available since 7.16.3 */ 995 REGISTER_CURL_CONSTANT(CURLMOPT_MAXCONNECTS); 996#endif 997 998#if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */ 999 REGISTER_CURL_CONSTANT(CURLOPT_KRBLEVEL); 1000 REGISTER_CURL_CONSTANT(CURLOPT_NEW_DIRECTORY_PERMS); 1001 REGISTER_CURL_CONSTANT(CURLOPT_NEW_FILE_PERMS); 1002#endif 1003 1004#if LIBCURL_VERSION_NUM >= 0x071100 /* Available since 7.17.0 */ 1005 REGISTER_CURL_CONSTANT(CURLOPT_APPEND); 1006 REGISTER_CURL_CONSTANT(CURLOPT_DIRLISTONLY); 1007 REGISTER_CURL_CONSTANT(CURLOPT_USE_SSL); 1008 /* Curl SSL Constants */ 1009 REGISTER_CURL_CONSTANT(CURLUSESSL_ALL); 1010 REGISTER_CURL_CONSTANT(CURLUSESSL_CONTROL); 1011 REGISTER_CURL_CONSTANT(CURLUSESSL_NONE); 1012 REGISTER_CURL_CONSTANT(CURLUSESSL_TRY); 1013#endif 1014 1015#if LIBCURL_VERSION_NUM >= 0x071101 /* Available since 7.17.1 */ 1016 REGISTER_CURL_CONSTANT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5); 1017#endif 1018 1019#if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */ 1020 REGISTER_CURL_CONSTANT(CURLOPT_PROXY_TRANSFER_MODE); 1021 REGISTER_CURL_CONSTANT(CURLPAUSE_ALL); 1022 REGISTER_CURL_CONSTANT(CURLPAUSE_CONT); 1023 REGISTER_CURL_CONSTANT(CURLPAUSE_RECV); 1024 REGISTER_CURL_CONSTANT(CURLPAUSE_RECV_CONT); 1025 REGISTER_CURL_CONSTANT(CURLPAUSE_SEND); 1026 REGISTER_CURL_CONSTANT(CURLPAUSE_SEND_CONT); 1027 REGISTER_CURL_CONSTANT(CURL_READFUNC_PAUSE); 1028 REGISTER_CURL_CONSTANT(CURL_WRITEFUNC_PAUSE); 1029#endif 1030 1031#if LIBCURL_VERSION_NUM >= 0x071202 /* Available since 7.18.2 */ 1032 REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_URL); 1033#endif 1034 1035#if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */ 1036 REGISTER_CURL_CONSTANT(CURLINFO_APPCONNECT_TIME); 1037 REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_IP); 1038 1039 REGISTER_CURL_CONSTANT(CURLOPT_ADDRESS_SCOPE); 1040 REGISTER_CURL_CONSTANT(CURLOPT_CRLFILE); 1041 REGISTER_CURL_CONSTANT(CURLOPT_ISSUERCERT); 1042 REGISTER_CURL_CONSTANT(CURLOPT_KEYPASSWD); 1043 1044 REGISTER_CURL_CONSTANT(CURLSSH_AUTH_ANY); 1045 REGISTER_CURL_CONSTANT(CURLSSH_AUTH_DEFAULT); 1046 REGISTER_CURL_CONSTANT(CURLSSH_AUTH_HOST); 1047 REGISTER_CURL_CONSTANT(CURLSSH_AUTH_KEYBOARD); 1048 REGISTER_CURL_CONSTANT(CURLSSH_AUTH_NONE); 1049 REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PASSWORD); 1050 REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PUBLICKEY); 1051#endif 1052 1053#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ 1054 REGISTER_CURL_CONSTANT(CURLINFO_CERTINFO); 1055 REGISTER_CURL_CONSTANT(CURLOPT_CERTINFO); 1056 REGISTER_CURL_CONSTANT(CURLOPT_PASSWORD); 1057 REGISTER_CURL_CONSTANT(CURLOPT_POSTREDIR); 1058 REGISTER_CURL_CONSTANT(CURLOPT_PROXYPASSWORD); 1059 REGISTER_CURL_CONSTANT(CURLOPT_PROXYUSERNAME); 1060 REGISTER_CURL_CONSTANT(CURLOPT_USERNAME); 1061#endif 1062 1063#if LIBCURL_VERSION_NUM >= 0x071303 /* Available since 7.19.3 */ 1064 REGISTER_CURL_CONSTANT(CURLAUTH_DIGEST_IE); 1065#endif 1066 1067#if LIBCURL_VERSION_NUM >= 0x071304 /* Available since 7.19.4 */ 1068 REGISTER_CURL_CONSTANT(CURLINFO_CONDITION_UNMET); 1069 1070 REGISTER_CURL_CONSTANT(CURLOPT_NOPROXY); 1071 REGISTER_CURL_CONSTANT(CURLOPT_PROTOCOLS); 1072 REGISTER_CURL_CONSTANT(CURLOPT_REDIR_PROTOCOLS); 1073 REGISTER_CURL_CONSTANT(CURLOPT_SOCKS5_GSSAPI_NEC); 1074 REGISTER_CURL_CONSTANT(CURLOPT_SOCKS5_GSSAPI_SERVICE); 1075 REGISTER_CURL_CONSTANT(CURLOPT_TFTP_BLKSIZE); 1076 1077 REGISTER_CURL_CONSTANT(CURLPROTO_ALL); 1078 REGISTER_CURL_CONSTANT(CURLPROTO_DICT); 1079 REGISTER_CURL_CONSTANT(CURLPROTO_FILE); 1080 REGISTER_CURL_CONSTANT(CURLPROTO_FTP); 1081 REGISTER_CURL_CONSTANT(CURLPROTO_FTPS); 1082 REGISTER_CURL_CONSTANT(CURLPROTO_HTTP); 1083 REGISTER_CURL_CONSTANT(CURLPROTO_HTTPS); 1084 REGISTER_CURL_CONSTANT(CURLPROTO_LDAP); 1085 REGISTER_CURL_CONSTANT(CURLPROTO_LDAPS); 1086 REGISTER_CURL_CONSTANT(CURLPROTO_SCP); 1087 REGISTER_CURL_CONSTANT(CURLPROTO_SFTP); 1088 REGISTER_CURL_CONSTANT(CURLPROTO_TELNET); 1089 REGISTER_CURL_CONSTANT(CURLPROTO_TFTP); 1090#endif 1091 1092#if LIBCURL_VERSION_NUM >= 0x071306 /* Available since 7.19.6 */ 1093 REGISTER_CURL_CONSTANT(CURLOPT_SSH_KNOWNHOSTS); 1094#endif 1095 1096#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */ 1097 REGISTER_CURL_CONSTANT(CURLINFO_RTSP_CLIENT_CSEQ); 1098 REGISTER_CURL_CONSTANT(CURLINFO_RTSP_CSEQ_RECV); 1099 REGISTER_CURL_CONSTANT(CURLINFO_RTSP_SERVER_CSEQ); 1100 REGISTER_CURL_CONSTANT(CURLINFO_RTSP_SESSION_ID); 1101 REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_PRET); 1102 REGISTER_CURL_CONSTANT(CURLOPT_MAIL_FROM); 1103 REGISTER_CURL_CONSTANT(CURLOPT_MAIL_RCPT); 1104 REGISTER_CURL_CONSTANT(CURLOPT_RTSP_CLIENT_CSEQ); 1105 REGISTER_CURL_CONSTANT(CURLOPT_RTSP_REQUEST); 1106 REGISTER_CURL_CONSTANT(CURLOPT_RTSP_SERVER_CSEQ); 1107 REGISTER_CURL_CONSTANT(CURLOPT_RTSP_SESSION_ID); 1108 REGISTER_CURL_CONSTANT(CURLOPT_RTSP_STREAM_URI); 1109 REGISTER_CURL_CONSTANT(CURLOPT_RTSP_TRANSPORT); 1110 REGISTER_CURL_CONSTANT(CURLPROTO_IMAP); 1111 REGISTER_CURL_CONSTANT(CURLPROTO_IMAPS); 1112 REGISTER_CURL_CONSTANT(CURLPROTO_POP3); 1113 REGISTER_CURL_CONSTANT(CURLPROTO_POP3S); 1114 REGISTER_CURL_CONSTANT(CURLPROTO_RTSP); 1115 REGISTER_CURL_CONSTANT(CURLPROTO_SMTP); 1116 REGISTER_CURL_CONSTANT(CURLPROTO_SMTPS); 1117 REGISTER_CURL_CONSTANT(CURL_RTSPREQ_ANNOUNCE); 1118 REGISTER_CURL_CONSTANT(CURL_RTSPREQ_DESCRIBE); 1119 REGISTER_CURL_CONSTANT(CURL_RTSPREQ_GET_PARAMETER); 1120 REGISTER_CURL_CONSTANT(CURL_RTSPREQ_OPTIONS); 1121 REGISTER_CURL_CONSTANT(CURL_RTSPREQ_PAUSE); 1122 REGISTER_CURL_CONSTANT(CURL_RTSPREQ_PLAY); 1123 REGISTER_CURL_CONSTANT(CURL_RTSPREQ_RECEIVE); 1124 REGISTER_CURL_CONSTANT(CURL_RTSPREQ_RECORD); 1125 REGISTER_CURL_CONSTANT(CURL_RTSPREQ_SETUP); 1126 REGISTER_CURL_CONSTANT(CURL_RTSPREQ_SET_PARAMETER); 1127 REGISTER_CURL_CONSTANT(CURL_RTSPREQ_TEARDOWN); 1128#endif 1129 1130#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ 1131 REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_IP); 1132 REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_PORT); 1133 REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_PORT); 1134 REGISTER_CURL_CONSTANT(CURLOPT_FNMATCH_FUNCTION); 1135 REGISTER_CURL_CONSTANT(CURLOPT_WILDCARDMATCH); 1136 REGISTER_CURL_CONSTANT(CURLPROTO_RTMP); 1137 REGISTER_CURL_CONSTANT(CURLPROTO_RTMPE); 1138 REGISTER_CURL_CONSTANT(CURLPROTO_RTMPS); 1139 REGISTER_CURL_CONSTANT(CURLPROTO_RTMPT); 1140 REGISTER_CURL_CONSTANT(CURLPROTO_RTMPTE); 1141 REGISTER_CURL_CONSTANT(CURLPROTO_RTMPTS); 1142 REGISTER_CURL_CONSTANT(CURL_FNMATCHFUNC_FAIL); 1143 REGISTER_CURL_CONSTANT(CURL_FNMATCHFUNC_MATCH); 1144 REGISTER_CURL_CONSTANT(CURL_FNMATCHFUNC_NOMATCH); 1145#endif 1146 1147#if LIBCURL_VERSION_NUM >= 0x071502 /* Available since 7.21.2 */ 1148 REGISTER_CURL_CONSTANT(CURLPROTO_GOPHER); 1149#endif 1150 1151#if LIBCURL_VERSION_NUM >= 0x071503 /* Available since 7.21.3 */ 1152 REGISTER_CURL_CONSTANT(CURLAUTH_ONLY); 1153 REGISTER_CURL_CONSTANT(CURLOPT_RESOLVE); 1154#endif 1155 1156#if LIBCURL_VERSION_NUM >= 0x071504 /* Available since 7.21.4 */ 1157 REGISTER_CURL_CONSTANT(CURLOPT_TLSAUTH_PASSWORD); 1158 REGISTER_CURL_CONSTANT(CURLOPT_TLSAUTH_TYPE); 1159 REGISTER_CURL_CONSTANT(CURLOPT_TLSAUTH_USERNAME); 1160 REGISTER_CURL_CONSTANT(CURL_TLSAUTH_SRP); 1161#endif 1162 1163#if LIBCURL_VERSION_NUM >= 0x071506 /* Available since 7.21.6 */ 1164 REGISTER_CURL_CONSTANT(CURLOPT_ACCEPT_ENCODING); 1165 REGISTER_CURL_CONSTANT(CURLOPT_TRANSFER_ENCODING); 1166#endif 1167 1168#if LIBCURL_VERSION_NUM >= 0x071600 /* Available since 7.22.0 */ 1169 REGISTER_CURL_CONSTANT(CURLGSSAPI_DELEGATION_FLAG); 1170 REGISTER_CURL_CONSTANT(CURLGSSAPI_DELEGATION_POLICY_FLAG); 1171 REGISTER_CURL_CONSTANT(CURLOPT_GSSAPI_DELEGATION); 1172#endif 1173 1174#if LIBCURL_VERSION_NUM >= 0x071800 /* Available since 7.24.0 */ 1175 REGISTER_CURL_CONSTANT(CURLOPT_ACCEPTTIMEOUT_MS); 1176 REGISTER_CURL_CONSTANT(CURLOPT_DNS_SERVERS); 1177#endif 1178 1179#if LIBCURL_VERSION_NUM >= 0x071900 /* Available since 7.25.0 */ 1180 REGISTER_CURL_CONSTANT(CURLOPT_MAIL_AUTH); 1181 REGISTER_CURL_CONSTANT(CURLOPT_SSL_OPTIONS); 1182 REGISTER_CURL_CONSTANT(CURLOPT_TCP_KEEPALIVE); 1183 REGISTER_CURL_CONSTANT(CURLOPT_TCP_KEEPIDLE); 1184 REGISTER_CURL_CONSTANT(CURLOPT_TCP_KEEPINTVL); 1185 REGISTER_CURL_CONSTANT(CURLSSLOPT_ALLOW_BEAST); 1186#endif 1187 1188#if CURLOPT_FTPASCII != 0 1189 REGISTER_CURL_CONSTANT(CURLOPT_FTPASCII); 1190#endif 1191#if CURLOPT_MUTE != 0 1192 REGISTER_CURL_CONSTANT(CURLOPT_MUTE); 1193#endif 1194#if CURLOPT_PASSWDFUNCTION != 0 1195 REGISTER_CURL_CONSTANT(CURLOPT_PASSWDFUNCTION); 1196#endif 1197 REGISTER_CURL_CONSTANT(CURLOPT_SAFE_UPLOAD); 1198 1199#ifdef PHP_CURL_NEED_OPENSSL_TSL 1200 if (!CRYPTO_get_id_callback()) { 1201 int i, c = CRYPTO_num_locks(); 1202 1203 php_curl_openssl_tsl = malloc(c * sizeof(MUTEX_T)); 1204 if (!php_curl_openssl_tsl) { 1205 return FAILURE; 1206 } 1207 1208 for (i = 0; i < c; ++i) { 1209 php_curl_openssl_tsl[i] = tsrm_mutex_alloc(); 1210 } 1211 1212 CRYPTO_set_id_callback(php_curl_ssl_id); 1213 CRYPTO_set_locking_callback(php_curl_ssl_lock); 1214 } 1215#endif 1216#ifdef PHP_CURL_NEED_GNUTLS_TSL 1217 gcry_control(GCRYCTL_SET_THREAD_CBS, &php_curl_gnutls_tsl); 1218#endif 1219 1220 if (curl_global_init(CURL_GLOBAL_SSL) != CURLE_OK) { 1221 return FAILURE; 1222 } 1223 1224 curlfile_register_class(TSRMLS_C); 1225 1226 return SUCCESS; 1227} 1228/* }}} */ 1229 1230/* {{{ PHP_MSHUTDOWN_FUNCTION 1231 */ 1232PHP_MSHUTDOWN_FUNCTION(curl) 1233{ 1234 curl_global_cleanup(); 1235#ifdef PHP_CURL_NEED_OPENSSL_TSL 1236 if (php_curl_openssl_tsl) { 1237 int i, c = CRYPTO_num_locks(); 1238 1239 CRYPTO_set_id_callback(NULL); 1240 CRYPTO_set_locking_callback(NULL); 1241 1242 for (i = 0; i < c; ++i) { 1243 tsrm_mutex_free(php_curl_openssl_tsl[i]); 1244 } 1245 1246 free(php_curl_openssl_tsl); 1247 php_curl_openssl_tsl = NULL; 1248 } 1249#endif 1250 UNREGISTER_INI_ENTRIES(); 1251 return SUCCESS; 1252} 1253/* }}} */ 1254 1255/* {{{ curl_write_nothing 1256 * Used as a work around. See _php_curl_close_ex 1257 */ 1258static size_t curl_write_nothing(char *data, size_t size, size_t nmemb, void *ctx) 1259{ 1260 return size * nmemb; 1261} 1262/* }}} */ 1263 1264/* {{{ curl_write 1265 */ 1266static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx) 1267{ 1268 php_curl *ch = (php_curl *) ctx; 1269 php_curl_write *t = ch->handlers->write; 1270 size_t length = size * nmemb; 1271 TSRMLS_FETCH_FROM_CTX(ch->thread_ctx); 1272 1273#if PHP_CURL_DEBUG 1274 fprintf(stderr, "curl_write() called\n"); 1275 fprintf(stderr, "data = %s, size = %d, nmemb = %d, ctx = %x\n", data, size, nmemb, ctx); 1276#endif 1277 1278 switch (t->method) { 1279 case PHP_CURL_STDOUT: 1280 PHPWRITE(data, length); 1281 break; 1282 case PHP_CURL_FILE: 1283 return fwrite(data, size, nmemb, t->fp); 1284 case PHP_CURL_RETURN: 1285 if (length > 0) { 1286 smart_str_appendl(&t->buf, data, (int) length); 1287 } 1288 break; 1289 case PHP_CURL_USER: { 1290 zval **argv[2]; 1291 zval *retval_ptr = NULL; 1292 zval *handle = NULL; 1293 zval *zdata = NULL; 1294 int error; 1295 zend_fcall_info fci; 1296 1297 MAKE_STD_ZVAL(handle); 1298 ZVAL_RESOURCE(handle, ch->id); 1299 zend_list_addref(ch->id); 1300 argv[0] = &handle; 1301 1302 MAKE_STD_ZVAL(zdata); 1303 ZVAL_STRINGL(zdata, data, length, 1); 1304 argv[1] = &zdata; 1305 1306 fci.size = sizeof(fci); 1307 fci.function_table = EG(function_table); 1308 fci.object_ptr = NULL; 1309 fci.function_name = t->func_name; 1310 fci.retval_ptr_ptr = &retval_ptr; 1311 fci.param_count = 2; 1312 fci.params = argv; 1313 fci.no_separation = 0; 1314 fci.symbol_table = NULL; 1315 1316 ch->in_callback = 1; 1317 error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC); 1318 ch->in_callback = 0; 1319 if (error == FAILURE) { 1320 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION"); 1321 length = -1; 1322 } else if (retval_ptr) { 1323 if (Z_TYPE_P(retval_ptr) != IS_LONG) { 1324 convert_to_long_ex(&retval_ptr); 1325 } 1326 length = Z_LVAL_P(retval_ptr); 1327 zval_ptr_dtor(&retval_ptr); 1328 } 1329 1330 zval_ptr_dtor(argv[0]); 1331 zval_ptr_dtor(argv[1]); 1332 break; 1333 } 1334 } 1335 1336 return length; 1337} 1338/* }}} */ 1339 1340#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ 1341/* {{{ curl_fnmatch 1342 */ 1343static int curl_fnmatch(void *ctx, const char *pattern, const char *string) 1344{ 1345 php_curl *ch = (php_curl *) ctx; 1346 php_curl_fnmatch *t = ch->handlers->fnmatch; 1347 int rval = CURL_FNMATCHFUNC_FAIL; 1348 switch (t->method) { 1349 case PHP_CURL_USER: { 1350 zval **argv[3]; 1351 zval *zhandle = NULL; 1352 zval *zpattern = NULL; 1353 zval *zstring = NULL; 1354 zval *retval_ptr; 1355 int error; 1356 zend_fcall_info fci; 1357 TSRMLS_FETCH_FROM_CTX(ch->thread_ctx); 1358 1359 MAKE_STD_ZVAL(zhandle); 1360 MAKE_STD_ZVAL(zpattern); 1361 MAKE_STD_ZVAL(zstring); 1362 1363 ZVAL_RESOURCE(zhandle, ch->id); 1364 zend_list_addref(ch->id); 1365 ZVAL_STRING(zpattern, pattern, 1); 1366 ZVAL_STRING(zstring, string, 1); 1367 1368 argv[0] = &zhandle; 1369 argv[1] = &zpattern; 1370 argv[2] = &zstring; 1371 1372 fci.size = sizeof(fci); 1373 fci.function_table = EG(function_table); 1374 fci.function_name = t->func_name; 1375 fci.object_ptr = NULL; 1376 fci.retval_ptr_ptr = &retval_ptr; 1377 fci.param_count = 3; 1378 fci.params = argv; 1379 fci.no_separation = 0; 1380 fci.symbol_table = NULL; 1381 1382 ch->in_callback = 1; 1383 error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC); 1384 ch->in_callback = 0; 1385 if (error == FAILURE) { 1386 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_FNMATCH_FUNCTION"); 1387 } else if (retval_ptr) { 1388 if (Z_TYPE_P(retval_ptr) != IS_LONG) { 1389 convert_to_long_ex(&retval_ptr); 1390 } 1391 rval = Z_LVAL_P(retval_ptr); 1392 zval_ptr_dtor(&retval_ptr); 1393 } 1394 zval_ptr_dtor(argv[0]); 1395 zval_ptr_dtor(argv[1]); 1396 zval_ptr_dtor(argv[2]); 1397 break; 1398 } 1399 } 1400 return rval; 1401} 1402/* }}} */ 1403#endif 1404 1405/* {{{ curl_progress 1406 */ 1407static size_t curl_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) 1408{ 1409 php_curl *ch = (php_curl *) clientp; 1410 php_curl_progress *t = ch->handlers->progress; 1411 size_t rval = 0; 1412 1413#if PHP_CURL_DEBUG 1414 fprintf(stderr, "curl_progress() called\n"); 1415 fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow); 1416#endif 1417 1418 switch (t->method) { 1419 case PHP_CURL_USER: { 1420 zval **argv[5]; 1421 zval *handle = NULL; 1422 zval *zdltotal = NULL; 1423 zval *zdlnow = NULL; 1424 zval *zultotal = NULL; 1425 zval *zulnow = NULL; 1426 zval *retval_ptr; 1427 int error; 1428 zend_fcall_info fci; 1429 TSRMLS_FETCH_FROM_CTX(ch->thread_ctx); 1430 1431 MAKE_STD_ZVAL(handle); 1432 MAKE_STD_ZVAL(zdltotal); 1433 MAKE_STD_ZVAL(zdlnow); 1434 MAKE_STD_ZVAL(zultotal); 1435 MAKE_STD_ZVAL(zulnow); 1436 1437 ZVAL_RESOURCE(handle, ch->id); 1438 zend_list_addref(ch->id); 1439 ZVAL_LONG(zdltotal, (long) dltotal); 1440 ZVAL_LONG(zdlnow, (long) dlnow); 1441 ZVAL_LONG(zultotal, (long) ultotal); 1442 ZVAL_LONG(zulnow, (long) ulnow); 1443 1444 argv[0] = &handle; 1445 argv[1] = &zdltotal; 1446 argv[2] = &zdlnow; 1447 argv[3] = &zultotal; 1448 argv[4] = &zulnow; 1449 1450 fci.size = sizeof(fci); 1451 fci.function_table = EG(function_table); 1452 fci.function_name = t->func_name; 1453 fci.object_ptr = NULL; 1454 fci.retval_ptr_ptr = &retval_ptr; 1455 fci.param_count = 5; 1456 fci.params = argv; 1457 fci.no_separation = 0; 1458 fci.symbol_table = NULL; 1459 1460 ch->in_callback = 1; 1461 error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC); 1462 ch->in_callback = 0; 1463 if (error == FAILURE) { 1464 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_PROGRESSFUNCTION"); 1465 } else if (retval_ptr) { 1466 if (Z_TYPE_P(retval_ptr) != IS_LONG) { 1467 convert_to_long_ex(&retval_ptr); 1468 } 1469 if (0 != Z_LVAL_P(retval_ptr)) { 1470 rval = 1; 1471 } 1472 zval_ptr_dtor(&retval_ptr); 1473 } 1474 zval_ptr_dtor(argv[0]); 1475 zval_ptr_dtor(argv[1]); 1476 zval_ptr_dtor(argv[2]); 1477 zval_ptr_dtor(argv[3]); 1478 zval_ptr_dtor(argv[4]); 1479 break; 1480 } 1481 } 1482 return rval; 1483} 1484/* }}} */ 1485 1486/* {{{ curl_read 1487 */ 1488static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx) 1489{ 1490 php_curl *ch = (php_curl *) ctx; 1491 php_curl_read *t = ch->handlers->read; 1492 int length = 0; 1493 1494 switch (t->method) { 1495 case PHP_CURL_DIRECT: 1496 if (t->fp) { 1497 length = fread(data, size, nmemb, t->fp); 1498 } 1499 break; 1500 case PHP_CURL_USER: { 1501 zval **argv[3]; 1502 zval *handle = NULL; 1503 zval *zfd = NULL; 1504 zval *zlength = NULL; 1505 zval *retval_ptr; 1506 int error; 1507 zend_fcall_info fci; 1508 TSRMLS_FETCH_FROM_CTX(ch->thread_ctx); 1509 1510 MAKE_STD_ZVAL(handle); 1511 MAKE_STD_ZVAL(zfd); 1512 MAKE_STD_ZVAL(zlength); 1513 1514 ZVAL_RESOURCE(handle, ch->id); 1515 zend_list_addref(ch->id); 1516 ZVAL_RESOURCE(zfd, t->fd); 1517 zend_list_addref(t->fd); 1518 ZVAL_LONG(zlength, (int) size * nmemb); 1519 1520 argv[0] = &handle; 1521 argv[1] = &zfd; 1522 argv[2] = &zlength; 1523 1524 fci.size = sizeof(fci); 1525 fci.function_table = EG(function_table); 1526 fci.function_name = t->func_name; 1527 fci.object_ptr = NULL; 1528 fci.retval_ptr_ptr = &retval_ptr; 1529 fci.param_count = 3; 1530 fci.params = argv; 1531 fci.no_separation = 0; 1532 fci.symbol_table = NULL; 1533 1534 ch->in_callback = 1; 1535 error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC); 1536 ch->in_callback = 0; 1537 if (error == FAILURE) { 1538 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_READFUNCTION"); 1539#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */ 1540 length = CURL_READFUNC_ABORT; 1541#endif 1542 } else if (retval_ptr) { 1543 if (Z_TYPE_P(retval_ptr) == IS_STRING) { 1544 length = MIN((int) (size * nmemb), Z_STRLEN_P(retval_ptr)); 1545 memcpy(data, Z_STRVAL_P(retval_ptr), length); 1546 } 1547 zval_ptr_dtor(&retval_ptr); 1548 } 1549 1550 zval_ptr_dtor(argv[0]); 1551 zval_ptr_dtor(argv[1]); 1552 zval_ptr_dtor(argv[2]); 1553 break; 1554 } 1555 } 1556 1557 return length; 1558} 1559/* }}} */ 1560 1561/* {{{ curl_write_header 1562 */ 1563static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx) 1564{ 1565 php_curl *ch = (php_curl *) ctx; 1566 php_curl_write *t = ch->handlers->write_header; 1567 size_t length = size * nmemb; 1568 TSRMLS_FETCH_FROM_CTX(ch->thread_ctx); 1569 1570 switch (t->method) { 1571 case PHP_CURL_STDOUT: 1572 /* Handle special case write when we're returning the entire transfer 1573 */ 1574 if (ch->handlers->write->method == PHP_CURL_RETURN && length > 0) { 1575 smart_str_appendl(&ch->handlers->write->buf, data, (int) length); 1576 } else { 1577 PHPWRITE(data, length); 1578 } 1579 break; 1580 case PHP_CURL_FILE: 1581 return fwrite(data, size, nmemb, t->fp); 1582 case PHP_CURL_USER: { 1583 zval **argv[2]; 1584 zval *handle = NULL; 1585 zval *zdata = NULL; 1586 zval *retval_ptr; 1587 int error; 1588 zend_fcall_info fci; 1589 1590 MAKE_STD_ZVAL(handle); 1591 MAKE_STD_ZVAL(zdata); 1592 1593 ZVAL_RESOURCE(handle, ch->id); 1594 zend_list_addref(ch->id); 1595 ZVAL_STRINGL(zdata, data, length, 1); 1596 1597 argv[0] = &handle; 1598 argv[1] = &zdata; 1599 1600 fci.size = sizeof(fci); 1601 fci.function_table = EG(function_table); 1602 fci.function_name = t->func_name; 1603 fci.symbol_table = NULL; 1604 fci.object_ptr = NULL; 1605 fci.retval_ptr_ptr = &retval_ptr; 1606 fci.param_count = 2; 1607 fci.params = argv; 1608 fci.no_separation = 0; 1609 1610 ch->in_callback = 1; 1611 error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC); 1612 ch->in_callback = 0; 1613 if (error == FAILURE) { 1614 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION"); 1615 length = -1; 1616 } else if (retval_ptr) { 1617 if (Z_TYPE_P(retval_ptr) != IS_LONG) { 1618 convert_to_long_ex(&retval_ptr); 1619 } 1620 length = Z_LVAL_P(retval_ptr); 1621 zval_ptr_dtor(&retval_ptr); 1622 } 1623 zval_ptr_dtor(argv[0]); 1624 zval_ptr_dtor(argv[1]); 1625 break; 1626 } 1627 1628 case PHP_CURL_IGNORE: 1629 return length; 1630 1631 default: 1632 return -1; 1633 } 1634 1635 return length; 1636} 1637/* }}} */ 1638 1639static int curl_debug(CURL *cp, curl_infotype type, char *buf, size_t buf_len, void *ctx) /* {{{ */ 1640{ 1641 php_curl *ch = (php_curl *) ctx; 1642 1643 if (type == CURLINFO_HEADER_OUT) { 1644 if (ch->header.str_len) { 1645 efree(ch->header.str); 1646 } 1647 if (buf_len > 0) { 1648 ch->header.str = estrndup(buf, buf_len); 1649 ch->header.str_len = buf_len; 1650 } 1651 } 1652 1653 return 0; 1654} 1655/* }}} */ 1656 1657#if CURLOPT_PASSWDFUNCTION != 0 1658/* {{{ curl_passwd 1659 */ 1660static size_t curl_passwd(void *ctx, char *prompt, char *buf, int buflen) 1661{ 1662 php_curl *ch = (php_curl *) ctx; 1663 zval *func = ch->handlers->passwd; 1664 zval *argv[3]; 1665 zval *retval = NULL; 1666 int error; 1667 int ret = -1; 1668 TSRMLS_FETCH_FROM_CTX(ch->thread_ctx); 1669 1670 MAKE_STD_ZVAL(argv[0]); 1671 MAKE_STD_ZVAL(argv[1]); 1672 MAKE_STD_ZVAL(argv[2]); 1673 1674 ZVAL_RESOURCE(argv[0], ch->id); 1675 zend_list_addref(ch->id); 1676 ZVAL_STRING(argv[1], prompt, 1); 1677 ZVAL_LONG(argv[2], buflen); 1678 1679 error = call_user_function(EG(function_table), NULL, func, retval, 2, argv TSRMLS_CC); 1680 if (error == FAILURE) { 1681 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_PASSWDFUNCTION"); 1682 } else if (Z_TYPE_P(retval) == IS_STRING) { 1683 if (Z_STRLEN_P(retval) > buflen) { 1684 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Returned password is too long for libcurl to handle"); 1685 } else { 1686 strlcpy(buf, Z_STRVAL_P(retval), Z_STRLEN_P(retval)); 1687 } 1688 } else { 1689 php_error_docref(NULL TSRMLS_CC, E_WARNING, "User handler '%s' did not return a string", Z_STRVAL_P(func)); 1690 } 1691 1692 zval_ptr_dtor(&argv[0]); 1693 zval_ptr_dtor(&argv[1]); 1694 zval_ptr_dtor(&argv[2]); 1695 zval_ptr_dtor(&retval); 1696 1697 return ret; 1698} 1699/* }}} */ 1700#endif 1701 1702/* {{{ curl_free_string 1703 */ 1704static void curl_free_string(void **string) 1705{ 1706 efree(*string); 1707} 1708/* }}} */ 1709 1710/* {{{ curl_free_post 1711 */ 1712static void curl_free_post(void **post) 1713{ 1714 curl_formfree((struct HttpPost *) *post); 1715} 1716/* }}} */ 1717 1718/* {{{ curl_free_slist 1719 */ 1720static void curl_free_slist(void **slist) 1721{ 1722 curl_slist_free_all((struct curl_slist *) *slist); 1723} 1724/* }}} */ 1725 1726/* {{{ proto array curl_version([int version]) 1727 Return cURL version information. */ 1728PHP_FUNCTION(curl_version) 1729{ 1730 curl_version_info_data *d; 1731 long uversion = CURLVERSION_NOW; 1732 1733 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &uversion) == FAILURE) { 1734 return; 1735 } 1736 1737 d = curl_version_info(uversion); 1738 if (d == NULL) { 1739 RETURN_FALSE; 1740 } 1741 1742 array_init(return_value); 1743 1744 CAAL("version_number", d->version_num); 1745 CAAL("age", d->age); 1746 CAAL("features", d->features); 1747 CAAL("ssl_version_number", d->ssl_version_num); 1748 CAAS("version", d->version); 1749 CAAS("host", d->host); 1750 CAAS("ssl_version", d->ssl_version); 1751 CAAS("libz_version", d->libz_version); 1752 /* Add an array of protocols */ 1753 { 1754 char **p = (char **) d->protocols; 1755 zval *protocol_list = NULL; 1756 1757 MAKE_STD_ZVAL(protocol_list); 1758 array_init(protocol_list); 1759 1760 while (*p != NULL) { 1761 add_next_index_string(protocol_list, *p, 1); 1762 p++; 1763 } 1764 CAAZ("protocols", protocol_list); 1765 } 1766} 1767/* }}} */ 1768 1769/* {{{ alloc_curl_handle 1770 */ 1771static void alloc_curl_handle(php_curl **ch) 1772{ 1773 *ch = emalloc(sizeof(php_curl)); 1774 (*ch)->to_free = ecalloc(1, sizeof(struct _php_curl_free)); 1775 (*ch)->handlers = ecalloc(1, sizeof(php_curl_handlers)); 1776 (*ch)->handlers->write = ecalloc(1, sizeof(php_curl_write)); 1777 (*ch)->handlers->write_header = ecalloc(1, sizeof(php_curl_write)); 1778 (*ch)->handlers->read = ecalloc(1, sizeof(php_curl_read)); 1779 (*ch)->handlers->progress = NULL; 1780#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ 1781 (*ch)->handlers->fnmatch = NULL; 1782#endif 1783 1784 (*ch)->in_callback = 0; 1785 (*ch)->header.str_len = 0; 1786 1787 memset(&(*ch)->err, 0, sizeof((*ch)->err)); 1788 (*ch)->handlers->write->stream = NULL; 1789 (*ch)->handlers->write_header->stream = NULL; 1790 (*ch)->handlers->read->stream = NULL; 1791 1792 zend_llist_init(&(*ch)->to_free->str, sizeof(char *), (llist_dtor_func_t) curl_free_string, 0); 1793 zend_llist_init(&(*ch)->to_free->slist, sizeof(struct curl_slist), (llist_dtor_func_t) curl_free_slist, 0); 1794 zend_llist_init(&(*ch)->to_free->post, sizeof(struct HttpPost), (llist_dtor_func_t) curl_free_post, 0); 1795 (*ch)->safe_upload = 0; /* for now, for BC reason we allow unsafe API */ 1796} 1797/* }}} */ 1798 1799#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ 1800/* {{{ split_certinfo 1801 */ 1802static void split_certinfo(char *string, zval *hash) 1803{ 1804 char *org = estrdup(string); 1805 char *s = org; 1806 char *split; 1807 1808 if(org) { 1809 do { 1810 char *key; 1811 char *val; 1812 char *tmp; 1813 1814 split = strstr(s, "; "); 1815 if(split) 1816 *split = '\0'; 1817 1818 key = s; 1819 tmp = memchr(key, '=', 64); 1820 if(tmp) { 1821 *tmp = '\0'; 1822 val = tmp+1; 1823 add_assoc_string(hash, key, val, 1); 1824 } 1825 s = split+2; 1826 } while(split); 1827 efree(org); 1828 } 1829} 1830/* }}} */ 1831 1832/* {{{ create_certinfo 1833 */ 1834static void create_certinfo(struct curl_certinfo *ci, zval *listcode TSRMLS_DC) 1835{ 1836 int i; 1837 1838 if(ci) { 1839 zval *certhash = NULL; 1840 1841 for(i=0; i<ci->num_of_certs; i++) { 1842 struct curl_slist *slist; 1843 1844 MAKE_STD_ZVAL(certhash); 1845 array_init(certhash); 1846 for(slist = ci->certinfo[i]; slist; slist = slist->next) { 1847 int len; 1848 char s[64]; 1849 char *tmp; 1850 strncpy(s, slist->data, 64); 1851 tmp = memchr(s, ':', 64); 1852 if(tmp) { 1853 *tmp = '\0'; 1854 len = strlen(s); 1855 if(!strcmp(s, "Subject") || !strcmp(s, "Issuer")) { 1856 zval *hash; 1857 1858 MAKE_STD_ZVAL(hash); 1859 array_init(hash); 1860 1861 split_certinfo(&slist->data[len+1], hash); 1862 add_assoc_zval(certhash, s, hash); 1863 } else { 1864 add_assoc_string(certhash, s, &slist->data[len+1], 1); 1865 } 1866 } else { 1867 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not extract hash key from certificate info"); 1868 } 1869 } 1870 add_next_index_zval(listcode, certhash); 1871 } 1872 } 1873} 1874/* }}} */ 1875#endif 1876 1877/* {{{ _php_curl_set_default_options() 1878 Set default options for a handle */ 1879static void _php_curl_set_default_options(php_curl *ch) 1880{ 1881 char *cainfo; 1882 1883 curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1); 1884 curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); 1885 curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str); 1886 curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write); 1887 curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch); 1888 curl_easy_setopt(ch->cp, CURLOPT_READFUNCTION, curl_read); 1889 curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch); 1890 curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_header); 1891 curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch); 1892 curl_easy_setopt(ch->cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 1); 1893 curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120); 1894 curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20); /* prevent infinite redirects */ 1895 1896 cainfo = INI_STR("curl.cainfo"); 1897 if (cainfo && strlen(cainfo) > 0) { 1898 curl_easy_setopt(ch->cp, CURLOPT_CAINFO, cainfo); 1899 } 1900 1901#if defined(ZTS) 1902 curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1); 1903#endif 1904} 1905/* }}} */ 1906 1907/* {{{ proto resource curl_init([string url]) 1908 Initialize a cURL session */ 1909PHP_FUNCTION(curl_init) 1910{ 1911 php_curl *ch; 1912 CURL *cp; 1913 zval *clone; 1914 char *url = NULL; 1915 int url_len = 0; 1916 1917 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &url, &url_len) == FAILURE) { 1918 return; 1919 } 1920 1921 cp = curl_easy_init(); 1922 if (!cp) { 1923 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize a new cURL handle"); 1924 RETURN_FALSE; 1925 } 1926 1927 alloc_curl_handle(&ch); 1928 TSRMLS_SET_CTX(ch->thread_ctx); 1929 1930 ch->cp = cp; 1931 1932 ch->handlers->write->method = PHP_CURL_STDOUT; 1933 ch->handlers->read->method = PHP_CURL_DIRECT; 1934 ch->handlers->write_header->method = PHP_CURL_IGNORE; 1935 1936 MAKE_STD_ZVAL(clone); 1937 ch->clone = clone; 1938 1939 _php_curl_set_default_options(ch); 1940 1941 if (url) { 1942 if (!php_curl_option_url(ch, url, url_len TSRMLS_CC)) { 1943 _php_curl_close_ex(ch TSRMLS_CC); 1944 RETURN_FALSE; 1945 } 1946 } 1947 1948 ZEND_REGISTER_RESOURCE(return_value, ch, le_curl); 1949 ch->id = Z_LVAL_P(return_value); 1950} 1951/* }}} */ 1952 1953/* {{{ proto resource curl_copy_handle(resource ch) 1954 Copy a cURL handle along with all of it's preferences */ 1955PHP_FUNCTION(curl_copy_handle) 1956{ 1957 CURL *cp; 1958 zval *zid; 1959 php_curl *ch, *dupch; 1960 1961 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) { 1962 return; 1963 } 1964 1965 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 1966 1967 cp = curl_easy_duphandle(ch->cp); 1968 if (!cp) { 1969 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot duplicate cURL handle"); 1970 RETURN_FALSE; 1971 } 1972 1973 alloc_curl_handle(&dupch); 1974 TSRMLS_SET_CTX(dupch->thread_ctx); 1975 1976 dupch->cp = cp; 1977 zend_list_addref(Z_LVAL_P(zid)); 1978 if (ch->handlers->write->stream) { 1979 Z_ADDREF_P(ch->handlers->write->stream); 1980 } 1981 dupch->handlers->write->stream = ch->handlers->write->stream; 1982 dupch->handlers->write->method = ch->handlers->write->method; 1983 if (ch->handlers->read->stream) { 1984 Z_ADDREF_P(ch->handlers->read->stream); 1985 } 1986 dupch->handlers->read->stream = ch->handlers->read->stream; 1987 dupch->handlers->read->method = ch->handlers->read->method; 1988 dupch->handlers->write_header->method = ch->handlers->write_header->method; 1989 if (ch->handlers->write_header->stream) { 1990 Z_ADDREF_P(ch->handlers->write_header->stream); 1991 } 1992 dupch->handlers->write_header->stream = ch->handlers->write_header->stream; 1993 1994 dupch->handlers->write->fp = ch->handlers->write->fp; 1995 dupch->handlers->write_header->fp = ch->handlers->write_header->fp; 1996 dupch->handlers->read->fp = ch->handlers->read->fp; 1997 dupch->handlers->read->fd = ch->handlers->read->fd; 1998#if CURLOPT_PASSWDDATA != 0 1999 if (ch->handlers->passwd) { 2000 zval_add_ref(&ch->handlers->passwd); 2001 dupch->handlers->passwd = ch->handlers->passwd; 2002 curl_easy_setopt(ch->cp, CURLOPT_PASSWDDATA, (void *) dupch); 2003 } 2004#endif 2005 if (ch->handlers->write->func_name) { 2006 zval_add_ref(&ch->handlers->write->func_name); 2007 dupch->handlers->write->func_name = ch->handlers->write->func_name; 2008 } 2009 if (ch->handlers->read->func_name) { 2010 zval_add_ref(&ch->handlers->read->func_name); 2011 dupch->handlers->read->func_name = ch->handlers->read->func_name; 2012 } 2013 if (ch->handlers->write_header->func_name) { 2014 zval_add_ref(&ch->handlers->write_header->func_name); 2015 dupch->handlers->write_header->func_name = ch->handlers->write_header->func_name; 2016 } 2017 2018 curl_easy_setopt(dupch->cp, CURLOPT_ERRORBUFFER, dupch->err.str); 2019 curl_easy_setopt(dupch->cp, CURLOPT_FILE, (void *) dupch); 2020 curl_easy_setopt(dupch->cp, CURLOPT_INFILE, (void *) dupch); 2021 curl_easy_setopt(dupch->cp, CURLOPT_WRITEHEADER, (void *) dupch); 2022 2023 if (ch->handlers->progress) { 2024 dupch->handlers->progress = ecalloc(1, sizeof(php_curl_progress)); 2025 if (ch->handlers->progress->func_name) { 2026 zval_add_ref(&ch->handlers->progress->func_name); 2027 dupch->handlers->progress->func_name = ch->handlers->progress->func_name; 2028 } 2029 dupch->handlers->progress->method = ch->handlers->progress->method; 2030 curl_easy_setopt(dupch->cp, CURLOPT_PROGRESSDATA, (void *) dupch); 2031 } 2032 2033/* Available since 7.21.0 */ 2034#if LIBCURL_VERSION_NUM >= 0x071500 2035 if (ch->handlers->fnmatch) { 2036 dupch->handlers->fnmatch = ecalloc(1, sizeof(php_curl_fnmatch)); 2037 if (ch->handlers->fnmatch->func_name) { 2038 zval_add_ref(&ch->handlers->fnmatch->func_name); 2039 dupch->handlers->fnmatch->func_name = ch->handlers->fnmatch->func_name; 2040 } 2041 dupch->handlers->fnmatch->method = ch->handlers->fnmatch->method; 2042 curl_easy_setopt(dupch->cp, CURLOPT_FNMATCH_DATA, (void *) dupch); 2043 } 2044#endif 2045 2046 efree(dupch->to_free); 2047 dupch->to_free = ch->to_free; 2048 2049 /* Keep track of cloned copies to avoid invoking curl destructors for every clone */ 2050 Z_ADDREF_P(ch->clone); 2051 dupch->clone = ch->clone; 2052 2053 ZEND_REGISTER_RESOURCE(return_value, dupch, le_curl); 2054 dupch->id = Z_LVAL_P(return_value); 2055} 2056/* }}} */ 2057 2058static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *return_value TSRMLS_DC) /* {{{ */ 2059{ 2060 CURLcode error=CURLE_OK; 2061 2062 switch (option) { 2063 /* Long options */ 2064 case CURLOPT_SSL_VERIFYHOST: 2065 if(Z_BVAL_PP(zvalue) == 1) { 2066#if LIBCURL_VERSION_NUM <= 0x071c00 /* 7.28.0 */ 2067 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "CURLOPT_SSL_VERIFYHOST with value 1 is deprecated and will be removed as of libcurl 7.28.1. It is recommended to use value 2 instead"); 2068#else 2069 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead"); 2070 error = curl_easy_setopt(ch->cp, option, 2); 2071 break; 2072#endif 2073 } 2074 case CURLOPT_AUTOREFERER: 2075 case CURLOPT_BUFFERSIZE: 2076 case CURLOPT_CLOSEPOLICY: 2077 case CURLOPT_CONNECTTIMEOUT: 2078 case CURLOPT_COOKIESESSION: 2079 case CURLOPT_CRLF: 2080 case CURLOPT_DNS_CACHE_TIMEOUT: 2081 case CURLOPT_DNS_USE_GLOBAL_CACHE: 2082 case CURLOPT_FAILONERROR: 2083 case CURLOPT_FILETIME: 2084 case CURLOPT_FORBID_REUSE: 2085 case CURLOPT_FRESH_CONNECT: 2086 case CURLOPT_FTP_USE_EPRT: 2087 case CURLOPT_FTP_USE_EPSV: 2088 case CURLOPT_HEADER: 2089 case CURLOPT_HTTPGET: 2090 case CURLOPT_HTTPPROXYTUNNEL: 2091 case CURLOPT_HTTP_VERSION: 2092 case CURLOPT_INFILESIZE: 2093 case CURLOPT_LOW_SPEED_LIMIT: 2094 case CURLOPT_LOW_SPEED_TIME: 2095 case CURLOPT_MAXCONNECTS: 2096 case CURLOPT_MAXREDIRS: 2097 case CURLOPT_NETRC: 2098 case CURLOPT_NOBODY: 2099 case CURLOPT_NOPROGRESS: 2100 case CURLOPT_NOSIGNAL: 2101 case CURLOPT_PORT: 2102 case CURLOPT_POST: 2103 case CURLOPT_PROXYPORT: 2104 case CURLOPT_PROXYTYPE: 2105 case CURLOPT_PUT: 2106 case CURLOPT_RESUME_FROM: 2107 case CURLOPT_SSLVERSION: 2108 case CURLOPT_SSL_VERIFYPEER: 2109 case CURLOPT_TIMECONDITION: 2110 case CURLOPT_TIMEOUT: 2111 case CURLOPT_TIMEVALUE: 2112 case CURLOPT_TRANSFERTEXT: 2113 case CURLOPT_UNRESTRICTED_AUTH: 2114 case CURLOPT_UPLOAD: 2115 case CURLOPT_VERBOSE: 2116#if LIBCURL_VERSION_NUM >= 0x070a06 /* Available since 7.10.6 */ 2117 case CURLOPT_HTTPAUTH: 2118#endif 2119#if LIBCURL_VERSION_NUM >= 0x070a07 /* Available since 7.10.7 */ 2120 case CURLOPT_FTP_CREATE_MISSING_DIRS: 2121 case CURLOPT_PROXYAUTH: 2122#endif 2123#if LIBCURL_VERSION_NUM >= 0x070a08 /* Available since 7.10.8 */ 2124 case CURLOPT_FTP_RESPONSE_TIMEOUT: 2125 case CURLOPT_IPRESOLVE: 2126 case CURLOPT_MAXFILESIZE: 2127#endif 2128#if LIBCURL_VERSION_NUM >= 0x070b02 /* Available since 7.11.2 */ 2129 case CURLOPT_TCP_NODELAY: 2130#endif 2131#if LIBCURL_VERSION_NUM >= 0x070c02 /* Available since 7.12.2 */ 2132 case CURLOPT_FTPSSLAUTH: 2133#endif 2134#if LIBCURL_VERSION_NUM >= 0x070e01 /* Available since 7.14.1 */ 2135 case CURLOPT_IGNORE_CONTENT_LENGTH: 2136#endif 2137#if LIBCURL_VERSION_NUM >= 0x070f00 /* Available since 7.15.0 */ 2138 case CURLOPT_FTP_SKIP_PASV_IP: 2139#endif 2140#if LIBCURL_VERSION_NUM >= 0x070f01 /* Available since 7.15.1 */ 2141 case CURLOPT_FTP_FILEMETHOD: 2142#endif 2143#if LIBCURL_VERSION_NUM >= 0x070f02 /* Available since 7.15.2 */ 2144 case CURLOPT_CONNECT_ONLY: 2145 case CURLOPT_LOCALPORT: 2146 case CURLOPT_LOCALPORTRANGE: 2147#endif 2148#if LIBCURL_VERSION_NUM >= 0x071000 /* Available since 7.16.0 */ 2149 case CURLOPT_SSL_SESSIONID_CACHE: 2150#endif 2151#if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */ 2152 case CURLOPT_FTP_SSL_CCC: 2153 case CURLOPT_SSH_AUTH_TYPES: 2154#endif 2155#if LIBCURL_VERSION_NUM >= 0x071002 /* Available since 7.16.2 */ 2156 case CURLOPT_CONNECTTIMEOUT_MS: 2157 case CURLOPT_HTTP_CONTENT_DECODING: 2158 case CURLOPT_HTTP_TRANSFER_DECODING: 2159 case CURLOPT_TIMEOUT_MS: 2160#endif 2161#if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */ 2162 case CURLOPT_NEW_DIRECTORY_PERMS: 2163 case CURLOPT_NEW_FILE_PERMS: 2164#endif 2165#if LIBCURL_VERSION_NUM >= 0x071100 /* Available since 7.17.0 */ 2166 case CURLOPT_USE_SSL: 2167#elif LIBCURL_VERSION_NUM >= 0x070b00 /* Available since 7.11.0 */ 2168 case CURLOPT_FTP_SSL: 2169#endif 2170#if LIBCURL_VERSION_NUM >= 0x071100 /* Available since 7.17.0 */ 2171 case CURLOPT_APPEND: 2172 case CURLOPT_DIRLISTONLY: 2173#else 2174 case CURLOPT_FTPAPPEND: 2175 case CURLOPT_FTPLISTONLY: 2176#endif 2177#if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */ 2178 case CURLOPT_PROXY_TRANSFER_MODE: 2179#endif 2180#if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */ 2181 case CURLOPT_ADDRESS_SCOPE: 2182#endif 2183#if LIBCURL_VERSION_NUM > 0x071301 /* Available since 7.19.1 */ 2184 case CURLOPT_CERTINFO: 2185#endif 2186#if LIBCURL_VERSION_NUM >= 0x071304 /* Available since 7.19.4 */ 2187 case CURLOPT_NOPROXY: 2188 case CURLOPT_PROTOCOLS: 2189 case CURLOPT_REDIR_PROTOCOLS: 2190 case CURLOPT_SOCKS5_GSSAPI_NEC: 2191 case CURLOPT_TFTP_BLKSIZE: 2192#endif 2193#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */ 2194 case CURLOPT_FTP_USE_PRET: 2195 case CURLOPT_RTSP_CLIENT_CSEQ: 2196 case CURLOPT_RTSP_REQUEST: 2197 case CURLOPT_RTSP_SERVER_CSEQ: 2198#endif 2199#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ 2200 case CURLOPT_WILDCARDMATCH: 2201#endif 2202#if LIBCURL_VERSION_NUM >= 0x071504 /* Available since 7.21.4 */ 2203 case CURLOPT_TLSAUTH_TYPE: 2204#endif 2205#if LIBCURL_VERSION_NUM >= 0x071600 /* Available since 7.22.0 */ 2206 case CURLOPT_GSSAPI_DELEGATION: 2207#endif 2208#if LIBCURL_VERSION_NUM >= 0x071800 /* Available since 7.24.0 */ 2209 case CURLOPT_ACCEPTTIMEOUT_MS: 2210#endif 2211#if LIBCURL_VERSION_NUM >= 0x071900 /* Available since 7.25.0 */ 2212 case CURLOPT_SSL_OPTIONS: 2213 case CURLOPT_TCP_KEEPALIVE: 2214 case CURLOPT_TCP_KEEPIDLE: 2215 case CURLOPT_TCP_KEEPINTVL: 2216#endif 2217#if CURLOPT_MUTE != 0 2218 case CURLOPT_MUTE: 2219#endif 2220 convert_to_long_ex(zvalue); 2221#if LIBCURL_VERSION_NUM >= 0x71304 2222 if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) && 2223 (PG(open_basedir) && *PG(open_basedir)) && (Z_LVAL_PP(zvalue) & CURLPROTO_FILE)) { 2224 php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLPROTO_FILE cannot be activated when an open_basedir is set"); 2225 RETVAL_FALSE; 2226 return 1; 2227 } 2228#endif 2229 error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue)); 2230 break; 2231 case CURLOPT_SAFE_UPLOAD: 2232 convert_to_long_ex(zvalue); 2233 ch->safe_upload = (Z_LVAL_PP(zvalue) != 0); 2234 break; 2235 2236 /* String options */ 2237 case CURLOPT_CAINFO: 2238 case CURLOPT_CAPATH: 2239 case CURLOPT_COOKIE: 2240 case CURLOPT_CUSTOMREQUEST: 2241 case CURLOPT_EGDSOCKET: 2242 case CURLOPT_FTPPORT: 2243 case CURLOPT_INTERFACE: 2244 case CURLOPT_PRIVATE: 2245 case CURLOPT_PROXY: 2246 case CURLOPT_PROXYUSERPWD: 2247 case CURLOPT_RANGE: 2248 case CURLOPT_REFERER: 2249 case CURLOPT_SSLCERTTYPE: 2250 case CURLOPT_SSLENGINE: 2251 case CURLOPT_SSLENGINE_DEFAULT: 2252 case CURLOPT_SSLKEY: 2253 case CURLOPT_SSLKEYPASSWD: 2254 case CURLOPT_SSLKEYTYPE: 2255 case CURLOPT_SSL_CIPHER_LIST: 2256 case CURLOPT_URL: 2257 case CURLOPT_USERAGENT: 2258 case CURLOPT_USERPWD: 2259#if LIBCURL_VERSION_NUM >= 0x070d00 /* Available since 7.13.0 */ 2260 case CURLOPT_FTP_ACCOUNT: 2261#endif 2262#if LIBCURL_VERSION_NUM >= 0x070e01 /* Available since 7.14.1 */ 2263 case CURLOPT_COOKIELIST: 2264#endif 2265#if LIBCURL_VERSION_NUM >= 0x070f05 /* Available since 7.15.5 */ 2266 case CURLOPT_FTP_ALTERNATIVE_TO_USER: 2267#endif 2268#if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */ 2269 case CURLOPT_KRBLEVEL: 2270#else 2271 case CURLOPT_KRB4LEVEL: 2272#endif 2273#if LIBCURL_VERSION_NUM >= 0x071101 /* Available since 7.17.1 */ 2274 case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: 2275#endif 2276#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ 2277 case CURLOPT_PASSWORD: 2278 case CURLOPT_PROXYPASSWORD: 2279 case CURLOPT_PROXYUSERNAME: 2280 case CURLOPT_USERNAME: 2281#endif 2282#if LIBCURL_VERSION_NUM >= 0x071304 /* Available since 7.19.4 */ 2283 case CURLOPT_SOCKS5_GSSAPI_SERVICE: 2284#endif 2285#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */ 2286 case CURLOPT_MAIL_FROM: 2287 case CURLOPT_RTSP_SESSION_ID: 2288 case CURLOPT_RTSP_STREAM_URI: 2289 case CURLOPT_RTSP_TRANSPORT: 2290#endif 2291#if LIBCURL_VERSION_NUM >= 0x071504 /* Available since 7.21.4 */ 2292 case CURLOPT_TLSAUTH_PASSWORD: 2293 case CURLOPT_TLSAUTH_USERNAME: 2294#endif 2295#if LIBCURL_VERSION_NUM >= 0x071506 /* Available since 7.21.6 */ 2296 case CURLOPT_ACCEPT_ENCODING: 2297 case CURLOPT_TRANSFER_ENCODING: 2298#else 2299 case CURLOPT_ENCODING: 2300#endif 2301#if LIBCURL_VERSION_NUM >= 0x071800 /* Available since 7.24.0 */ 2302 case CURLOPT_DNS_SERVERS: 2303#endif 2304#if LIBCURL_VERSION_NUM >= 0x071900 /* Available since 7.25.0 */ 2305 case CURLOPT_MAIL_AUTH: 2306#endif 2307 { 2308 convert_to_string_ex(zvalue); 2309 if (option == CURLOPT_URL) { 2310 if (!php_curl_option_url(ch, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue) TSRMLS_CC)) { 2311 RETVAL_FALSE; 2312 return 1; 2313 } 2314 } else { 2315 if (option == CURLOPT_PRIVATE) { 2316 char *copystr; 2317#if LIBCURL_VERSION_NUM < 0x071100 2318string_copy: 2319#endif 2320 copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue)); 2321 error = curl_easy_setopt(ch->cp, option, copystr); 2322 zend_llist_add_element(&ch->to_free->str, ©str); 2323 } else { 2324#if LIBCURL_VERSION_NUM >= 0x071100 2325 /* Strings passed to libcurl as ’char *’ arguments, are copied by the library... NOTE: before 7.17.0 strings were not copied. */ 2326 error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue)); 2327#else 2328 goto string_copy; 2329#endif 2330 } 2331 } 2332 break; 2333 } 2334 2335 /* Curl file handle options */ 2336 case CURLOPT_FILE: 2337 case CURLOPT_INFILE: 2338 case CURLOPT_STDERR: 2339 case CURLOPT_WRITEHEADER: { 2340 FILE *fp = NULL; 2341 int type; 2342 void * what; 2343 2344 what = zend_fetch_resource(zvalue TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream(), php_file_le_pstream()); 2345 if (!what) { 2346 RETVAL_FALSE; 2347 return 1; 2348 } 2349 2350 if (FAILURE == php_stream_cast((php_stream *) what, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) { 2351 RETVAL_FALSE; 2352 return 1; 2353 } 2354 2355 if (!fp) { 2356 RETVAL_FALSE; 2357 return 1; 2358 } 2359 2360 error = CURLE_OK; 2361 switch (option) { 2362 case CURLOPT_FILE: 2363 if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') { 2364 if (ch->handlers->write->stream) { 2365 Z_DELREF_P(ch->handlers->write->stream); 2366 } 2367 Z_ADDREF_PP(zvalue); 2368 ch->handlers->write->fp = fp; 2369 ch->handlers->write->method = PHP_CURL_FILE; 2370 ch->handlers->write->stream = *zvalue; 2371 } else { 2372 php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable"); 2373 RETVAL_FALSE; 2374 return 1; 2375 } 2376 break; 2377 case CURLOPT_WRITEHEADER: 2378 if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') { 2379 if (ch->handlers->write_header->stream) { 2380 Z_DELREF_P(ch->handlers->write_header->stream); 2381 } 2382 Z_ADDREF_PP(zvalue); 2383 ch->handlers->write_header->fp = fp; 2384 ch->handlers->write_header->method = PHP_CURL_FILE; 2385 ch->handlers->write_header->stream = *zvalue; 2386 } else { 2387 php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable"); 2388 RETVAL_FALSE; 2389 return 1; 2390 } 2391 break; 2392 case CURLOPT_INFILE: 2393 if (ch->handlers->read->stream) { 2394 Z_DELREF_P(ch->handlers->read->stream); 2395 } 2396 Z_ADDREF_PP(zvalue); 2397 ch->handlers->read->fp = fp; 2398 ch->handlers->read->fd = Z_LVAL_PP(zvalue); 2399 ch->handlers->read->stream = *zvalue; 2400 break; 2401 case CURLOPT_STDERR: 2402 if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') { 2403 if (ch->handlers->std_err) { 2404 zval_ptr_dtor(&ch->handlers->std_err); 2405 } 2406 zval_add_ref(zvalue); 2407 ch->handlers->std_err = *zvalue; 2408 } else { 2409 php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable"); 2410 RETVAL_FALSE; 2411 return 1; 2412 } 2413 /* break omitted intentionally */ 2414 default: 2415 error = curl_easy_setopt(ch->cp, option, fp); 2416 break; 2417 } 2418 break; 2419 } 2420 2421 /* Curl linked list options */ 2422 case CURLOPT_HTTP200ALIASES: 2423 case CURLOPT_HTTPHEADER: 2424 case CURLOPT_POSTQUOTE: 2425 case CURLOPT_PREQUOTE: 2426 case CURLOPT_QUOTE: 2427 case CURLOPT_TELNETOPTIONS: 2428#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */ 2429 case CURLOPT_MAIL_RCPT: 2430#endif 2431#if LIBCURL_VERSION_NUM >= 0x071503 /* Available since 7.21.3 */ 2432 case CURLOPT_RESOLVE: 2433#endif 2434 { 2435 zval **current; 2436 HashTable *ph; 2437 struct curl_slist *slist = NULL; 2438 2439 ph = HASH_OF(*zvalue); 2440 if (!ph) { 2441 char *name; 2442 switch (option) { 2443 case CURLOPT_HTTPHEADER: 2444 name = "CURLOPT_HTTPHEADER"; 2445 break; 2446 case CURLOPT_QUOTE: 2447 name = "CURLOPT_QUOTE"; 2448 break; 2449 case CURLOPT_HTTP200ALIASES: 2450 name = "CURLOPT_HTTP200ALIASES"; 2451 break; 2452 case CURLOPT_POSTQUOTE: 2453 name = "CURLOPT_POSTQUOTE"; 2454 break; 2455 case CURLOPT_PREQUOTE: 2456 name = "CURLOPT_PREQUOTE"; 2457 break; 2458 case CURLOPT_TELNETOPTIONS: 2459 name = "CURLOPT_TELNETOPTIONS"; 2460 break; 2461#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */ 2462 case CURLOPT_MAIL_RCPT: 2463 name = "CURLOPT_MAIL_RCPT"; 2464 break; 2465#endif 2466#if LIBCURL_VERSION_NUM >= 0x071503 /* Available since 7.21.3 */ 2467 case CURLOPT_RESOLVE: 2468 name = "CURLOPT_RESOLVE"; 2469 break; 2470#endif 2471 } 2472 php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must pass either an object or an array with the %s argument", name); 2473 RETVAL_FALSE; 2474 return 1; 2475 } 2476 2477 for (zend_hash_internal_pointer_reset(ph); 2478 zend_hash_get_current_data(ph, (void **) ¤t) == SUCCESS; 2479 zend_hash_move_forward(ph) 2480 ) { 2481 SEPARATE_ZVAL(current); 2482 convert_to_string_ex(current); 2483 2484 slist = curl_slist_append(slist, Z_STRVAL_PP(current)); 2485 if (!slist) { 2486 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not build curl_slist"); 2487 RETVAL_FALSE; 2488 return 1; 2489 } 2490 } 2491 zend_llist_add_element(&ch->to_free->slist, &slist); 2492 2493 error = curl_easy_setopt(ch->cp, option, slist); 2494 2495 break; 2496 } 2497 2498 case CURLOPT_BINARYTRANSFER: 2499 /* Do nothing, just backward compatibility */ 2500 break; 2501 2502 case CURLOPT_FOLLOWLOCATION: 2503 convert_to_long_ex(zvalue); 2504 if (PG(open_basedir) && *PG(open_basedir)) { 2505 if (Z_LVAL_PP(zvalue) != 0) { 2506 php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set"); 2507 RETVAL_FALSE; 2508 return 1; 2509 } 2510 } 2511 error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue)); 2512 break; 2513 2514 case CURLOPT_HEADERFUNCTION: 2515 if (ch->handlers->write_header->func_name) { 2516 zval_ptr_dtor(&ch->handlers->write_header->func_name); 2517 ch->handlers->write_header->fci_cache = empty_fcall_info_cache; 2518 } 2519 zval_add_ref(zvalue); 2520 ch->handlers->write_header->func_name = *zvalue; 2521 ch->handlers->write_header->method = PHP_CURL_USER; 2522 break; 2523 2524 case CURLOPT_POSTFIELDS: 2525 if (Z_TYPE_PP(zvalue) == IS_ARRAY || Z_TYPE_PP(zvalue) == IS_OBJECT) { 2526 zval **current; 2527 HashTable *postfields; 2528 struct HttpPost *first = NULL; 2529 struct HttpPost *last = NULL; 2530 2531 postfields = HASH_OF(*zvalue); 2532 if (!postfields) { 2533 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't get HashTable in CURLOPT_POSTFIELDS"); 2534 RETVAL_FALSE; 2535 return 1; 2536 } 2537 2538 for (zend_hash_internal_pointer_reset(postfields); 2539 zend_hash_get_current_data(postfields, (void **) ¤t) == SUCCESS; 2540 zend_hash_move_forward(postfields) 2541 ) { 2542 char *postval; 2543 char *string_key = NULL; 2544 uint string_key_len; 2545 ulong num_key; 2546 int numeric_key; 2547 2548 zend_hash_get_current_key_ex(postfields, &string_key, &string_key_len, &num_key, 0, NULL); 2549 2550 /* Pretend we have a string_key here */ 2551 if(!string_key) { 2552 spprintf(&string_key, 0, "%ld", num_key); 2553 string_key_len = strlen(string_key)+1; 2554 numeric_key = 1; 2555 } else { 2556 numeric_key = 0; 2557 } 2558 2559 if(Z_TYPE_PP(current) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(current), curl_CURLFile_class TSRMLS_CC)) { 2560 /* new-style file upload */ 2561 zval *prop; 2562 char *type = NULL, *filename = NULL; 2563 2564 prop = zend_read_property(curl_CURLFile_class, *current, "name", sizeof("name")-1, 0 TSRMLS_CC); 2565 if(Z_TYPE_P(prop) != IS_STRING) { 2566 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid filename for key %s", string_key); 2567 } else { 2568 postval = Z_STRVAL_P(prop); 2569 2570 if (php_check_open_basedir(postval TSRMLS_CC)) { 2571 RETVAL_FALSE; 2572 return 1; 2573 } 2574 2575 prop = zend_read_property(curl_CURLFile_class, *current, "mime", sizeof("mime")-1, 0 TSRMLS_CC); 2576 if(Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) { 2577 type = Z_STRVAL_P(prop); 2578 } 2579 prop = zend_read_property(curl_CURLFile_class, *current, "postname", sizeof("postname")-1, 0 TSRMLS_CC); 2580 if(Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) { 2581 filename = Z_STRVAL_P(prop); 2582 } 2583 error = curl_formadd(&first, &last, 2584 CURLFORM_COPYNAME, string_key, 2585 CURLFORM_NAMELENGTH, (long)string_key_len - 1, 2586 CURLFORM_FILENAME, filename ? filename : postval, 2587 CURLFORM_CONTENTTYPE, type ? type : "application/octet-stream", 2588 CURLFORM_FILE, postval, 2589 CURLFORM_END); 2590 } 2591 2592 if (numeric_key) { 2593 efree(string_key); 2594 } 2595 continue; 2596 } 2597 2598 SEPARATE_ZVAL(current); 2599 convert_to_string_ex(current); 2600 2601 postval = Z_STRVAL_PP(current); 2602 2603 /* The arguments after _NAMELENGTH and _CONTENTSLENGTH 2604 * must be explicitly cast to long in curl_formadd 2605 * use since curl needs a long not an int. */ 2606 if (!ch->safe_upload && *postval == '@') { 2607 char *type, *filename; 2608 ++postval; 2609 2610 php_error_docref("curl.curlfile" TSRMLS_CC, E_DEPRECATED, "The usage of the @filename API for file uploading is deprecated. Please use the CURLFile class instead"); 2611 2612 if ((type = php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + Z_STRLEN_PP(current)))) { 2613 *type = '\0'; 2614 } 2615 if ((filename = php_memnstr(postval, ";filename=", sizeof(";filename=") - 1, postval + Z_STRLEN_PP(current)))) { 2616 *filename = '\0'; 2617 } 2618 /* open_basedir check */ 2619 if (php_check_open_basedir(postval TSRMLS_CC)) { 2620 RETVAL_FALSE; 2621 return 1; 2622 } 2623 error = curl_formadd(&first, &last, 2624 CURLFORM_COPYNAME, string_key, 2625 CURLFORM_NAMELENGTH, (long)string_key_len - 1, 2626 CURLFORM_FILENAME, filename ? filename + sizeof(";filename=") - 1 : postval, 2627 CURLFORM_CONTENTTYPE, type ? type + sizeof(";type=") - 1 : "application/octet-stream", 2628 CURLFORM_FILE, postval, 2629 CURLFORM_END); 2630 if (type) { 2631 *type = ';'; 2632 } 2633 if (filename) { 2634 *filename = ';'; 2635 } 2636 } else { 2637 error = curl_formadd(&first, &last, 2638 CURLFORM_COPYNAME, string_key, 2639 CURLFORM_NAMELENGTH, (long)string_key_len - 1, 2640 CURLFORM_COPYCONTENTS, postval, 2641 CURLFORM_CONTENTSLENGTH, (long)Z_STRLEN_PP(current), 2642 CURLFORM_END); 2643 } 2644 2645 if (numeric_key) { 2646 efree(string_key); 2647 } 2648 } 2649 2650 SAVE_CURL_ERROR(ch, error); 2651 if (error != CURLE_OK) { 2652 RETVAL_FALSE; 2653 return 1; 2654 } 2655 2656 if (Z_REFCOUNT_P(ch->clone) <= 1) { 2657 zend_llist_clean(&ch->to_free->post); 2658 } 2659 zend_llist_add_element(&ch->to_free->post, &first); 2660 error = curl_easy_setopt(ch->cp, CURLOPT_HTTPPOST, first); 2661 2662 } else { 2663#if LIBCURL_VERSION_NUM >= 0x071101 2664 convert_to_string_ex(zvalue); 2665 /* with curl 7.17.0 and later, we can use COPYPOSTFIELDS, but we have to provide size before */ 2666 error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue)); 2667 error = curl_easy_setopt(ch->cp, CURLOPT_COPYPOSTFIELDS, Z_STRVAL_PP(zvalue)); 2668#else 2669 char *post = NULL; 2670 2671 convert_to_string_ex(zvalue); 2672 post = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue)); 2673 zend_llist_add_element(&ch->to_free->str, &post); 2674 2675 error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, post); 2676 error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue)); 2677#endif 2678 } 2679 break; 2680 2681 case CURLOPT_PROGRESSFUNCTION: 2682 curl_easy_setopt(ch->cp, CURLOPT_PROGRESSFUNCTION, curl_progress); 2683 curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, ch); 2684 if (ch->handlers->progress == NULL) { 2685 ch->handlers->progress = ecalloc(1, sizeof(php_curl_progress)); 2686 } else if (ch->handlers->progress->func_name) { 2687 zval_ptr_dtor(&ch->handlers->progress->func_name); 2688 ch->handlers->progress->fci_cache = empty_fcall_info_cache; 2689 } 2690 zval_add_ref(zvalue); 2691 ch->handlers->progress->func_name = *zvalue; 2692 ch->handlers->progress->method = PHP_CURL_USER; 2693 break; 2694 2695 case CURLOPT_READFUNCTION: 2696 if (ch->handlers->read->func_name) { 2697 zval_ptr_dtor(&ch->handlers->read->func_name); 2698 ch->handlers->read->fci_cache = empty_fcall_info_cache; 2699 } 2700 zval_add_ref(zvalue); 2701 ch->handlers->read->func_name = *zvalue; 2702 ch->handlers->read->method = PHP_CURL_USER; 2703 break; 2704 2705 case CURLOPT_RETURNTRANSFER: 2706 convert_to_long_ex(zvalue); 2707 if (Z_LVAL_PP(zvalue)) { 2708 ch->handlers->write->method = PHP_CURL_RETURN; 2709 } else { 2710 ch->handlers->write->method = PHP_CURL_STDOUT; 2711 } 2712 break; 2713 2714 case CURLOPT_WRITEFUNCTION: 2715 if (ch->handlers->write->func_name) { 2716 zval_ptr_dtor(&ch->handlers->write->func_name); 2717 ch->handlers->write->fci_cache = empty_fcall_info_cache; 2718 } 2719 zval_add_ref(zvalue); 2720 ch->handlers->write->func_name = *zvalue; 2721 ch->handlers->write->method = PHP_CURL_USER; 2722 break; 2723 2724#if LIBCURL_VERSION_NUM >= 0x070f05 /* Available since 7.15.5 */ 2725 case CURLOPT_MAX_RECV_SPEED_LARGE: 2726 case CURLOPT_MAX_SEND_SPEED_LARGE: 2727 convert_to_long_ex(zvalue); 2728 error = curl_easy_setopt(ch->cp, option, (curl_off_t)Z_LVAL_PP(zvalue)); 2729 break; 2730#endif 2731 2732#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ 2733 case CURLOPT_POSTREDIR: 2734 convert_to_long_ex(zvalue); 2735 error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, Z_LVAL_PP(zvalue) & CURL_REDIR_POST_ALL); 2736 break; 2737#endif 2738 2739#if CURLOPT_PASSWDFUNCTION != 0 2740 case CURLOPT_PASSWDFUNCTION: 2741 if (ch->handlers->passwd) { 2742 zval_ptr_dtor(&ch->handlers->passwd); 2743 } 2744 zval_add_ref(zvalue); 2745 ch->handlers->passwd = *zvalue; 2746 error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDFUNCTION, curl_passwd); 2747 error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDDATA, (void *) ch); 2748 break; 2749#endif 2750 2751 /* the following options deal with files, therefore the open_basedir check 2752 * is required. 2753 */ 2754 case CURLOPT_COOKIEFILE: 2755 case CURLOPT_COOKIEJAR: 2756 case CURLOPT_RANDOM_FILE: 2757 case CURLOPT_SSLCERT: 2758#if LIBCURL_VERSION_NUM >= 0x070b00 /* Available since 7.11.0 */ 2759 case CURLOPT_NETRC_FILE: 2760#endif 2761#if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */ 2762 case CURLOPT_SSH_PRIVATE_KEYFILE: 2763 case CURLOPT_SSH_PUBLIC_KEYFILE: 2764#endif 2765#if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */ 2766 case CURLOPT_CRLFILE: 2767 case CURLOPT_ISSUERCERT: 2768#endif 2769#if LIBCURL_VERSION_NUM >= 0x071306 /* Available since 7.19.6 */ 2770 case CURLOPT_SSH_KNOWNHOSTS: 2771#endif 2772 { 2773#if LIBCURL_VERSION_NUM < 0x071100 2774 char *copystr = NULL; 2775#endif 2776 2777 convert_to_string_ex(zvalue); 2778 2779 if (Z_STRLEN_PP(zvalue) && php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC)) { 2780 RETVAL_FALSE; 2781 return 1; 2782 } 2783 2784#if LIBCURL_VERSION_NUM >= 0x071100 2785 error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue)); 2786#else 2787 copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue)); 2788 2789 error = curl_easy_setopt(ch->cp, option, copystr); 2790 zend_llist_add_element(&ch->to_free->str, ©str); 2791#endif 2792 break; 2793 } 2794 2795 case CURLINFO_HEADER_OUT: 2796 convert_to_long_ex(zvalue); 2797 if (Z_LVAL_PP(zvalue) == 1) { 2798 curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug); 2799 curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *)ch); 2800 curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1); 2801 } else { 2802 curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL); 2803 curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL); 2804 curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); 2805 } 2806 break; 2807 2808 case CURLOPT_SHARE: 2809 { 2810 php_curlsh *sh = NULL; 2811 ZEND_FETCH_RESOURCE_NO_RETURN(sh, php_curlsh *, zvalue, -1, le_curl_share_handle_name, le_curl_share_handle); 2812 if (sh) { 2813 curl_easy_setopt(ch->cp, CURLOPT_SHARE, sh->share); 2814 } 2815 } 2816 2817#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ 2818 case CURLOPT_FNMATCH_FUNCTION: 2819 curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_FUNCTION, curl_fnmatch); 2820 curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_DATA, ch); 2821 if (ch->handlers->fnmatch == NULL) { 2822 ch->handlers->fnmatch = ecalloc(1, sizeof(php_curl_fnmatch)); 2823 } else if (ch->handlers->fnmatch->func_name) { 2824 zval_ptr_dtor(&ch->handlers->fnmatch->func_name); 2825 ch->handlers->fnmatch->fci_cache = empty_fcall_info_cache; 2826 } 2827 zval_add_ref(zvalue); 2828 ch->handlers->fnmatch->func_name = *zvalue; 2829 ch->handlers->fnmatch->method = PHP_CURL_USER; 2830 break; 2831#endif 2832 2833 } 2834 2835 SAVE_CURL_ERROR(ch, error); 2836 if (error != CURLE_OK) { 2837 return 1; 2838 } else { 2839 return 0; 2840 } 2841} 2842/* }}} */ 2843 2844/* {{{ proto bool curl_setopt(resource ch, int option, mixed value) 2845 Set an option for a cURL transfer */ 2846PHP_FUNCTION(curl_setopt) 2847{ 2848 zval *zid, **zvalue; 2849 long options; 2850 php_curl *ch; 2851 2852 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlZ", &zid, &options, &zvalue) == FAILURE) { 2853 return; 2854 } 2855 2856 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 2857 2858 if (options <= 0 && options != CURLOPT_SAFE_UPLOAD) { 2859 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid curl configuration option"); 2860 RETURN_FALSE; 2861 } 2862 2863 if (!_php_curl_setopt(ch, options, zvalue, return_value TSRMLS_CC)) { 2864 RETURN_TRUE; 2865 } else { 2866 RETURN_FALSE; 2867 } 2868} 2869/* }}} */ 2870 2871/* {{{ proto bool curl_setopt_array(resource ch, array options) 2872 Set an array of option for a cURL transfer */ 2873PHP_FUNCTION(curl_setopt_array) 2874{ 2875 zval *zid, *arr, **entry; 2876 php_curl *ch; 2877 ulong option; 2878 HashPosition pos; 2879 char *string_key; 2880 uint str_key_len; 2881 2882 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za", &zid, &arr) == FAILURE) { 2883 return; 2884 } 2885 2886 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 2887 2888 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos); 2889 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) { 2890 if (zend_hash_get_current_key_ex(Z_ARRVAL_P(arr), &string_key, &str_key_len, &option, 0, &pos) != HASH_KEY_IS_LONG) { 2891 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array keys must be CURLOPT constants or equivalent integer values"); 2892 RETURN_FALSE; 2893 } 2894 if (_php_curl_setopt(ch, (long) option, entry, return_value TSRMLS_CC)) { 2895 RETURN_FALSE; 2896 } 2897 zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos); 2898 } 2899 RETURN_TRUE; 2900} 2901/* }}} */ 2902 2903/* {{{ _php_curl_cleanup_handle(ch) 2904 Cleanup an execution phase */ 2905void _php_curl_cleanup_handle(php_curl *ch) 2906{ 2907 if (ch->handlers->write->buf.len > 0) { 2908 smart_str_free(&ch->handlers->write->buf); 2909 } 2910 if (ch->header.str_len) { 2911 efree(ch->header.str); 2912 ch->header.str_len = 0; 2913 } 2914 2915 memset(ch->err.str, 0, CURL_ERROR_SIZE + 1); 2916 ch->err.no = 0; 2917} 2918/* }}} */ 2919 2920/* {{{ proto bool curl_exec(resource ch) 2921 Perform a cURL session */ 2922PHP_FUNCTION(curl_exec) 2923{ 2924 CURLcode error; 2925 zval *zid; 2926 php_curl *ch; 2927 2928 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) { 2929 return; 2930 } 2931 2932 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 2933 2934 _php_curl_verify_handlers(ch, 1 TSRMLS_CC); 2935 2936 _php_curl_cleanup_handle(ch); 2937 2938 error = curl_easy_perform(ch->cp); 2939 SAVE_CURL_ERROR(ch, error); 2940 /* CURLE_PARTIAL_FILE is returned by HEAD requests */ 2941 if (error != CURLE_OK && error != CURLE_PARTIAL_FILE) { 2942 if (ch->handlers->write->buf.len > 0) { 2943 smart_str_free(&ch->handlers->write->buf); 2944 } 2945 RETURN_FALSE; 2946 } 2947 2948 if (ch->handlers->std_err) { 2949 php_stream *stream; 2950 stream = (php_stream*)zend_fetch_resource(&ch->handlers->std_err TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream()); 2951 if (stream) { 2952 php_stream_flush(stream); 2953 } 2954 } 2955 2956 if (ch->handlers->write->method == PHP_CURL_RETURN && ch->handlers->write->buf.len > 0) { 2957 smart_str_0(&ch->handlers->write->buf); 2958 RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 1); 2959 } 2960 2961 /* flush the file handle, so any remaining data is synched to disk */ 2962 if (ch->handlers->write->method == PHP_CURL_FILE && ch->handlers->write->fp) { 2963 fflush(ch->handlers->write->fp); 2964 } 2965 if (ch->handlers->write_header->method == PHP_CURL_FILE && ch->handlers->write_header->fp) { 2966 fflush(ch->handlers->write_header->fp); 2967 } 2968 2969 if (ch->handlers->write->method == PHP_CURL_RETURN) { 2970 RETURN_EMPTY_STRING(); 2971 } else { 2972 RETURN_TRUE; 2973 } 2974} 2975/* }}} */ 2976 2977/* {{{ proto mixed curl_getinfo(resource ch [, int option]) 2978 Get information regarding a specific transfer */ 2979PHP_FUNCTION(curl_getinfo) 2980{ 2981 zval *zid; 2982 php_curl *ch; 2983 long option = 0; 2984 2985 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zid, &option) == FAILURE) { 2986 return; 2987 } 2988 2989 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 2990 2991 if (ZEND_NUM_ARGS() < 2) { 2992 char *s_code; 2993 long l_code; 2994 double d_code; 2995#if LIBCURL_VERSION_NUM > 0x071301 2996 struct curl_certinfo *ci = NULL; 2997 zval *listcode; 2998#endif 2999 3000 array_init(return_value); 3001 3002 if (curl_easy_getinfo(ch->cp, CURLINFO_EFFECTIVE_URL, &s_code) == CURLE_OK) { 3003 CAAS("url", s_code); 3004 } 3005 if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_TYPE, &s_code) == CURLE_OK) { 3006 if (s_code != NULL) { 3007 CAAS("content_type", s_code); 3008 } else { 3009 zval *retnull; 3010 MAKE_STD_ZVAL(retnull); 3011 ZVAL_NULL(retnull); 3012 CAAZ("content_type", retnull); 3013 } 3014 } 3015 if (curl_easy_getinfo(ch->cp, CURLINFO_HTTP_CODE, &l_code) == CURLE_OK) { 3016 CAAL("http_code", l_code); 3017 } 3018 if (curl_easy_getinfo(ch->cp, CURLINFO_HEADER_SIZE, &l_code) == CURLE_OK) { 3019 CAAL("header_size", l_code); 3020 } 3021 if (curl_easy_getinfo(ch->cp, CURLINFO_REQUEST_SIZE, &l_code) == CURLE_OK) { 3022 CAAL("request_size", l_code); 3023 } 3024 if (curl_easy_getinfo(ch->cp, CURLINFO_FILETIME, &l_code) == CURLE_OK) { 3025 CAAL("filetime", l_code); 3026 } 3027 if (curl_easy_getinfo(ch->cp, CURLINFO_SSL_VERIFYRESULT, &l_code) == CURLE_OK) { 3028 CAAL("ssl_verify_result", l_code); 3029 } 3030 if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_COUNT, &l_code) == CURLE_OK) { 3031 CAAL("redirect_count", l_code); 3032 } 3033 if (curl_easy_getinfo(ch->cp, CURLINFO_TOTAL_TIME, &d_code) == CURLE_OK) { 3034 CAAD("total_time", d_code); 3035 } 3036 if (curl_easy_getinfo(ch->cp, CURLINFO_NAMELOOKUP_TIME, &d_code) == CURLE_OK) { 3037 CAAD("namelookup_time", d_code); 3038 } 3039 if (curl_easy_getinfo(ch->cp, CURLINFO_CONNECT_TIME, &d_code) == CURLE_OK) { 3040 CAAD("connect_time", d_code); 3041 } 3042 if (curl_easy_getinfo(ch->cp, CURLINFO_PRETRANSFER_TIME, &d_code) == CURLE_OK) { 3043 CAAD("pretransfer_time", d_code); 3044 } 3045 if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_UPLOAD, &d_code) == CURLE_OK) { 3046 CAAD("size_upload", d_code); 3047 } 3048 if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_DOWNLOAD, &d_code) == CURLE_OK) { 3049 CAAD("size_download", d_code); 3050 } 3051 if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_DOWNLOAD, &d_code) == CURLE_OK) { 3052 CAAD("speed_download", d_code); 3053 } 3054 if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_UPLOAD, &d_code) == CURLE_OK) { 3055 CAAD("speed_upload", d_code); 3056 } 3057 if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d_code) == CURLE_OK) { 3058 CAAD("download_content_length", d_code); 3059 } 3060 if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_UPLOAD, &d_code) == CURLE_OK) { 3061 CAAD("upload_content_length", d_code); 3062 } 3063 if (curl_easy_getinfo(ch->cp, CURLINFO_STARTTRANSFER_TIME, &d_code) == CURLE_OK) { 3064 CAAD("starttransfer_time", d_code); 3065 } 3066 if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_TIME, &d_code) == CURLE_OK) { 3067 CAAD("redirect_time", d_code); 3068 } 3069#if LIBCURL_VERSION_NUM >= 0x071202 /* Available since 7.18.2 */ 3070 if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_URL, &s_code) == CURLE_OK) { 3071 CAAS("redirect_url", s_code); 3072 } 3073#endif 3074#if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */ 3075 if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_IP, &s_code) == CURLE_OK) { 3076 CAAS("primary_ip", s_code); 3077 } 3078#endif 3079#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ 3080 if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) { 3081 MAKE_STD_ZVAL(listcode); 3082 array_init(listcode); 3083 create_certinfo(ci, listcode TSRMLS_CC); 3084 CAAZ("certinfo", listcode); 3085 } 3086#endif 3087#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ 3088 if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_PORT, &l_code) == CURLE_OK) { 3089 CAAL("primary_port", l_code); 3090 } 3091 if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_IP, &s_code) == CURLE_OK) { 3092 CAAS("local_ip", s_code); 3093 } 3094 if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_PORT, &l_code) == CURLE_OK) { 3095 CAAL("local_port", l_code); 3096 } 3097#endif 3098 if (ch->header.str_len > 0) { 3099 CAAS("request_header", ch->header.str); 3100 } 3101 } else { 3102 switch (option) { 3103 case CURLINFO_HEADER_OUT: 3104 if (ch->header.str_len > 0) { 3105 RETURN_STRINGL(ch->header.str, ch->header.str_len, 1); 3106 } else { 3107 RETURN_FALSE; 3108 } 3109#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ 3110 case CURLINFO_CERTINFO: { 3111 struct curl_certinfo *ci = NULL; 3112 3113 array_init(return_value); 3114 3115 if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) { 3116 create_certinfo(ci, return_value TSRMLS_CC); 3117 } else { 3118 RETURN_FALSE; 3119 } 3120 break; 3121 } 3122#endif 3123 default: { 3124 int type = CURLINFO_TYPEMASK & option; 3125 switch (type) { 3126 case CURLINFO_STRING: 3127 { 3128 char *s_code = NULL; 3129 3130 if (curl_easy_getinfo(ch->cp, option, &s_code) == CURLE_OK && s_code) { 3131 RETURN_STRING(s_code, 1); 3132 } else { 3133 RETURN_FALSE; 3134 } 3135 break; 3136 } 3137 case CURLINFO_LONG: 3138 { 3139 long code = 0; 3140 3141 if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) { 3142 RETURN_LONG(code); 3143 } else { 3144 RETURN_FALSE; 3145 } 3146 break; 3147 } 3148 case CURLINFO_DOUBLE: 3149 { 3150 double code = 0.0; 3151 3152 if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) { 3153 RETURN_DOUBLE(code); 3154 } else { 3155 RETURN_FALSE; 3156 } 3157 break; 3158 } 3159 case CURLINFO_SLIST: 3160 { 3161 struct curl_slist *slist; 3162 array_init(return_value); 3163 if (curl_easy_getinfo(ch->cp, option, &slist) == CURLE_OK) { 3164 while (slist) { 3165 add_next_index_string(return_value, slist->data, 1); 3166 slist = slist->next; 3167 } 3168 curl_slist_free_all(slist); 3169 } else { 3170 RETURN_FALSE; 3171 } 3172 break; 3173 } 3174 default: 3175 RETURN_FALSE; 3176 } 3177 } 3178 } 3179 } 3180} 3181/* }}} */ 3182 3183/* {{{ proto string curl_error(resource ch) 3184 Return a string contain the last error for the current session */ 3185PHP_FUNCTION(curl_error) 3186{ 3187 zval *zid; 3188 php_curl *ch; 3189 3190 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) { 3191 return; 3192 } 3193 3194 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 3195 3196 ch->err.str[CURL_ERROR_SIZE] = 0; 3197 RETURN_STRING(ch->err.str, 1); 3198} 3199/* }}} */ 3200 3201/* {{{ proto int curl_errno(resource ch) 3202 Return an integer containing the last error number */ 3203PHP_FUNCTION(curl_errno) 3204{ 3205 zval *zid; 3206 php_curl *ch; 3207 3208 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) { 3209 return; 3210 } 3211 3212 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 3213 3214 RETURN_LONG(ch->err.no); 3215} 3216/* }}} */ 3217 3218/* {{{ proto void curl_close(resource ch) 3219 Close a cURL session */ 3220PHP_FUNCTION(curl_close) 3221{ 3222 zval *zid; 3223 php_curl *ch; 3224 3225 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) { 3226 return; 3227 } 3228 3229 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 3230 3231 if (ch->in_callback) { 3232 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempt to close cURL handle from a callback"); 3233 return; 3234 } 3235 3236 zend_list_delete(Z_LVAL_P(zid)); 3237} 3238/* }}} */ 3239 3240/* {{{ _php_curl_close() 3241 List destructor for curl handles */ 3242static void _php_curl_close_ex(php_curl *ch TSRMLS_DC) 3243{ 3244#if PHP_CURL_DEBUG 3245 fprintf(stderr, "DTOR CALLED, ch = %x\n", ch); 3246#endif 3247 3248 _php_curl_verify_handlers(ch, 0 TSRMLS_CC); 3249 3250 /* 3251 * Libcurl is doing connection caching. When easy handle is cleaned up, 3252 * if the handle was previously used by the curl_multi_api, the connection 3253 * remains open un the curl multi handle is cleaned up. Some protocols are 3254 * sending content like the FTP one, and libcurl try to use the 3255 * WRITEFUNCTION or the HEADERFUNCTION. Since structures used in those 3256 * callback are freed, we need to use an other callback to which avoid 3257 * segfaults. 3258 * 3259 * Libcurl commit d021f2e8a00 fix this issue and should be part of 7.28.2 3260 */ 3261 curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing); 3262 curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing); 3263 3264 curl_easy_cleanup(ch->cp); 3265 3266 /* cURL destructors should be invoked only by last curl handle */ 3267 if (Z_REFCOUNT_P(ch->clone) <= 1) { 3268 zend_llist_clean(&ch->to_free->str); 3269 zend_llist_clean(&ch->to_free->slist); 3270 zend_llist_clean(&ch->to_free->post); 3271 efree(ch->to_free); 3272 FREE_ZVAL(ch->clone); 3273 } else { 3274 Z_DELREF_P(ch->clone); 3275 } 3276 3277 if (ch->handlers->write->buf.len > 0) { 3278 smart_str_free(&ch->handlers->write->buf); 3279 } 3280 if (ch->handlers->write->func_name) { 3281 zval_ptr_dtor(&ch->handlers->write->func_name); 3282 } 3283 if (ch->handlers->read->func_name) { 3284 zval_ptr_dtor(&ch->handlers->read->func_name); 3285 } 3286 if (ch->handlers->write_header->func_name) { 3287 zval_ptr_dtor(&ch->handlers->write_header->func_name); 3288 } 3289#if CURLOPT_PASSWDFUNCTION != 0 3290 if (ch->handlers->passwd) { 3291 zval_ptr_dtor(&ch->handlers->passwd); 3292 } 3293#endif 3294 if (ch->handlers->std_err) { 3295 zval_ptr_dtor(&ch->handlers->std_err); 3296 } 3297 if (ch->header.str_len > 0) { 3298 efree(ch->header.str); 3299 } 3300 3301 if (ch->handlers->write_header->stream) { 3302 zval_ptr_dtor(&ch->handlers->write_header->stream); 3303 } 3304 if (ch->handlers->write->stream) { 3305 zval_ptr_dtor(&ch->handlers->write->stream); 3306 } 3307 if (ch->handlers->read->stream) { 3308 zval_ptr_dtor(&ch->handlers->read->stream); 3309 } 3310 3311 efree(ch->handlers->write); 3312 efree(ch->handlers->write_header); 3313 efree(ch->handlers->read); 3314 3315 if (ch->handlers->progress) { 3316 if (ch->handlers->progress->func_name) { 3317 zval_ptr_dtor(&ch->handlers->progress->func_name); 3318 } 3319 efree(ch->handlers->progress); 3320 } 3321 3322#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ 3323 if (ch->handlers->fnmatch) { 3324 if (ch->handlers->fnmatch->func_name) { 3325 zval_ptr_dtor(&ch->handlers->fnmatch->func_name); 3326 } 3327 efree(ch->handlers->fnmatch); 3328 } 3329#endif 3330 3331 efree(ch->handlers); 3332 efree(ch); 3333} 3334/* }}} */ 3335 3336/* {{{ _php_curl_close() 3337 List destructor for curl handles */ 3338static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC) 3339{ 3340 php_curl *ch = (php_curl *) rsrc->ptr; 3341 _php_curl_close_ex(ch TSRMLS_CC); 3342} 3343/* }}} */ 3344 3345#if LIBCURL_VERSION_NUM >= 0x070c00 /* Available since 7.12.0 */ 3346/* {{{ proto bool curl_strerror(int code) 3347 return string describing error code */ 3348PHP_FUNCTION(curl_strerror) 3349{ 3350 long code; 3351 const char *str; 3352 3353 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code) == FAILURE) { 3354 return; 3355 } 3356 3357 str = curl_easy_strerror(code); 3358 if (str) { 3359 RETURN_STRING(str, 1); 3360 } else { 3361 RETURN_NULL(); 3362 } 3363} 3364/* }}} */ 3365#endif 3366 3367#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */ 3368/* {{{ _php_curl_reset_handlers() 3369 Reset all handlers of a given php_curl */ 3370static void _php_curl_reset_handlers(php_curl *ch) 3371{ 3372 if (ch->handlers->write->stream) { 3373 Z_DELREF_P(ch->handlers->write->stream); 3374 ch->handlers->write->stream = NULL; 3375 } 3376 ch->handlers->write->fp = NULL; 3377 ch->handlers->write->method = PHP_CURL_STDOUT; 3378 3379 if (ch->handlers->write_header->stream) { 3380 Z_DELREF_P(ch->handlers->write_header->stream); 3381 ch->handlers->write_header->stream = NULL; 3382 } 3383 ch->handlers->write_header->fp = NULL; 3384 ch->handlers->write_header->method = PHP_CURL_IGNORE; 3385 3386 if (ch->handlers->read->stream) { 3387 Z_DELREF_P(ch->handlers->read->stream); 3388 ch->handlers->read->stream = NULL; 3389 } 3390 ch->handlers->read->fp = NULL; 3391 ch->handlers->read->fd = 0; 3392 ch->handlers->read->method = PHP_CURL_DIRECT; 3393 3394 if (ch->handlers->std_err) { 3395 zval_ptr_dtor(&ch->handlers->std_err); 3396 ch->handlers->std_err = NULL; 3397 } 3398 3399 if (ch->handlers->progress) { 3400 if (ch->handlers->progress->func_name) { 3401 zval_ptr_dtor(&ch->handlers->progress->func_name); 3402 } 3403 efree(ch->handlers->progress); 3404 ch->handlers->progress = NULL; 3405 } 3406 3407#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ 3408 if (ch->handlers->fnmatch) { 3409 if (ch->handlers->fnmatch->func_name) { 3410 zval_ptr_dtor(&ch->handlers->fnmatch->func_name); 3411 } 3412 efree(ch->handlers->fnmatch); 3413 ch->handlers->fnmatch = NULL; 3414 } 3415#endif 3416 3417} 3418/* }}} */ 3419 3420/* {{{ proto void curl_reset(resource ch) 3421 Reset all options of a libcurl session handle */ 3422PHP_FUNCTION(curl_reset) 3423{ 3424 zval *zid; 3425 php_curl *ch; 3426 3427 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) { 3428 return; 3429 } 3430 3431 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 3432 3433 if (ch->in_callback) { 3434 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempt to reset cURL handle from a callback"); 3435 return; 3436 } 3437 3438 curl_easy_reset(ch->cp); 3439 _php_curl_reset_handlers(ch); 3440 _php_curl_set_default_options(ch); 3441} 3442/* }}} */ 3443#endif 3444 3445#if LIBCURL_VERSION_NUM > 0x070f03 /* 7.15.4 */ 3446/* {{{ proto void curl_escape(resource ch, string str) 3447 URL encodes the given string */ 3448PHP_FUNCTION(curl_escape) 3449{ 3450 char *str = NULL, *res = NULL; 3451 int str_len = 0; 3452 zval *zid; 3453 php_curl *ch; 3454 3455 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zid, &str, &str_len) == FAILURE) { 3456 return; 3457 } 3458 3459 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 3460 3461 if ((res = curl_easy_escape(ch->cp, str, str_len))) { 3462 RETVAL_STRING(res, 1); 3463 curl_free(res); 3464 } else { 3465 RETURN_FALSE; 3466 } 3467} 3468/* }}} */ 3469 3470/* {{{ proto void curl_unescape(resource ch, string str) 3471 URL decodes the given string */ 3472PHP_FUNCTION(curl_unescape) 3473{ 3474 char *str = NULL, *out = NULL; 3475 int str_len = 0, out_len; 3476 zval *zid; 3477 php_curl *ch; 3478 3479 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zid, &str, &str_len) == FAILURE) { 3480 return; 3481 } 3482 3483 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 3484 3485 if ((out = curl_easy_unescape(ch->cp, str, str_len, &out_len))) { 3486 RETVAL_STRINGL(out, out_len, 1); 3487 curl_free(out); 3488 } else { 3489 RETURN_FALSE; 3490 } 3491} 3492/* }}} */ 3493#endif 3494 3495#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ 3496/* {{{ proto void curl_pause(resource ch, int bitmask) 3497 pause and unpause a connection */ 3498PHP_FUNCTION(curl_pause) 3499{ 3500 long bitmask; 3501 zval *zid; 3502 php_curl *ch; 3503 3504 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zid, &bitmask) == FAILURE) { 3505 return; 3506 } 3507 3508 ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); 3509 3510 RETURN_LONG(curl_easy_pause(ch->cp, bitmask)); 3511} 3512/* }}} */ 3513#endif 3514 3515#endif /* HAVE_CURL */ 3516 3517/* 3518 * Local variables: 3519 * tab-width: 4 3520 * c-basic-offset: 4 3521 * End: 3522 * vim600: fdm=marker 3523 * vim: noet sw=4 ts=4 3524 */ 3525