Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 88 additions & 141 deletions ext/curl/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,54 @@ static zend_object *curl_clone_obj(zend_object *object);
php_curl *init_curl_handle_into_zval(zval *curl);
static inline zend_result build_mime_structure_from_hash(php_curl *ch, zval *zpostfields);

struct php_curl_feature {
const char *name;
int bitmask;
};

/* To update on each new cURL release using src/main.c in cURL sources */
static const struct php_curl_feature php_curl_features[] = {
{ "AsynchDNS", CURL_VERSION_ASYNCHDNS },
{ "CharConv", CURL_VERSION_CONV },
{ "Debug", CURL_VERSION_DEBUG },
{ "GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE },
{ "IDN", CURL_VERSION_IDN },
{ "IPv6", CURL_VERSION_IPV6 },
{ "krb4", CURL_VERSION_KERBEROS4 },
{ "Largefile", CURL_VERSION_LARGEFILE },
{ "libz", CURL_VERSION_LIBZ },
{ "NTLM", CURL_VERSION_NTLM },
{ "NTLMWB", CURL_VERSION_NTLM_WB },
{ "SPNEGO", CURL_VERSION_SPNEGO },
{ "SSL", CURL_VERSION_SSL },
{ "SSPI", CURL_VERSION_SSPI },
{ "TLS-SRP", CURL_VERSION_TLSAUTH_SRP },
{ "HTTP2", CURL_VERSION_HTTP2 },
{ "GSSAPI", CURL_VERSION_GSSAPI },
{ "KERBEROS5", CURL_VERSION_KERBEROS5 },
{ "UNIX_SOCKETS", CURL_VERSION_UNIX_SOCKETS },
{ "PSL", CURL_VERSION_PSL },
{ "HTTPS_PROXY", CURL_VERSION_HTTPS_PROXY },
{ "MULTI_SSL", CURL_VERSION_MULTI_SSL },
{ "BROTLI", CURL_VERSION_BROTLI },
#if LIBCURL_VERSION_NUM >= 0x074001 /* Available since 7.64.1 */
{ "ALTSVC", CURL_VERSION_ALTSVC },
#endif
#if LIBCURL_VERSION_NUM >= 0x074200 /* Available since 7.66.0 */
{ "HTTP3", CURL_VERSION_HTTP3 },
#endif
#if LIBCURL_VERSION_NUM >= 0x074800 /* Available since 7.72.0 */
{ "UNICODE", CURL_VERSION_UNICODE },
{ "ZSTD", CURL_VERSION_ZSTD },
#endif
#if LIBCURL_VERSION_NUM >= 0x074a00 /* Available since 7.74.0 */
{ "HSTS", CURL_VERSION_HSTS },
#endif
#if LIBCURL_VERSION_NUM >= 0x074c00 /* Available since 7.76.0 */
{ "GSASL", CURL_VERSION_GSASL },
#endif
};

/* {{{ PHP_INI_BEGIN */
PHP_INI_BEGIN()
PHP_INI_ENTRY("curl.cainfo", "", PHP_INI_SYSTEM, NULL)
Expand All @@ -253,69 +301,17 @@ PHP_MINFO_FUNCTION(curl)

d = curl_version_info(CURLVERSION_NOW);
php_info_print_table_start();
php_info_print_table_row(2, "cURL support", "enabled");
php_info_print_table_row(2, "cURL support", "enabled");
php_info_print_table_row(2, "cURL Information", d->version);
snprintf(str, sizeof(str), "%d", d->age);
php_info_print_table_row(2, "Age", str);

/* To update on each new cURL release using src/main.c in cURL sources */
/* make sure to sync this list with curl_version as well */
if (d->features) {
struct feat {
const char *name;
int bitmask;
};

unsigned int i;

static const struct feat feats[] = {
{"AsynchDNS", CURL_VERSION_ASYNCHDNS},
{"CharConv", CURL_VERSION_CONV},
{"Debug", CURL_VERSION_DEBUG},
{"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE},
{"IDN", CURL_VERSION_IDN},
{"IPv6", CURL_VERSION_IPV6},
{"krb4", CURL_VERSION_KERBEROS4},
{"Largefile", CURL_VERSION_LARGEFILE},
{"libz", CURL_VERSION_LIBZ},
{"NTLM", CURL_VERSION_NTLM},
{"NTLMWB", CURL_VERSION_NTLM_WB},
{"SPNEGO", CURL_VERSION_SPNEGO},
{"SSL", CURL_VERSION_SSL},
{"SSPI", CURL_VERSION_SSPI},
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
{"HTTP2", CURL_VERSION_HTTP2},
{"GSSAPI", CURL_VERSION_GSSAPI},
{"KERBEROS5", CURL_VERSION_KERBEROS5},
{"UNIX_SOCKETS", CURL_VERSION_UNIX_SOCKETS},
{"PSL", CURL_VERSION_PSL},
{"HTTPS_PROXY", CURL_VERSION_HTTPS_PROXY},
{"MULTI_SSL", CURL_VERSION_MULTI_SSL},
{"BROTLI", CURL_VERSION_BROTLI},
#if LIBCURL_VERSION_NUM >= 0x074001 /* Available since 7.64.1 */
{"ALTSVC", CURL_VERSION_ALTSVC},
#endif
#if LIBCURL_VERSION_NUM >= 0x074200 /* Available since 7.66.0 */
{"HTTP3", CURL_VERSION_HTTP3},
#endif
#if LIBCURL_VERSION_NUM >= 0x074800 /* Available since 7.72.0 */
{"UNICODE", CURL_VERSION_UNICODE},
{"ZSTD", CURL_VERSION_ZSTD},
#endif
#if LIBCURL_VERSION_NUM >= 0x074a00 /* Available since 7.74.0 */
{"HSTS", CURL_VERSION_HSTS},
#endif
#if LIBCURL_VERSION_NUM >= 0x074c00 /* Available since 7.76.0 */
{"GSASL", CURL_VERSION_GSASL},
#endif
{NULL, 0}
};

php_info_print_table_row(1, "Features");
for(i=0; i<sizeof(feats)/sizeof(feats[0]); i++) {
if (feats[i].name) {
php_info_print_table_row(2, feats[i].name, d->features & feats[i].bitmask ? "Yes" : "No");
}
for (i = 0; i < sizeof(php_curl_features) / sizeof(php_curl_features[0]); i++) {
php_info_print_table_row(2, php_curl_features[i].name, d->features & php_curl_features[i].bitmask ? "Yes" : "No");
}
}

Expand Down Expand Up @@ -513,6 +509,7 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
zend_get_gc_buffer_add_fcc(gc_buffer, &curl->handlers.prereq);
}
#endif

#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
if (ZEND_FCC_INITIALIZED(curl->handlers.sshhostkey)) {
zend_get_gc_buffer_add_fcc(gc_buffer, &curl->handlers.sshhostkey);
Expand Down Expand Up @@ -728,8 +725,8 @@ static int curl_prereqfunction(void *clientp, char *conn_primary_ip, char *conn_
// gets called. Return CURL_PREREQFUNC_OK immediately in this case to avoid
// zend_call_known_fcc() with an uninitialized FCC.
if (!ZEND_FCC_INITIALIZED(ch->handlers.prereq)) {
return rval;
}
return rval;
}

#if PHP_CURL_DEBUG
fprintf(stderr, "curl_prereqfunction() called\n");
Expand Down Expand Up @@ -924,42 +921,42 @@ static int curl_debug(CURL *handle, curl_infotype type, char *data, size_t size,
{
php_curl *ch = (php_curl *)clientp;

#if PHP_CURL_DEBUG
fprintf(stderr, "curl_debug() called\n");
fprintf(stderr, "type = %d, data = %s\n", type, data);
#endif
#if PHP_CURL_DEBUG
fprintf(stderr, "curl_debug() called\n");
fprintf(stderr, "type = %d, data = %s\n", type, data);
#endif

// Implicitly store the headers for compatibility with CURLINFO_HEADER_OUT
// used as a Curl option. Previously, setting CURLINFO_HEADER_OUT set curl_debug
// as the CURLOPT_DEBUGFUNCTION and stored the debug data when type is set to
// CURLINFO_HEADER_OUT. For backward compatibility, we now store the headers
// but also call the user-callback function if available.
if (type == CURLINFO_HEADER_OUT) {
if (ch->header.str) {
zend_string_release_ex(ch->header.str, 0);
}
ch->header.str = zend_string_init(data, size, 0);
}
if (type == CURLINFO_HEADER_OUT) {
if (ch->header.str) {
zend_string_release_ex(ch->header.str, 0);
}
ch->header.str = zend_string_init(data, size, 0);
}

if (!ZEND_FCC_INITIALIZED(ch->handlers.debug)) {
return 0;
}
if (!ZEND_FCC_INITIALIZED(ch->handlers.debug)) {
return 0;
}

zval args[3];
zval args[3];

GC_ADDREF(&ch->std);
ZVAL_OBJ(&args[0], &ch->std);
ZVAL_LONG(&args[1], type);
ZVAL_STRINGL(&args[2], data, size);
GC_ADDREF(&ch->std);
ZVAL_OBJ(&args[0], &ch->std);
ZVAL_LONG(&args[1], type);
ZVAL_STRINGL(&args[2], data, size);

ch->in_callback = true;
zend_call_known_fcc(&ch->handlers.debug, NULL, /* param_count */ 3, args, /* named_params */ NULL);
ch->in_callback = false;
ch->in_callback = true;
zend_call_known_fcc(&ch->handlers.debug, NULL, /* param_count */ 3, args, /* named_params */ NULL);
ch->in_callback = false;

zval_ptr_dtor(&args[0]);
zval_ptr_dtor(&args[2]);
zval_ptr_dtor(&args[0]);
zval_ptr_dtor(&args[2]);

return 0;
return 0;
}
/* }}} */

Expand Down Expand Up @@ -1012,62 +1009,12 @@ PHP_FUNCTION(curl_version)
CAAL("features", d->features);
/* Add an array of features */
{
struct feat {
const char *name;
int bitmask;
};

unsigned int i;
zval feature_list;
array_init(&feature_list);

/* Sync this list with PHP_MINFO_FUNCTION(curl) as well */
static const struct feat feats[] = {
{"AsynchDNS", CURL_VERSION_ASYNCHDNS},
{"CharConv", CURL_VERSION_CONV},
{"Debug", CURL_VERSION_DEBUG},
{"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE},
{"IDN", CURL_VERSION_IDN},
{"IPv6", CURL_VERSION_IPV6},
{"krb4", CURL_VERSION_KERBEROS4},
{"Largefile", CURL_VERSION_LARGEFILE},
{"libz", CURL_VERSION_LIBZ},
{"NTLM", CURL_VERSION_NTLM},
{"NTLMWB", CURL_VERSION_NTLM_WB},
{"SPNEGO", CURL_VERSION_SPNEGO},
{"SSL", CURL_VERSION_SSL},
{"SSPI", CURL_VERSION_SSPI},
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
{"HTTP2", CURL_VERSION_HTTP2},
{"GSSAPI", CURL_VERSION_GSSAPI},
{"KERBEROS5", CURL_VERSION_KERBEROS5},
{"UNIX_SOCKETS", CURL_VERSION_UNIX_SOCKETS},
{"PSL", CURL_VERSION_PSL},
{"HTTPS_PROXY", CURL_VERSION_HTTPS_PROXY},
{"MULTI_SSL", CURL_VERSION_MULTI_SSL},
{"BROTLI", CURL_VERSION_BROTLI},
#if LIBCURL_VERSION_NUM >= 0x074001 /* Available since 7.64.1 */
{"ALTSVC", CURL_VERSION_ALTSVC},
#endif
#if LIBCURL_VERSION_NUM >= 0x074200 /* Available since 7.66.0 */
{"HTTP3", CURL_VERSION_HTTP3},
#endif
#if LIBCURL_VERSION_NUM >= 0x074800 /* Available since 7.72.0 */
{"UNICODE", CURL_VERSION_UNICODE},
{"ZSTD", CURL_VERSION_ZSTD},
#endif
#if LIBCURL_VERSION_NUM >= 0x074a00 /* Available since 7.74.0 */
{"HSTS", CURL_VERSION_HSTS},
#endif
#if LIBCURL_VERSION_NUM >= 0x074c00 /* Available since 7.76.0 */
{"GSASL", CURL_VERSION_GSASL},
#endif
};

for(i = 0; i < sizeof(feats) / sizeof(feats[0]); i++) {
if (feats[i].name) {
add_assoc_bool(&feature_list, feats[i].name, d->features & feats[i].bitmask ? true : false);
}
array_init_size(&feature_list, sizeof(php_curl_features) / sizeof(php_curl_features[0]));
for (i = 0; i < sizeof(php_curl_features) / sizeof(php_curl_features[0]); i++) {
add_assoc_bool(&feature_list, php_curl_features[i].name, d->features & php_curl_features[i].bitmask ? true : false);
}

CAAZ("feature_list", &feature_list);
Expand Down Expand Up @@ -1813,7 +1760,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
case CURLOPT_DNS_SHUFFLE_ADDRESSES:
case CURLOPT_HAPROXYPROTOCOL:
case CURLOPT_DISALLOW_USERNAME_IN_URL:
#if LIBCURL_VERSION_NUM >= 0x073E00 /* Available since 7.62.0 */
#if LIBCURL_VERSION_NUM >= 0x073e00 /* Available since 7.62.0 */
case CURLOPT_UPKEEP_INTERVAL_MS:
case CURLOPT_UPLOAD_BUFFERSIZE:
#endif
Expand Down Expand Up @@ -1976,7 +1923,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
case CURLOPT_DNS_LOCAL_IP6:
case CURLOPT_XOAUTH2_BEARER:
case CURLOPT_UNIX_SOCKET_PATH:
#if LIBCURL_VERSION_NUM >= 0x073E00 /* Available since 7.62.0 */
#if LIBCURL_VERSION_NUM >= 0x073e00 /* Available since 7.62.0 */
case CURLOPT_DOH_URL:
#endif
#if LIBCURL_VERSION_NUM >= 0x074a00 /* Available since 7.74.0 */
Expand Down Expand Up @@ -2282,9 +2229,9 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue

case CURLINFO_HEADER_OUT:
if (ZEND_FCC_INITIALIZED(ch->handlers.debug)) {
zend_value_error("CURLINFO_HEADER_OUT option must not be set when the CURLOPT_DEBUGFUNCTION option is set");
return FAILURE;
}
zend_value_error("CURLINFO_HEADER_OUT option must not be set when the CURLOPT_DEBUGFUNCTION option is set");
return FAILURE;
}

if (zend_is_true(zvalue)) {
curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug);
Expand Down Expand Up @@ -3071,7 +3018,7 @@ PHP_FUNCTION(curl_pause)
}
/* }}} */

#if LIBCURL_VERSION_NUM >= 0x073E00 /* Available since 7.62.0 */
#if LIBCURL_VERSION_NUM >= 0x073e00 /* Available since 7.62.0 */
/* {{{ perform connection upkeep checks */
PHP_FUNCTION(curl_upkeep)
{
Expand All @@ -3090,5 +3037,5 @@ PHP_FUNCTION(curl_upkeep)

RETURN_BOOL(error == CURLE_OK);
}
/*}}} */
/* }}} */
#endif