X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=src%2Fphp_http_client_curl.c;h=e779ff5157f7e7640327ce477a540995988dcc04;hp=18eb944708b7d74b562966a9f4fed1b0e6552aac;hb=ed02721b0b9a64e7bec3e98e3dc4f535c3802e61;hpb=f6a612bfd0eb7ff179c013f3226b6a7790bb4d82 diff --git a/src/php_http_client_curl.c b/src/php_http_client_curl.c index 18eb944..e779ff5 100644 --- a/src/php_http_client_curl.c +++ b/src/php_http_client_curl.c @@ -12,53 +12,17 @@ #include "php_http_api.h" #include "php_http_client.h" +#include "php_http_client_curl_event.h" +#include "php_http_client_curl_user.h" -#if PHP_HTTP_HAVE_CURL - -#if PHP_HTTP_HAVE_EVENT -# if !PHP_HTTP_HAVE_EVENT2 && /* just be really sure */ !(LIBEVENT_VERSION_NUMBER >= 0x02000000) -# include -# define event_base_new event_init -# define event_assign(e, b, s, a, cb, d) do {\ - event_set(e, s, a, cb, d); \ - event_base_set(b, e); \ - } while(0) -# else -# if PHP_HTTP_HAVE_EVENT2 -# include -# include -# else -# error "libevent presence is unknown" -# endif -# endif -# ifndef DBG_EVENTS -# define DBG_EVENTS 0 -# endif -#endif +#if PHP_HTTP_HAVE_LIBCURL -#ifdef PHP_HTTP_HAVE_OPENSSL +#if PHP_HTTP_HAVE_LIBCURL_OPENSSL # include #endif -#ifdef PHP_HTTP_HAVE_GNUTLS -# include -#endif - -typedef struct php_http_client_curl_handle { - CURLM *multi; - CURLSH *share; -} php_http_client_curl_handle_t; - -typedef struct php_http_client_curl { - php_http_client_curl_handle_t *handle; - - int unfinished; /* int because of curl_multi_perform() */ - -#if PHP_HTTP_HAVE_EVENT - struct event_base *evbase; - struct event *timeout; - unsigned useevents:1; +#if PHP_HTTP_HAVE_LIBCURL_GNUTLS +# include #endif -} php_http_client_curl_t; typedef struct php_http_client_curl_handler { CURL *handle; @@ -82,7 +46,7 @@ typedef struct php_http_client_curl_handler { php_http_buffer_t ranges; struct { - uint count; + uint32_t count; double delay; } retry; @@ -213,22 +177,19 @@ static int php_http_curle_progress_callback(void *ctx, double dltotal, double dl #endif { php_http_client_curl_handler_t *h = ctx; - zend_bool update = 0; if (h->progress.dl.total != dltotal || h->progress.dl.now != dlnow || h->progress.ul.total != ultotal || h->progress.ul.now != ulnow ) { - update = 1; - h->progress.dl.total = dltotal; h->progress.dl.now = dlnow; h->progress.ul.total = ultotal; h->progress.ul.now = ulnow; } - if (update && h->client->callback.progress.func) { + if (h->client->callback.progress.func) { h->client->callback.progress.func(h->client->callback.progress.arg, h->client, &h->queue, &h->progress); } @@ -251,11 +212,13 @@ static int php_http_curle_seek_callback(void *userdata, curl_off_t offset, int o static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data, size_t length, void *ctx) { php_http_client_curl_handler_t *h = ctx; + unsigned utype = PHP_HTTP_CLIENT_DEBUG_INFO; /* catch progress */ switch (type) { case CURLINFO_TEXT: if (data[0] == '-') { + goto text; } else if (php_memnstr(data, ZEND_STRL("Adding handle:"), data + length)) { h->progress.info = "setup"; } else if (php_memnstr(data, ZEND_STRL("addHandle"), data + length)) { @@ -272,8 +235,16 @@ static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data, h->progress.info = "connected"; } else if (php_memnstr(data, ZEND_STRL("blacklisted"), data + length)) { h->progress.info = "blacklist check"; + } else if (php_memnstr(data, ZEND_STRL("TLS"), data + length)) { + h->progress.info = "ssl negotiation"; } else if (php_memnstr(data, ZEND_STRL("SSL"), data + length)) { h->progress.info = "ssl negotiation"; + } else if (php_memnstr(data, ZEND_STRL("certificate"), data + length)) { + h->progress.info = "ssl negotiation"; + } else if (php_memnstr(data, ZEND_STRL("ALPN"), data + length)) { + h->progress.info = "alpn"; + } else if (php_memnstr(data, ZEND_STRL("NPN"), data + length)) { + h->progress.info = "npn"; } else if (php_memnstr(data, ZEND_STRL("upload"), data + length)) { h->progress.info = "uploaded"; } else if (php_memnstr(data, ZEND_STRL("left intact"), data + length)) { @@ -285,6 +256,7 @@ static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data, } else if (php_memnstr(data, ZEND_STRL("Operation timed out"), data + length)) { h->progress.info = "timeout"; } else { + text:; #if 0 h->progress.info = data; data[length - 1] = '\0'; @@ -294,20 +266,43 @@ static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data, h->client->callback.progress.func(h->client->callback.progress.arg, h->client, &h->queue, &h->progress); } break; + case CURLINFO_HEADER_OUT: - case CURLINFO_DATA_OUT: + utype |= PHP_HTTP_CLIENT_DEBUG_HEADER; + goto data_out; + case CURLINFO_SSL_DATA_OUT: + utype |= PHP_HTTP_CLIENT_DEBUG_SSL; + goto data_out; + + case CURLINFO_DATA_OUT: + data_out: + utype |= PHP_HTTP_CLIENT_DEBUG_OUT; h->progress.info = "send"; break; + case CURLINFO_HEADER_IN: - case CURLINFO_DATA_IN: + utype |= PHP_HTTP_CLIENT_DEBUG_HEADER; + goto data_in; + case CURLINFO_SSL_DATA_IN: + utype |= PHP_HTTP_CLIENT_DEBUG_SSL; + goto data_in; + + case CURLINFO_DATA_IN: + data_in: + utype |= PHP_HTTP_CLIENT_DEBUG_IN; h->progress.info = "receive"; break; + default: break; } + if (h->client->callback.debug.func) { + h->client->callback.debug.func(h->client->callback.debug.arg, h->client, &h->queue, utype, data, length); + } + #if 0 /* debug */ _dpf(type, data, length); @@ -335,8 +330,11 @@ static ZEND_RESULT_CODE php_http_curle_get_info(CURL *ch, HashTable *info) char *c = NULL; long l = 0; double d = 0; + curl_off_t o = 0; struct curl_slist *s = NULL, *p = NULL; - zval tmp = {{0}}; + zval tmp; + + ZVAL_NULL(&tmp); /* BEGIN::CURLINFO */ if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_EFFECTIVE_URL, &c)) { @@ -489,6 +487,48 @@ static ZEND_RESULT_CODE php_http_curle_get_info(CURL *ch, HashTable *info) zend_hash_str_update(info, "local_port", lenof("local_port"), &tmp); } #endif +#if PHP_HTTP_CURL_VERSION(7,50,0) + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_HTTP_VERSION, &l)) { + ZVAL_LONG(&tmp, l); + zend_hash_str_update(info, "http_version", lenof("http_version"), &tmp); + } +#endif +#if PHP_HTTP_CURL_VERSION(7,52,0) + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_PROXY_SSL_VERIFYRESULT, &l)) { + ZVAL_LONG(&tmp, l); + zend_hash_str_update(info, "proxy_ssl_verifyresult", lenof("proxy_ssl_verifyresult"), &tmp); + } +#endif +#if PHP_HTTP_CURL_VERSION(7,52,0) + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_PROTOCOL, &l)) { + ZVAL_LONG(&tmp, l); + zend_hash_str_update(info, "protocol", lenof("protocol"), &tmp); + } +#endif +#if PHP_HTTP_CURL_VERSION(7,52,0) + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_SCHEME, &c)) { + ZVAL_STRING(&tmp, STR_PTR(c)); + zend_hash_str_update(info, "scheme", lenof("scheme"), &tmp); + } +#endif +#if PHP_HTTP_CURL_VERSION(7,66,0) + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_RETRY_AFTER, &o)) { + ZVAL_LONG(&tmp, o); + zend_hash_str_update(info, "retry_after", lenof("retry_after"), &tmp); + } +#endif +#if PHP_HTTP_CURL_VERSION(7,72,0) + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_EFFECTIVE_METHOD, &c)) { + ZVAL_STRING(&tmp, STR_PTR(c)); + zend_hash_str_update(info, "effective_method", lenof("effective_method"), &tmp); + } +#endif +#if PHP_HTTP_CURL_VERSION(7,73,0) + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_PROXY_ERROR, &l)) { + ZVAL_LONG(&tmp, l); + zend_hash_str_update(info, "proxy_error", lenof("proxy_error"), &tmp); + } +#endif /* END::CURLINFO */ @@ -497,7 +537,11 @@ static ZEND_RESULT_CODE php_http_curle_get_info(CURL *ch, HashTable *info) zval ti_array, subarray; struct curl_tlssessioninfo *ti; +#if PHP_HTTP_CURL_VERSION(7,48,0) + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_TLS_SSL_PTR, &ti)) { +#else if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_TLS_SESSION, &ti)) { +#endif char *backend; ZVAL_NULL(&subarray); @@ -509,33 +553,42 @@ static ZEND_RESULT_CODE php_http_curle_get_info(CURL *ch, HashTable *info) break; case CURLSSLBACKEND_OPENSSL: backend = "openssl"; -#ifdef PHP_HTTP_HAVE_OPENSSL +#if PHP_HTTP_HAVE_LIBCURL_OPENSSL { +#if PHP_HTTP_CURL_VERSION(7,48,0) + SSL *ssl = ti->internals; + SSL_CTX *ctx = ssl ? SSL_get_SSL_CTX(ssl) : NULL; +#else SSL_CTX *ctx = ti->internals; +#endif array_init(&subarray); - add_assoc_long_ex(&subarray, ZEND_STRL("number"), SSL_CTX_sess_number(ctx)); - add_assoc_long_ex(&subarray, ZEND_STRL("connect"), SSL_CTX_sess_connect(ctx)); - add_assoc_long_ex(&subarray, ZEND_STRL("connect_good"), SSL_CTX_sess_connect_good(ctx)); - add_assoc_long_ex(&subarray, ZEND_STRL("connect_renegotiate"), SSL_CTX_sess_connect_renegotiate(ctx)); - add_assoc_long_ex(&subarray, ZEND_STRL("hits"), SSL_CTX_sess_hits(ctx)); - add_assoc_long_ex(&subarray, ZEND_STRL("cache_full"), SSL_CTX_sess_cache_full(ctx)); + if (ctx) { + add_assoc_long_ex(&subarray, ZEND_STRL("number"), SSL_CTX_sess_number(ctx)); + add_assoc_long_ex(&subarray, ZEND_STRL("connect"), SSL_CTX_sess_connect(ctx)); + add_assoc_long_ex(&subarray, ZEND_STRL("connect_good"), SSL_CTX_sess_connect_good(ctx)); + add_assoc_long_ex(&subarray, ZEND_STRL("connect_renegotiate"), SSL_CTX_sess_connect_renegotiate(ctx)); + add_assoc_long_ex(&subarray, ZEND_STRL("hits"), SSL_CTX_sess_hits(ctx)); + add_assoc_long_ex(&subarray, ZEND_STRL("cache_full"), SSL_CTX_sess_cache_full(ctx)); + } } #endif break; case CURLSSLBACKEND_GNUTLS: backend = "gnutls"; -#ifdef PHP_HTTP_HAVE_GNUTLS +#if PHP_HTTP_HAVE_LIBCURL_GNUTLS { gnutls_session_t sess = ti->internals; char *desc; array_init(&subarray); - if ((desc = gnutls_session_get_desc(sess))) { - add_assoc_string_ex(&subarray, ZEND_STRL("desc"), desc); - gnutls_free(desc); + if (sess) { + if ((desc = gnutls_session_get_desc(sess))) { + add_assoc_string_ex(&subarray, ZEND_STRL("desc"), desc); + gnutls_free(desc); + } + add_assoc_bool_ex(&subarray, ZEND_STRL("resumed"), gnutls_session_is_resumed(sess)); } - add_assoc_bool_ex(&subarray, ZEND_STRL("resumed"), gnutls_session_is_resumed(sess)); } #endif break; @@ -573,7 +626,10 @@ static ZEND_RESULT_CODE php_http_curle_get_info(CURL *ch, HashTable *info) } #endif -#if (PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)) || (PHP_HTTP_CURL_VERSION(7,34,0) && defined(PHP_HTTP_HAVE_NSS)) || (PHP_HTTP_CURL_VERSION(7,42,0) && defined(PHP_HTTP_HAVE_GNUTLS)) || (PHP_HTTP_CURL_VERSION(7,39,0) && defined(PHP_HTTP_HAVE_GSKIT)) +#if (PHP_HTTP_CURL_VERSION(7,19,1) && PHP_HTTP_HAVE_LIBCURL_OPENSSL) || \ + (PHP_HTTP_CURL_VERSION(7,34,0) && PHP_HTTP_HAVE_LIBCURL_NSS) || \ + (PHP_HTTP_CURL_VERSION(7,42,0) && PHP_HTTP_HAVE_LIBCURL_GNUTLS) || \ + (PHP_HTTP_CURL_VERSION(7,39,0) && PHP_HTTP_HAVE_LIBCURL_GSKIT) { int i; zval ci_array, subarray; @@ -625,7 +681,7 @@ static php_http_message_t *php_http_curlm_responseparser(php_http_client_curl_ha { php_http_message_t *response; php_http_header_parser_t parser; - zval *zh; + zval *zh, tmp; response = php_http_message_init(NULL, 0, h->response.body); php_http_header_parser_init(&parser); @@ -654,30 +710,30 @@ static php_http_message_t *php_http_curlm_responseparser(php_http_client_curl_ha /* let's update the response headers */ if ((zh = php_http_message_header(response, ZEND_STRL("Content-Length")))) { - Z_TRY_ADDREF_P(zh); - zend_hash_str_update(&response->hdrs, "X-Original-Content-Length", lenof("X-Original-Content-Length"), zh); + ZVAL_COPY(&tmp, zh); + zend_hash_str_update(&response->hdrs, "X-Original-Content-Length", lenof("X-Original-Content-Length"), &tmp); } if ((zh = php_http_message_header(response, ZEND_STRL("Transfer-Encoding")))) { - Z_TRY_ADDREF_P(zh); - zend_hash_str_update(&response->hdrs, "X-Original-Transfer-Encoding", lenof("X-Original-Transfer-Encoding"), zh); + ZVAL_COPY(&tmp, zh); zend_hash_str_del(&response->hdrs, "Transfer-Encoding", lenof("Transfer-Encoding")); + zend_hash_str_update(&response->hdrs, "X-Original-Transfer-Encoding", lenof("X-Original-Transfer-Encoding"), &tmp); } if ((zh = php_http_message_header(response, ZEND_STRL("Content-Range")))) { - Z_TRY_ADDREF_P(zh); - zend_hash_str_update(&response->hdrs, "X-Original-Content-Range", lenof("X-Original-Content-Range"), zh); + ZVAL_COPY(&tmp, zh); zend_hash_str_del(&response->hdrs, "Content-Range", lenof("Content-Range")); + zend_hash_str_update(&response->hdrs, "X-Original-Content-Range", lenof("X-Original-Content-Range"), &tmp); } if ((zh = php_http_message_header(response, ZEND_STRL("Content-Encoding")))) { - Z_TRY_ADDREF_P(zh); - zend_hash_str_update(&response->hdrs, "X-Original-Content-Encoding", lenof("X-Original-Content-Encoding"), zh); + ZVAL_COPY(&tmp, zh); zend_hash_str_del(&response->hdrs, "Content-Encoding", lenof("Content-Encoding")); + zend_hash_str_update(&response->hdrs, "X-Original-Content-Encoding", lenof("X-Original-Content-Encoding"), &tmp); } php_http_message_update_headers(response); return response; } -static void php_http_curlm_responsehandler(php_http_client_t *context) +void php_http_client_curl_responsehandler(php_http_client_t *context) { int err_count = 0, remaining = 0; php_http_curle_storage_t *st, *err = NULL; @@ -729,158 +785,26 @@ static void php_http_curlm_responsehandler(php_http_client_t *context) } } -#if PHP_HTTP_HAVE_EVENT - -typedef struct php_http_curlm_event { - struct event evnt; - php_http_client_t *context; -} php_http_curlm_event_t; - -static inline int etoca(short action) { - switch (action & (EV_READ|EV_WRITE)) { - case EV_READ: - return CURL_CSELECT_IN; - break; - case EV_WRITE: - return CURL_CSELECT_OUT; - break; - case EV_READ|EV_WRITE: - return CURL_CSELECT_IN|CURL_CSELECT_OUT; - break; - default: - return 0; - } -} - -static void php_http_curlm_timeout_callback(int socket, short action, void *event_data) -{ - php_http_client_t *context = event_data; - php_http_client_curl_t *curl = context->ctx; - -#if DBG_EVENTS - fprintf(stderr, "T"); -#endif - if (curl->useevents) { - CURLMcode rc; - - /* ignore and use -1,0 on timeout */ - (void) socket; - (void) action; - - while (CURLM_CALL_MULTI_PERFORM == (rc = curl_multi_socket_action(curl->handle->multi, CURL_SOCKET_TIMEOUT, 0, &curl->unfinished))); - - if (CURLM_OK != rc) { - php_error_docref(NULL, E_WARNING, "%s", curl_multi_strerror(rc)); - } - - php_http_curlm_responsehandler(context); - } -} - -static void php_http_curlm_event_callback(int socket, short action, void *event_data) +void php_http_client_curl_loop(php_http_client_t *client, curl_socket_t s, int curl_action) { - php_http_client_t *context = event_data; - php_http_client_curl_t *curl = context->ctx; - -#if DBG_EVENTS - fprintf(stderr, "E"); -#endif - if (curl->useevents) { - CURLMcode rc = CURLM_OK; - - while (CURLM_CALL_MULTI_PERFORM == (rc = curl_multi_socket_action(curl->handle->multi, socket, etoca(action), &curl->unfinished))); - - if (CURLM_OK != rc) { - php_error_docref(NULL, E_WARNING, "%s", curl_multi_strerror(rc)); - } - - php_http_curlm_responsehandler(context); - - /* remove timeout if there are no transfers left */ - if (!curl->unfinished && event_initialized(curl->timeout) && event_pending(curl->timeout, EV_TIMEOUT, NULL)) { - event_del(curl->timeout); - } - } -} - -static int php_http_curlm_socket_callback(CURL *easy, curl_socket_t sock, int action, void *socket_data, void *assign_data) -{ - php_http_client_t *context = socket_data; - php_http_client_curl_t *curl = context->ctx; + CURLMcode rc; + php_http_client_curl_t *curl = client->ctx; #if DBG_EVENTS - fprintf(stderr, "S"); + fprintf(stderr, "H"); #endif - if (curl->useevents) { - int events = EV_PERSIST; - php_http_curlm_event_t *ev = assign_data; - if (!ev) { - ev = ecalloc(1, sizeof(php_http_curlm_event_t)); - ev->context = context; - curl_multi_assign(curl->handle->multi, sock, ev); - } else { - event_del(&ev->evnt); - } - - switch (action) { - case CURL_POLL_IN: - events |= EV_READ; - break; - case CURL_POLL_OUT: - events |= EV_WRITE; - break; - case CURL_POLL_INOUT: - events |= EV_READ|EV_WRITE; - break; - - case CURL_POLL_REMOVE: - efree(ev); - /* no break */ - case CURL_POLL_NONE: - return 0; - - default: - php_error_docref(NULL, E_WARNING, "Unknown socket action %d", action); - return -1; - } + do { + rc = curl_multi_socket_action(curl->handle->multi, s, curl_action, &curl->unfinished); + } while (CURLM_CALL_MULTI_PERFORM == rc); - event_assign(&ev->evnt, curl->evbase, sock, events, php_http_curlm_event_callback, context); - event_add(&ev->evnt, NULL); + if (CURLM_OK != rc) { + php_error_docref(NULL, E_WARNING, "%s", curl_multi_strerror(rc)); } - return 0; -} - -static void php_http_curlm_timer_callback(CURLM *multi, long timeout_ms, void *timer_data) -{ - php_http_client_t *context = timer_data; - php_http_client_curl_t *curl = context->ctx; - -#if DBG_EVENTS - fprintf(stderr, "\ntimer <- timeout_ms: %ld\n", timeout_ms); -#endif - if (curl->useevents) { - - if (timeout_ms < 0) { - php_http_curlm_timeout_callback(CURL_SOCKET_TIMEOUT, /*EV_READ|EV_WRITE*/0, context); - } else if (timeout_ms > 0 || !event_initialized(curl->timeout) || !event_pending(curl->timeout, EV_TIMEOUT, NULL)) { - struct timeval timeout; - - if (!event_initialized(curl->timeout)) { - event_assign(curl->timeout, curl->evbase, CURL_SOCKET_TIMEOUT, 0, php_http_curlm_timeout_callback, context); - } - - timeout.tv_sec = timeout_ms / 1000; - timeout.tv_usec = (timeout_ms % 1000) * 1000; - - event_add(curl->timeout, &timeout); - } - } + php_http_client_curl_responsehandler(client); } -#endif /* HAVE_EVENT */ - /* curl options */ static php_http_options_t php_http_curle_options, php_http_curlm_options; @@ -894,7 +818,7 @@ static ZEND_RESULT_CODE php_http_curle_option_set_ssl_verifyhost(php_http_option php_http_client_curl_handler_t *curl = userdata; CURL *ch = curl->handle; - if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, Z_TYPE_P(val) == IS_TRUE ? 2 : 0)) { + if (CURLE_OK != curl_easy_setopt(ch, opt->option, Z_TYPE_P(val) == IS_TRUE ? 2 : 0)) { return FAILURE; } return SUCCESS; @@ -1025,6 +949,21 @@ static ZEND_RESULT_CODE php_http_curle_option_set_lastmodified(php_http_option_t return SUCCESS; } +#if PHP_HTTP_CURL_VERSION(7,64,1) +static ZEND_RESULT_CODE php_http_curle_option_set_altsvc_ctrl(php_http_option_t *opt, zval *val, void *userdata) +{ + php_http_client_curl_handler_t *curl = userdata; + CURL *ch = curl->handle; + + if (Z_LVAL_P(val)) { + if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_ALTSVC_CTRL, Z_LVAL_P(val))) { + return FAILURE; + } + } + return SUCCESS; +} +#endif + static ZEND_RESULT_CODE php_http_curle_option_set_compress(php_http_option_t *opt, zval *val, void *userdata) { php_http_client_curl_handler_t *curl = userdata; @@ -1064,20 +1003,23 @@ static ZEND_RESULT_CODE php_http_curle_option_set_range(php_http_option_t *opt, if (val && Z_TYPE_P(val) != IS_NULL) { zval *rr, *rb, *re; - zend_long rbl, rel; HashTable *ht = HASH_OF(val); ZEND_HASH_FOREACH_VAL(ht, rr) { if (Z_TYPE_P(rr) == IS_ARRAY) { if (2 == php_http_array_list(Z_ARRVAL_P(rr), 2, &rb, &re)) { - if ( ((Z_TYPE_P(rb) == IS_LONG) || ((Z_TYPE_P(rb) == IS_STRING) && is_numeric_string(Z_STRVAL_P(rb), Z_STRLEN_P(rb), &rbl, NULL, 1))) && - ((Z_TYPE_P(re) == IS_LONG) || ((Z_TYPE_P(re) == IS_STRING) && is_numeric_string(Z_STRVAL_P(re), Z_STRLEN_P(re), &rel, NULL, 1)))) { - if ((rbl >= 0) && (rel >= 0)) { + zend_long rbl = zval_get_long(rb), rel = zval_get_long(re); + + if (rbl >= 0) { + if (rel > 0) { php_http_buffer_appendf(&curl->options.ranges, "%ld-%ld,", rbl, rel); + } else { + php_http_buffer_appendf(&curl->options.ranges, "%ld-", rbl); } + } else if (rel > 0) { + php_http_buffer_appendf(&curl->options.ranges, "-%ld", rel); } - } } } @@ -1236,7 +1178,7 @@ static ZEND_RESULT_CODE php_http_curle_option_set_resolve(php_http_option_t *opt } #endif -#if PHP_HTTP_CURL_VERSION(7,21,4) && defined(PHP_HTTP_CURL_TLSAUTH_SRP) +#if PHP_HTTP_CURL_VERSION(7,21,4) && PHP_HTTP_HAVE_LIBCURL_TLSAUTH_TYPE static ZEND_RESULT_CODE php_http_curle_option_set_ssl_tlsauthtype(php_http_option_t *opt, zval *val, void *userdata) { php_http_client_curl_handler_t *curl = userdata; @@ -1245,7 +1187,7 @@ static ZEND_RESULT_CODE php_http_curle_option_set_ssl_tlsauthtype(php_http_optio if (val && Z_LVAL_P(val)) { switch (Z_LVAL_P(val)) { case CURL_TLSAUTH_SRP: - if (CURLE_OK == curl_easy_setopt(ch, CURLOPT_TLSAUTH_TYPE, PHP_HTTP_CURL_TLSAUTH_SRP)) { + if (CURLE_OK == curl_easy_setopt(ch, opt->option, PHP_HTTP_LIBCURL_TLSAUTH_SRP)) { return SUCCESS; } /* no break */ @@ -1253,7 +1195,7 @@ static ZEND_RESULT_CODE php_http_curle_option_set_ssl_tlsauthtype(php_http_optio return FAILURE; } } - if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_TLSAUTH_TYPE, PHP_HTTP_CURL_TLSAUTH_DEF)) { + if (CURLE_OK != curl_easy_setopt(ch, opt->option, PHP_HTTP_LIBCURL_TLSAUTH_DEF)) { return FAILURE; } return SUCCESS; @@ -1283,6 +1225,9 @@ static void php_http_curle_options_init(php_http_options_t *registry) #if PHP_HTTP_CURL_VERSION(7,19,4) php_http_option_register(registry, ZEND_STRL("noproxy"), CURLOPT_NOPROXY, IS_STRING); #endif +#if PHP_HTTP_CURL_VERSION(7,55,0) + php_http_option_register(registry, ZEND_STRL("socks5_auth"), CURLOPT_SOCKS5_AUTH, IS_LONG); +#endif #if PHP_HTTP_CURL_VERSION(7,37,0) if ((opt = php_http_option_register(registry, ZEND_STRL("proxyheader"), CURLOPT_PROXYHEADER, IS_ARRAY))) { @@ -1296,13 +1241,22 @@ static void php_http_curle_options_init(php_http_options_t *registry) opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; } #endif +#if PHP_HTTP_CURL_VERSION(7,60,0) + php_http_option_register(registry, ZEND_STRL("haproxy_protocol"), CURLOPT_HAPROXYPROTOCOL, _IS_BOOL); +#endif + /* unix sockets */ #if PHP_HTTP_CURL_VERSION(7,40,0) if (PHP_HTTP_CURL_FEATURE(CURL_VERSION_UNIX_SOCKETS)) { if ((opt = php_http_option_register(registry, ZEND_STRL("unix_socket_path"), CURLOPT_UNIX_SOCKET_PATH, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } +#if PHP_HTTP_CURL_VERSION(7,53,0) + if ((opt = php_http_option_register(registry, ZEND_STRL("abstract_unix_socket"), CURLOPT_ABSTRACT_UNIX_SOCKET, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } +#endif } #endif @@ -1316,7 +1270,7 @@ static void php_http_curle_options_init(php_http_options_t *registry) opt->setter = php_http_curle_option_set_resolve; } #endif -#if PHP_HTTP_HAVE_ARES +#if PHP_HTTP_HAVE_LIBCURL_ARES # if PHP_HTTP_CURL_VERSION(7,24,0) if ((opt = php_http_option_register(registry, ZEND_STRL("dns_servers"), CURLOPT_DNS_SERVERS, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; @@ -1334,6 +1288,13 @@ static void php_http_curle_options_init(php_http_options_t *registry) } # endif #endif +#if PHP_HTTP_CURL_VERSION(7,60,0) + php_http_option_register(registry, ZEND_STRL("dns_shuffle_addresses"), CURLOPT_DNS_SHUFFLE_ADDRESSES, _IS_BOOL); +#endif +#if PHP_HTTP_CURL_VERSION(7,62,0) + php_http_option_register(registry, ZEND_STRL("doh_url"), CURLOPT_DOH_URL, IS_STRING); +#endif + /* limits */ php_http_option_register(registry, ZEND_STRL("low_speed_limit"), CURLOPT_LOW_SPEED_LIMIT, IS_LONG); @@ -1352,6 +1313,11 @@ static void php_http_curle_options_init(php_http_options_t *registry) */ php_http_option_register(registry, ZEND_STRL("fresh_connect"), CURLOPT_FRESH_CONNECT, _IS_BOOL); php_http_option_register(registry, ZEND_STRL("forbid_reuse"), CURLOPT_FORBID_REUSE, _IS_BOOL); +#if PHP_HTTP_CURL_VERSION(7,65,0) + if ((opt = php_http_option_register(registry, ZEND_STRL("maxage_conn"), CURLOPT_MAXAGE_CONN, IS_LONG))) { + ZVAL_LONG(&opt->defval, 118); + } +#endif /* outgoing interface */ php_http_option_register(registry, ZEND_STRL("interface"), CURLOPT_INTERFACE, IS_STRING); @@ -1380,6 +1346,11 @@ static void php_http_curle_options_init(php_http_options_t *registry) opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; } #endif +#if PHP_HTTP_CURL_VERSION(7,61,0) + if ((opt = php_http_option_register(registry, ZEND_STRL("xoauth2_bearer"), CURLOPT_XOAUTH2_BEARER, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } +#endif /* redirects */ if ((opt = php_http_option_register(registry, ZEND_STRL("redirect"), CURLOPT_FOLLOWLOCATION, IS_LONG))) { @@ -1465,6 +1436,9 @@ static void php_http_curle_options_init(php_http_options_t *registry) /* http protocol version */ php_http_option_register(registry, ZEND_STRL("protocol"), CURLOPT_HTTP_VERSION, IS_LONG); +#if PHP_HTTP_CURL_VERSION(7,64,0) + php_http_option_register(registry, ZEND_STRL("http09_allowed"), CURLOPT_HTTP09_ALLOWED, _IS_BOOL); +#endif /* timeouts */ if ((opt = php_http_option_register(registry, ZEND_STRL("timeout"), CURLOPT_TIMEOUT_MS, IS_DOUBLE))) { @@ -1492,114 +1466,221 @@ static void php_http_curle_options_init(php_http_options_t *registry) Z_LVAL(opt->defval) = 60; } #endif +#if PHP_HTTP_CURL_VERSION(7,49,0) + php_http_option_register(registry, ZEND_STRL("tcp_fastopen"), CURLOPT_TCP_FASTOPEN, _IS_BOOL); +#endif /* ssl */ if (PHP_HTTP_CURL_FEATURE(CURL_VERSION_SSL)) { - if ((opt = php_http_option_register(registry, ZEND_STRL("ssl"), 0, IS_ARRAY))) { - registry = &opt->suboptions; + php_http_option_t *ssl_opt, *proxy_opt; + + if ((ssl_opt = php_http_option_register(registry, ZEND_STRL("ssl"), 0, IS_ARRAY))) { + php_http_options_t *ssl_registry = &ssl_opt->suboptions; - if ((opt = php_http_option_register(registry, ZEND_STRL("cert"), CURLOPT_SSLCERT, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("cert"), CURLOPT_SSLCERT, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } - if ((opt = php_http_option_register(registry, ZEND_STRL("certtype"), CURLOPT_SSLCERTTYPE, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("certtype"), CURLOPT_SSLCERTTYPE, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; ZVAL_PSTRING(&opt->defval, "PEM"); } - if ((opt = php_http_option_register(registry, ZEND_STRL("key"), CURLOPT_SSLKEY, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("key"), CURLOPT_SSLKEY, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } - if ((opt = php_http_option_register(registry, ZEND_STRL("keytype"), CURLOPT_SSLKEYTYPE, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("keytype"), CURLOPT_SSLKEYTYPE, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; ZVAL_PSTRING(&opt->defval, "PEM"); } - if ((opt = php_http_option_register(registry, ZEND_STRL("keypasswd"), CURLOPT_SSLKEYPASSWD, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("keypasswd"), CURLOPT_SSLKEYPASSWD, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; } - php_http_option_register(registry, ZEND_STRL("engine"), CURLOPT_SSLENGINE, IS_STRING); - php_http_option_register(registry, ZEND_STRL("version"), CURLOPT_SSLVERSION, IS_LONG); - if ((opt = php_http_option_register(registry, ZEND_STRL("verifypeer"), CURLOPT_SSL_VERIFYPEER, _IS_BOOL))) { + php_http_option_register(ssl_registry, ZEND_STRL("engine"), CURLOPT_SSLENGINE, IS_STRING); + php_http_option_register(ssl_registry, ZEND_STRL("version"), CURLOPT_SSLVERSION, IS_LONG); + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("verifypeer"), CURLOPT_SSL_VERIFYPEER, _IS_BOOL))) { ZVAL_BOOL(&opt->defval, 1); } - if ((opt = php_http_option_register(registry, ZEND_STRL("verifyhost"), CURLOPT_SSL_VERIFYHOST, _IS_BOOL))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("verifyhost"), CURLOPT_SSL_VERIFYHOST, _IS_BOOL))) { ZVAL_BOOL(&opt->defval, 1); opt->setter = php_http_curle_option_set_ssl_verifyhost; } -#if PHP_HTTP_CURL_VERSION(7,41,0) && (defined(PHP_HTTP_HAVE_OPENSSL) || defined(PHP_HTTP_HAVE_NSS) || defined(PHP_HTTP_HAVE_GNUTLS)) - php_http_option_register(registry, ZEND_STRL("verifystatus"), CURLOPT_SSL_VERIFYSTATUS, _IS_BOOL); +#if PHP_HTTP_CURL_VERSION(7,41,0) && (PHP_HTTP_HAVE_LIBCURL_OPENSSL || PHP_HTTP_HAVE_LIBCURL_NSS || PHP_HTTP_HAVE_LIBCURL_GNUTLS) + php_http_option_register(ssl_registry, ZEND_STRL("verifystatus"), CURLOPT_SSL_VERIFYSTATUS, _IS_BOOL); #endif - php_http_option_register(registry, ZEND_STRL("cipher_list"), CURLOPT_SSL_CIPHER_LIST, IS_STRING); - if ((opt = php_http_option_register(registry, ZEND_STRL("cainfo"), CURLOPT_CAINFO, IS_STRING))) { + php_http_option_register(ssl_registry, ZEND_STRL("cipher_list"), CURLOPT_SSL_CIPHER_LIST, IS_STRING); +#if PHP_HTTP_HAVE_LIBCURL_CAINFO + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("cainfo"), CURLOPT_CAINFO, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; -#ifdef PHP_HTTP_CURL_CAINFO - ZVAL_PSTRING(&opt->defval, PHP_HTTP_CURL_CAINFO); -#endif +# ifdef PHP_HTTP_CAINFO + ZVAL_PSTRING(&opt->defval, PHP_HTTP_CAINFO); +# endif } - if ((opt = php_http_option_register(registry, ZEND_STRL("capath"), CURLOPT_CAPATH, IS_STRING))) { +#endif +#if PHP_HTTP_HAVE_LIBCURL_CAPATH + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("capath"), CURLOPT_CAPATH, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; -#ifdef PHP_HTTP_CURL_CAPATH - ZVAL_PSTRING(&opt->defval, PHP_HTTP_CURL_CAPATH); +# ifdef PHP_HTTP_CAPATH + ZVAL_PSTRING(&opt->defval, PHP_HTTP_CAPATH); +# endif + } #endif - } - if ((opt = php_http_option_register(registry, ZEND_STRL("random_file"), CURLOPT_RANDOM_FILE, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("random_file"), CURLOPT_RANDOM_FILE, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } - if ((opt = php_http_option_register(registry, ZEND_STRL("egdsocket"), CURLOPT_EGDSOCKET, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("egdsocket"), CURLOPT_EGDSOCKET, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } #if PHP_HTTP_CURL_VERSION(7,19,0) - if ((opt = php_http_option_register(registry, ZEND_STRL("issuercert"), CURLOPT_ISSUERCERT, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("issuercert"), CURLOPT_ISSUERCERT, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } -# ifdef PHP_HTTP_HAVE_OPENSSL - if ((opt = php_http_option_register(registry, ZEND_STRL("crlfile"), CURLOPT_CRLFILE, IS_STRING))) { +# if PHP_HTTP_HAVE_LIBCURL_OPENSSL + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("crlfile"), CURLOPT_CRLFILE, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } # endif #endif -#if (PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)) || (PHP_HTTP_CURL_VERSION(7,34,0) && defined(PHP_HTTP_HAVE_NSS)) || (PHP_HTTP_CURL_VERSION(7,42,0) && defined(PHP_HTTP_HAVE_GNUTLS)) || (PHP_HTTP_CURL_VERSION(7,39,0) && defined(PHP_HTTP_HAVE_GSKIT)) - if ((opt = php_http_option_register(registry, ZEND_STRL("certinfo"), CURLOPT_CERTINFO, _IS_BOOL))) { +#if (PHP_HTTP_CURL_VERSION(7,19,1) && PHP_HTTP_HAVE_LIBCURL_OPENSSL) || (PHP_HTTP_CURL_VERSION(7,34,0) && PHP_HTTP_HAVE_LIBCURL_NSS) || (PHP_HTTP_CURL_VERSION(7,42,0) && defined(PHP_HTTP_HAVE_LIBCURL_GNUTLS)) || (PHP_HTTP_CURL_VERSION(7,39,0) && defined(PHP_HTTP_HAVE_LIBCURL_GSKIT)) + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("certinfo"), CURLOPT_CERTINFO, _IS_BOOL))) { ZVAL_FALSE(&opt->defval); } #endif #if PHP_HTTP_CURL_VERSION(7,36,0) - if ((opt = php_http_option_register(registry, ZEND_STRL("enable_npn"), CURLOPT_SSL_ENABLE_NPN, _IS_BOOL))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("enable_npn"), CURLOPT_SSL_ENABLE_NPN, _IS_BOOL))) { ZVAL_BOOL(&opt->defval, 1); } - if ((opt = php_http_option_register(registry, ZEND_STRL("enable_alpn"), CURLOPT_SSL_ENABLE_ALPN, _IS_BOOL))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("enable_alpn"), CURLOPT_SSL_ENABLE_ALPN, _IS_BOOL))) { ZVAL_BOOL(&opt->defval, 1); } #endif #if PHP_HTTP_CURL_VERSION(7,39,0) /* FIXME: see http://curl.haxx.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html#AVAILABILITY */ - if ((opt = php_http_option_register(registry, ZEND_STRL("pinned_publickey"), CURLOPT_PINNEDPUBLICKEY, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("pinned_publickey"), CURLOPT_PINNEDPUBLICKEY, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } #endif -#if PHP_HTTP_CURL_VERSION(7,21,4) && defined(PHP_HTTP_CURL_TLSAUTH_SRP) - if ((opt = php_http_option_register(registry, ZEND_STRL("tlsauthtype"), CURLOPT_TLSAUTH_TYPE, IS_LONG))) { +#if PHP_HTTP_CURL_VERSION(7,21,4) && PHP_HTTP_HAVE_LIBCURL_TLSAUTH_TYPE + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("tlsauthtype"), CURLOPT_TLSAUTH_TYPE, IS_LONG))) { opt->setter = php_http_curle_option_set_ssl_tlsauthtype; } - if ((opt = php_http_option_register(registry, ZEND_STRL("tlsauthuser"), CURLOPT_TLSAUTH_USERNAME, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("tlsauthuser"), CURLOPT_TLSAUTH_USERNAME, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; } - if ((opt = php_http_option_register(registry, ZEND_STRL("tlsauthpass"), CURLOPT_TLSAUTH_PASSWORD, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("tlsauthpass"), CURLOPT_TLSAUTH_PASSWORD, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; } #endif -#if PHP_HTTP_CURL_VERSION(7,42,0) && (defined(PHP_HTTP_HAVE_NSS) || defined(PHP_HTTP_HAVE_DARWINSSL)) - php_http_option_register(registry, ZEND_STRL("falsestart"), CURLOPT_SSL_FALSESTART, _IS_BOOL); +#if PHP_HTTP_CURL_VERSION(7,42,0) && (PHP_HTTP_HAVE_LIBCURL_NSS || PHP_HTTP_HAVE_LIBCURL_SECURETRANSPORT) + php_http_option_register(ssl_registry, ZEND_STRL("falsestart"), CURLOPT_SSL_FALSESTART, _IS_BOOL); +#endif +#if PHP_HTTP_CURL_VERSION(7,61,0) + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("tls13_ciphers"), CURLOPT_TLS13_CIPHERS, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } #endif } + +#if PHP_HTTP_CURL_VERSION(7,52,0) + /* proxy_ssl */ + if ((proxy_opt = php_http_option_register(registry, ZEND_STRL("proxy_ssl"), 0, IS_ARRAY))) { + php_http_options_t *proxy_registry = &proxy_opt->suboptions; + + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("cert"), CURLOPT_PROXY_SSLCERT, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("certtype"), CURLOPT_PROXY_SSLCERTTYPE, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + ZVAL_PSTRING(&opt->defval, "PEM"); + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("key"), CURLOPT_PROXY_SSLKEY, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("keytype"), CURLOPT_PROXY_SSLKEYTYPE, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + ZVAL_PSTRING(&opt->defval, "PEM"); + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("keypasswd"), CURLOPT_PROXY_KEYPASSWD, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } + php_http_option_register(proxy_registry, ZEND_STRL("version"), CURLOPT_PROXY_SSLVERSION, IS_LONG); + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("verifypeer"), CURLOPT_PROXY_SSL_VERIFYPEER, _IS_BOOL))) { + ZVAL_BOOL(&opt->defval, 1); + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("verifyhost"), CURLOPT_PROXY_SSL_VERIFYHOST, _IS_BOOL))) { + ZVAL_BOOL(&opt->defval, 1); + opt->setter = php_http_curle_option_set_ssl_verifyhost; + } + php_http_option_register(proxy_registry, ZEND_STRL("cipher_list"), CURLOPT_PROXY_SSL_CIPHER_LIST, IS_STRING); +# if PHP_HTTP_HAVE_LIBCURL_OPENSSL + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("crlfile"), CURLOPT_PROXY_CRLFILE, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; + } +# endif +# if PHP_HTTP_HAVE_LIBCURL_CAINFO + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("cainfo"), CURLOPT_PROXY_CAINFO, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; +# ifdef PHP_HTTP_CAINFO + ZVAL_PSTRING(&opt->defval, PHP_HTTP_CAINFO); +# endif + } +# endif +# if PHP_HTTP_HAVE_LIBCURL_CAPATH + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("capath"), CURLOPT_PROXY_CAPATH, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; +# ifdef PHP_HTTP_CAPATH + ZVAL_PSTRING(&opt->defval, PHP_HTTP_CAPATH); +# endif + } +# endif + +# if PHP_HTTP_HAVE_LIBCURL_TLSAUTH_TYPE + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("tlsauthtype"), CURLOPT_PROXY_TLSAUTH_TYPE, IS_LONG))) { + opt->setter = php_http_curle_option_set_ssl_tlsauthtype; + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("tlsauthuser"), CURLOPT_PROXY_TLSAUTH_USERNAME, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("tlsauthpass"), CURLOPT_PROXY_TLSAUTH_PASSWORD, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } +# endif +# if PHP_HTTP_CURL_VERSION(7,59,0) + /* FIXME: see http://curl.haxx.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html#AVAILABILITY */ + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("pinned_publickey"), CURLOPT_PROXY_PINNEDPUBLICKEY, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; + } +# endif +# if PHP_HTTP_CURL_VERSION(7,61,0) + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("tls13_ciphers"), CURLOPT_PROXY_TLS13_CIPHERS, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } +# endif + } +#endif + } + +#if PHP_HTTP_CURL_VERSION(7,64,1) + if ((opt = php_http_option_register(registry, ZEND_STRL("altsvc_ctrl"), CURLOPT_ALTSVC_CTRL, IS_LONG))) { + opt->setter = php_http_curle_option_set_altsvc_ctrl; + } + if ((opt = php_http_option_register(registry, ZEND_STRL("altsvc"), CURLOPT_ALTSVC, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } +#endif } static zval *php_http_curle_get_option(php_http_option_t *opt, HashTable *options, void *userdata) @@ -1702,7 +1783,7 @@ static ZEND_RESULT_CODE php_http_curle_set_option(php_http_option_t *opt, zval * return rv; } -#if PHP_HTTP_CURL_VERSION(7,30,0) +#if PHP_HTTP_CURL_VERSION(7,30,0) && !PHP_HTTP_CURL_VERSION(7,62,0) static ZEND_RESULT_CODE php_http_curlm_option_set_pipelining_bl(php_http_option_t *opt, zval *value, void *userdata) { php_http_client_t *client = userdata; @@ -1746,27 +1827,24 @@ static ZEND_RESULT_CODE php_http_curlm_option_set_pipelining_bl(php_http_option_ } #endif -#if PHP_HTTP_HAVE_EVENT -static inline ZEND_RESULT_CODE php_http_curlm_use_eventloop(php_http_client_t *h, zend_bool enable) +static inline ZEND_RESULT_CODE php_http_curlm_use_eventloop(php_http_client_t *h, php_http_client_curl_ops_t *ev_ops, zval *init_data) { php_http_client_curl_t *curl = h->ctx; + void *ev_ctx; - if ((curl->useevents = enable)) { - if (!curl->evbase) { - curl->evbase = event_base_new(); - } - if (!curl->timeout) { - curl->timeout = ecalloc(1, sizeof(struct event)); + if (ev_ops) { + if (!(ev_ctx = ev_ops->init(h, init_data))) { + return FAILURE; } - curl_multi_setopt(curl->handle->multi, CURLMOPT_SOCKETDATA, h); - curl_multi_setopt(curl->handle->multi, CURLMOPT_SOCKETFUNCTION, php_http_curlm_socket_callback); - curl_multi_setopt(curl->handle->multi, CURLMOPT_TIMERDATA, h); - curl_multi_setopt(curl->handle->multi, CURLMOPT_TIMERFUNCTION, php_http_curlm_timer_callback); + curl->ev_ctx = ev_ctx; + curl->ev_ops = ev_ops; } else { - curl_multi_setopt(curl->handle->multi, CURLMOPT_SOCKETDATA, NULL); - curl_multi_setopt(curl->handle->multi, CURLMOPT_SOCKETFUNCTION, NULL); - curl_multi_setopt(curl->handle->multi, CURLMOPT_TIMERDATA, NULL); - curl_multi_setopt(curl->handle->multi, CURLMOPT_TIMERFUNCTION, NULL); + if (curl->ev_ops) { + if (curl->ev_ctx) { + curl->ev_ops->dtor(&curl->ev_ctx); + } + curl->ev_ops = NULL; + } } return SUCCESS; @@ -1775,10 +1853,18 @@ static inline ZEND_RESULT_CODE php_http_curlm_use_eventloop(php_http_client_t *h static ZEND_RESULT_CODE php_http_curlm_option_set_use_eventloop(php_http_option_t *opt, zval *value, void *userdata) { php_http_client_t *client = userdata; + php_http_client_curl_ops_t *ev_ops = NULL; - return php_http_curlm_use_eventloop(client, value && Z_TYPE_P(value) == IS_TRUE); -} + if (value && Z_TYPE_P(value) == IS_OBJECT && instanceof_function(Z_OBJCE_P(value), php_http_client_curl_user_get_class_entry())) { + ev_ops = php_http_client_curl_user_ops_get(); +#if PHP_HTTP_HAVE_LIBEVENT + } else if (value && zend_is_true(value)) { + ev_ops = php_http_client_curl_event_ops_get(); #endif + } + + return php_http_curlm_use_eventloop(client, ev_ops, value); +} static ZEND_RESULT_CODE php_http_curlm_option_set_share_cookies(php_http_option_t *opt, zval *value, void *userdata) { @@ -1832,45 +1918,43 @@ static void php_http_curlm_options_init(php_http_options_t *registry) /* set max number of connections to a single host */ #if PHP_HTTP_CURL_VERSION(7,30,0) php_http_option_register(registry, ZEND_STRL("max_host_connections"), CURLMOPT_MAX_HOST_CONNECTIONS, IS_LONG); -#endif - /* maximum number of requests in a pipeline */ -#if PHP_HTTP_CURL_VERSION(7,30,0) - if ((opt = php_http_option_register(registry, ZEND_STRL("max_pipeline_length"), CURLMOPT_MAX_PIPELINE_LENGTH, IS_LONG))) { - ZVAL_LONG(&opt->defval, 5); - } #endif /* max simultaneously open connections */ #if PHP_HTTP_CURL_VERSION(7,30,0) php_http_option_register(registry, ZEND_STRL("max_total_connections"), CURLMOPT_MAX_TOTAL_CONNECTIONS, IS_LONG); #endif +#if PHP_HTTP_CURL_VERSION(7,67,0) + if ((opt = php_http_option_register(registry, ZEND_STRL("max_concurrent_streams"), CURLMOPT_MAX_CONCURRENT_STREAMS, IS_LONG))) { + ZVAL_LONG(&opt->defval, 100); + } +#endif + +#if !PHP_HTTP_CURL_VERSION(7,62,0) /* enable/disable HTTP pipelining */ php_http_option_register(registry, ZEND_STRL("pipelining"), CURLMOPT_PIPELINING, _IS_BOOL); +# if PHP_HTTP_CURL_VERSION(7,30,0) + /* maximum number of requests in a pipeline */ + if ((opt = php_http_option_register(registry, ZEND_STRL("max_pipeline_length"), CURLMOPT_MAX_PIPELINE_LENGTH, IS_LONG))) { + ZVAL_LONG(&opt->defval, 5); + } /* chunk length threshold for pipelining */ -#if PHP_HTTP_CURL_VERSION(7,30,0) php_http_option_register(registry, ZEND_STRL("chunk_length_penalty_size"), CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, IS_LONG); -#endif /* size threshold for pipelining penalty */ -#if PHP_HTTP_CURL_VERSION(7,30,0) php_http_option_register(registry, ZEND_STRL("content_length_penalty_size"), CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, IS_LONG); -#endif /* pipelining server blacklist */ -#if PHP_HTTP_CURL_VERSION(7,30,0) if ((opt = php_http_option_register(registry, ZEND_STRL("pipelining_server_bl"), CURLMOPT_PIPELINING_SERVER_BL, IS_ARRAY))) { opt->setter = php_http_curlm_option_set_pipelining_bl; } -#endif /* pipelining host blacklist */ -#if PHP_HTTP_CURL_VERSION(7,30,0) if ((opt = php_http_option_register(registry, ZEND_STRL("pipelining_site_bl"), CURLMOPT_PIPELINING_SITE_BL, IS_ARRAY))) { opt->setter = php_http_curlm_option_set_pipelining_bl; } +# endif #endif /* events */ -#if PHP_HTTP_HAVE_EVENT - if ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, _IS_BOOL))) { + if ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, 0))) { opt->setter = php_http_curlm_option_set_use_eventloop; } -#endif /* share */ if ((opt = php_http_option_register(registry, ZEND_STRL("share_cookies"), 0, _IS_BOOL))) { opt->setter = php_http_curlm_option_set_share_cookies; @@ -1889,15 +1973,13 @@ static ZEND_RESULT_CODE php_http_curlm_set_option(php_http_option_t *opt, zval * php_http_client_t *client = userdata; php_http_client_curl_t *curl = client->ctx; CURLM *ch = curl->handle->multi; - zval *orig = val; + zval zopt, *orig = val; CURLMcode rc = CURLM_UNKNOWN_OPTION; ZEND_RESULT_CODE rv = SUCCESS; if (!val) { val = &opt->defval; } else if (opt->type && Z_TYPE_P(val) != opt->type && !(Z_TYPE_P(val) == IS_NULL && opt->type == IS_ARRAY)) { - zval zopt; - ZVAL_DUP(&zopt, val); convert_to_explicit_type(&zopt, opt->type); @@ -2013,7 +2095,7 @@ static php_http_client_curl_handler_t *php_http_client_curl_handler_init(php_htt php_http_buffer_init(&handler->options.ranges); zend_hash_init(&handler->options.cache, 0, NULL, ZVAL_PTR_DTOR, 0); -#if defined(ZTS) +#if ZTS curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L); #endif curl_easy_setopt(handle, CURLOPT_HEADER, 0L); @@ -2163,6 +2245,10 @@ static void php_http_client_curl_handler_clear(php_http_client_curl_handler_t *h curl_easy_setopt(handler->handle, CURLOPT_DEBUGFUNCTION, NULL); curl_easy_setopt(handler->handle, CURLOPT_COOKIELIST, "FLUSH"); curl_easy_setopt(handler->handle, CURLOPT_SHARE, NULL); + /* see gh issue #84 */ +#if PHP_HTTP_CURL_VERSION(7,63,0) && !PHP_HTTP_CURL_VERSION(7,65,0) + curl_easy_setopt(handler->handle, CURLOPT_COOKIEJAR, NULL); +#endif } static void php_http_client_curl_handler_dtor(php_http_client_curl_handler_t *handler) @@ -2219,19 +2305,10 @@ static void php_http_client_curl_dtor(php_http_client_t *h) { php_http_client_curl_t *curl = h->ctx; -#if PHP_HTTP_HAVE_EVENT - if (curl->timeout) { - if (event_initialized(curl->timeout) && event_pending(curl->timeout, EV_TIMEOUT, NULL)) { - event_del(curl->timeout); - } - efree(curl->timeout); - curl->timeout = NULL; - } - if (curl->evbase) { - event_base_free(curl->evbase); - curl->evbase = NULL; + if (curl->ev_ops) { + curl->ev_ops->dtor(&curl->ev_ctx); + curl->ev_ops = NULL; } -#endif curl->unfinished = 0; php_resource_factory_handle_dtor(h->rf, curl->handle); @@ -2345,6 +2422,11 @@ static ZEND_RESULT_CODE php_http_client_curl_dequeue(php_http_client_t *h, php_h php_http_client_curl_t *curl = h->ctx; php_http_client_curl_handler_t *handler = enqueue->opaque; + if (h->callback.depth && !CG(unclean_shutdown)) { + php_error_docref(NULL, E_WARNING, "Could not dequeue request while executing callbacks"); + return FAILURE; + } + php_http_client_curl_handler_clear(handler); if (CURLM_OK == (rs = curl_multi_remove_handle(curl->handle->multi, handler->handle))) { zend_llist_del_element(&h->requests, handler->handle, (int (*)(void *, void *)) compare_queue); @@ -2366,18 +2448,7 @@ static void php_http_client_curl_reset(php_http_client_t *h) } } -static inline void php_http_client_curl_get_timeout(php_http_client_curl_t *curl, long max_tout, struct timeval *timeout) -{ - if ((CURLM_OK == curl_multi_timeout(curl->handle->multi, &max_tout)) && (max_tout > 0)) { - timeout->tv_sec = max_tout / 1000; - timeout->tv_usec = (max_tout % 1000) * 1000; - } else { - timeout->tv_sec = 0; - timeout->tv_usec = 1000; - } -} - -#ifdef PHP_WIN32 +#if PHP_WIN32 # define SELECT_ERROR SOCKET_ERROR #else # define SELECT_ERROR -1 @@ -2390,22 +2461,9 @@ static ZEND_RESULT_CODE php_http_client_curl_wait(php_http_client_t *h, struct t struct timeval timeout; php_http_client_curl_t *curl = h->ctx; -#if PHP_HTTP_HAVE_EVENT - if (curl->useevents) { - if (!event_initialized(curl->timeout)) { - event_assign(curl->timeout, curl->evbase, CURL_SOCKET_TIMEOUT, 0, php_http_curlm_timeout_callback, h); - } else if (custom_timeout && timerisset(custom_timeout)) { - event_add(curl->timeout, custom_timeout); - } else if (!event_pending(curl->timeout, EV_TIMEOUT, NULL)) { - php_http_client_curl_get_timeout(curl, 1000, &timeout); - event_add(curl->timeout, &timeout); - } - - event_base_loop(curl->evbase, EVLOOP_ONCE); - - return SUCCESS; + if (curl->ev_ops) { + return curl->ev_ops->wait(curl->ev_ctx, custom_timeout); } -#endif FD_ZERO(&R); FD_ZERO(&W); @@ -2432,44 +2490,31 @@ static int php_http_client_curl_once(php_http_client_t *h) { php_http_client_curl_t *curl = h->ctx; -#if PHP_HTTP_HAVE_EVENT - if (curl->useevents) { - event_base_loop(curl->evbase, EVLOOP_NONBLOCK); - } else -#endif - while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl->handle->multi, &curl->unfinished)); + if (!h->callback.depth) { + if (curl->ev_ops) { + curl->ev_ops->once(curl->ev_ctx); + } else { + while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl->handle->multi, &curl->unfinished)); + } - php_http_curlm_responsehandler(h); + php_http_client_curl_responsehandler(h); + } return curl->unfinished; - } static ZEND_RESULT_CODE php_http_client_curl_exec(php_http_client_t *h) { -#if PHP_HTTP_HAVE_EVENT php_http_client_curl_t *curl = h->ctx; - if (curl->useevents) { - php_http_curlm_timeout_callback(CURL_SOCKET_TIMEOUT, /*EV_READ|EV_WRITE*/0, h); - do { - int ev_rc = event_base_dispatch(curl->evbase); - -#if DBG_EVENTS - fprintf(stderr, "%c", "X.0"[ev_rc+1]); -#endif + if (!h->callback.depth) { + if (curl->ev_ops) { + return curl->ev_ops->exec(curl->ev_ctx); + } - if (ev_rc < 0) { - php_error_docref(NULL, E_ERROR, "Error in event_base_dispatch()"); - return FAILURE; - } - } while (curl->unfinished && !EG(exception)); - } else -#endif - { while (php_http_client_curl_once(h) && !EG(exception)) { if (SUCCESS != php_http_client_curl_wait(h, NULL)) { -#ifdef PHP_WIN32 +#if PHP_WIN32 /* see http://msdn.microsoft.com/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp */ php_error_docref(NULL, E_WARNING, "WinSock error: %d", WSAGetLastError()); #else @@ -2491,16 +2536,18 @@ static ZEND_RESULT_CODE php_http_client_curl_setopt(php_http_client_t *h, php_ht case PHP_HTTP_CLIENT_OPT_CONFIGURATION: return php_http_options_apply(&php_http_curlm_options, (HashTable *) arg, h); break; - +#if !PHP_HTTP_CURL_VERSION(7,62,0) case PHP_HTTP_CLIENT_OPT_ENABLE_PIPELINING: if (CURLM_OK != curl_multi_setopt(curl->handle->multi, CURLMOPT_PIPELINING, (long) *((zend_bool *) arg))) { return FAILURE; } break; - +#endif case PHP_HTTP_CLIENT_OPT_USE_EVENTS: -#if PHP_HTTP_HAVE_EVENT - return php_http_curlm_use_eventloop(h, *(zend_bool *) arg); +#if PHP_HTTP_HAVE_LIBEVENT + return php_http_curlm_use_eventloop(h, (*(zend_bool *) arg) + ? php_http_client_curl_event_ops_get() + : NULL, NULL); break; #endif @@ -2598,6 +2645,15 @@ php_http_client_ops_t *php_http_client_curl_get_ops(void) return &php_http_client_curl_ops; } +#define REGISTER_NS_STRING_OR_NULL_CONSTANT(ns, name, str, flags) \ + do { \ + if ((str) != NULL) { \ + REGISTER_NS_STRING_CONSTANT(ns, name, str, flags); \ + } else { \ + REGISTER_NS_NULL_CONSTANT(ns, name, flags); \ + } \ + } while (0) + PHP_MINIT_FUNCTION(http_client_curl) { curl_version_info_data *info; @@ -2633,6 +2689,13 @@ PHP_MINIT_FUNCTION(http_client_curl) } if ((info = curl_version_info(CURLVERSION_NOW))) { + char tmp_ver[0x20], *tmp_ptr, *tmp_end; +#define tmp_ver_init() do {\ + tmp_ver[0] = 0; \ + tmp_ptr = &tmp_ver[0]; \ + tmp_end = &tmp_ver[sizeof(tmp_ver) - 1]; \ +} while (0) + /* * Feature constants */ @@ -2640,9 +2703,6 @@ PHP_MINIT_FUNCTION(http_client_curl) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "IPV6", CURL_VERSION_IPV6, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "KERBEROS4", CURL_VERSION_KERBEROS4, CONST_CS|CONST_PERSISTENT); -#if PHP_HTTP_CURL_VERSION(7,40,0) - REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "KERBEROS5", CURL_VERSION_KERBEROS5, CONST_CS|CONST_PERSISTENT); -#endif REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "SSL", CURL_VERSION_SSL, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "LIBZ", CURL_VERSION_LIBZ, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "NTLM", CURL_VERSION_NTLM, CONST_CS|CONST_PERSISTENT); @@ -2652,9 +2712,6 @@ PHP_MINIT_FUNCTION(http_client_curl) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "LARGEFILE", CURL_VERSION_LARGEFILE, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "IDN", CURL_VERSION_IDN, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "SSPI", CURL_VERSION_SSPI, CONST_CS|CONST_PERSISTENT); -#if PHP_HTTP_CURL_VERSION(7,38,0) - REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "GSSAPI", CURL_VERSION_GSSAPI, CONST_CS|CONST_PERSISTENT); -#endif #if PHP_HTTP_CURL_VERSION(7,21,4) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "TLSAUTH_SRP", CURL_VERSION_TLSAUTH_SRP, CONST_CS|CONST_PERSISTENT); #endif @@ -2664,28 +2721,73 @@ PHP_MINIT_FUNCTION(http_client_curl) #if PHP_HTTP_CURL_VERSION(7,33,0) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "HTTP2", CURL_VERSION_HTTP2, CONST_CS|CONST_PERSISTENT); #endif +#if PHP_HTTP_CURL_VERSION(7,38,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "GSSAPI", CURL_VERSION_GSSAPI, CONST_CS|CONST_PERSISTENT); +#endif #if PHP_HTTP_CURL_VERSION(7,40,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "KERBEROS5", CURL_VERSION_KERBEROS5, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "UNIX_SOCKETS", CURL_VERSION_UNIX_SOCKETS, CONST_CS|CONST_PERSISTENT); #endif #if PHP_HTTP_CURL_VERSION(7,47,0) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "PSL", CURL_VERSION_PSL, CONST_CS|CONST_PERSISTENT); #endif +#if PHP_HTTP_CURL_VERSION(7,52,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "HTTPS_PROXY", CURL_VERSION_HTTPS_PROXY, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,56,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "MULTI_SSL", CURL_VERSION_MULTI_SSL, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,57,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "BROTLI", CURL_VERSION_BROTLI, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,64,1) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "ALTSVC", CURL_VERSION_ALTSVC, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,66,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "HTTP3", CURL_VERSION_HTTP3, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,72,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "ZSTD", CURL_VERSION_ZSTD, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "UNICODE", CURL_VERSION_UNICODE, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,74,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "HSTS", CURL_VERSION_HSTS, CONST_CS|CONST_PERSISTENT); +#endif + /* * Version constants */ REGISTER_NS_STRING_CONSTANT("http\\Client\\Curl", "VERSIONS", curl_version(), CONST_CS|CONST_PERSISTENT); -#if CURLVERSION_NOW >= 0 - REGISTER_NS_STRING_CONSTANT("http\\Client\\Curl\\Versions", "CURL", (char *) info->version, CONST_CS|CONST_PERSISTENT); - REGISTER_NS_STRING_CONSTANT("http\\Client\\Curl\\Versions", "SSL", (char *) info->ssl_version, CONST_CS|CONST_PERSISTENT); - REGISTER_NS_STRING_CONSTANT("http\\Client\\Curl\\Versions", "LIBZ", (char *) info->libz_version, CONST_CS|CONST_PERSISTENT); -# if CURLVERSION_NOW >= 1 - REGISTER_NS_STRING_CONSTANT("http\\Client\\Curl\\Versions", "ARES", (char *) info->ares, CONST_CS|CONST_PERSISTENT); -# if CURLVERSION_NOW >= 2 - REGISTER_NS_STRING_CONSTANT("http\\Client\\Curl\\Versions", "IDN", (char *) info->libidn, CONST_CS|CONST_PERSISTENT); -# endif -# endif + REGISTER_NS_STRING_CONSTANT("http\\Client\\Curl\\Versions", "CURL", info->version, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "SSL", info->ssl_version, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "LIBZ", info->libz_version, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "ARES", info->ares, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "IDN", info->libidn, CONST_CS|CONST_PERSISTENT); + tmp_ver_init(); + tmp_ptr = zend_print_ulong_to_buf(tmp_end, info->iconv_ver_num & 0xf); + tmp_end = tmp_ptr - 1; + tmp_ptr = zend_print_ulong_to_buf(tmp_end, info->iconv_ver_num >> 8); + *tmp_end = '.'; + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "ICONV", tmp_ptr, CONST_CS|CONST_PERSISTENT); +#if PHP_HTTP_CURL_VERSION(7,57,0) + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "BROTLI", info->brotli_version, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,66,0) + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "NGHTTP2", info->nghttp2_version, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "QUIC", info->quic_version, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,70,0) + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "CAINFO", info->cainfo, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "CAPATH", info->capath, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,72,0) + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "ZSTD", info->zstd_version, CONST_CS|CONST_PERSISTENT); #endif +#if PHP_HTTP_CURL_VERSION(7,75,0) + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "HYPER", info->hyper_version, CONST_CS|CONST_PERSISTENT); +#endif + } /* @@ -2698,6 +2800,12 @@ PHP_MINIT_FUNCTION(http_client_curl) #endif #if PHP_HTTP_CURL_VERSION(7,47,0) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_2TLS", CURL_HTTP_VERSION_2TLS, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,49,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_2_PRIOR_KNOWLEDGE", CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,66,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_3", CURL_HTTP_VERSION_3, CONST_CS|CONST_PERSISTENT); #endif REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_ANY", CURL_HTTP_VERSION_NONE, CONST_CS|CONST_PERSISTENT); @@ -2709,14 +2817,25 @@ PHP_MINIT_FUNCTION(http_client_curl) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1_0", CURL_SSLVERSION_TLSv1_0, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1_1", CURL_SSLVERSION_TLSv1_1, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1_2", CURL_SSLVERSION_TLSv1_2, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,52,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1_3", CURL_SSLVERSION_TLSv1_3, CONST_CS|CONST_PERSISTENT); #endif REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_SSLv2", CURL_SSLVERSION_SSLv2, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_SSLv3", CURL_SSLVERSION_SSLv3, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_ANY", CURL_SSLVERSION_DEFAULT, CONST_CS|CONST_PERSISTENT); -#if PHP_HTTP_CURL_VERSION(7,21,4) && defined(PHP_HTTP_CURL_TLSAUTH_SRP) +#if PHP_HTTP_CURL_VERSION(7,21,4) && PHP_HTTP_HAVE_LIBCURL_TLSAUTH_TYPE REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "TLSAUTH_SRP", CURL_TLSAUTH_SRP, CONST_CS|CONST_PERSISTENT); #endif +#if PHP_HTTP_CURL_VERSION(7,54,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_MAX_DEFAULT", CURL_SSLVERSION_MAX_DEFAULT, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_MAX_TLSv1_0", CURL_SSLVERSION_MAX_TLSv1_0, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_MAX_TLSv1_1", CURL_SSLVERSION_MAX_TLSv1_1, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_MAX_TLSv1_2", CURL_SSLVERSION_MAX_TLSv1_2, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_MAX_TLSv1_3", CURL_SSLVERSION_MAX_TLSv1_3, CONST_CS|CONST_PERSISTENT); +#endif + /* * DNS IPvX resolving */ @@ -2727,6 +2846,7 @@ PHP_MINIT_FUNCTION(http_client_curl) /* * Auth Constants */ + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_NONE", CURLAUTH_NONE, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_BASIC", CURLAUTH_BASIC, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_DIGEST", CURLAUTH_DIGEST, CONST_CS|CONST_PERSISTENT); #if PHP_HTTP_CURL_VERSION(7,19,3) @@ -2736,6 +2856,9 @@ PHP_MINIT_FUNCTION(http_client_curl) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_GSSNEG", CURLAUTH_GSSNEGOTIATE, CONST_CS|CONST_PERSISTENT); #if PHP_HTTP_CURL_VERSION(7,38,0) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_SPNEGO", CURLAUTH_NEGOTIATE, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,61,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_BEARER", CURLAUTH_BEARER, CONST_CS|CONST_PERSISTENT); #endif REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_ANY", CURLAUTH_ANY, CONST_CS|CONST_PERSISTENT); @@ -2743,8 +2866,8 @@ PHP_MINIT_FUNCTION(http_client_curl) * Proxy Type Constants */ REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS4", CURLPROXY_SOCKS4, CONST_CS|CONST_PERSISTENT); - REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS4A", CURLPROXY_SOCKS5, CONST_CS|CONST_PERSISTENT); - REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS5_HOSTNAME", CURLPROXY_SOCKS5, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS4A", CURLPROXY_SOCKS4A, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS5_HOSTNAME", CURLPROXY_SOCKS5_HOSTNAME, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS5", CURLPROXY_SOCKS5, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_HTTP", CURLPROXY_HTTP, CONST_CS|CONST_PERSISTENT); #if PHP_HTTP_CURL_VERSION(7,19,4) @@ -2763,6 +2886,12 @@ PHP_MINIT_FUNCTION(http_client_curl) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "POSTREDIR_ALL", CURL_REDIR_POST_ALL, CONST_CS|CONST_PERSISTENT); #endif +#if PHP_HTTP_CURL_VERSION(7,64,1) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "ALTSVC_READONLYFILE", CURLALTSVC_READONLYFILE, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "ALTSVC_H1", CURLALTSVC_H1, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "ALTSVC_H2", CURLALTSVC_H2, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "ALTSVC_H3", CURLALTSVC_H3, CONST_CS|CONST_PERSISTENT); +#endif return SUCCESS; } @@ -2780,7 +2909,7 @@ PHP_MSHUTDOWN_FUNCTION(http_client_curl) return SUCCESS; } -#endif /* PHP_HTTP_HAVE_CURL */ +#endif /* PHP_HTTP_HAVE_LIBCURL */ /* * Local variables: