curl interop
[m6w6/ext-http] / src / php_http_client_curl.c
index accc02342273a28493e8dcafaf09bbcdd2d1f4ac..8898b5dda91ec37b0ea8f5c73c8085809342e733 100644 (file)
@@ -17,6 +17,8 @@
 
 #if PHP_HTTP_HAVE_LIBCURL
 
+#define DEBUG_COOKIES 0
+
 #if PHP_HTTP_HAVE_LIBCURL_OPENSSL
 #      include <openssl/ssl.h>
 #endif
@@ -330,6 +332,7 @@ 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;
 
@@ -510,6 +513,12 @@ static ZEND_RESULT_CODE php_http_curle_get_info(CURL *ch, HashTable *info)
                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));
@@ -805,6 +814,7 @@ static php_http_options_t php_http_curle_options, php_http_curlm_options;
 #define PHP_HTTP_CURLE_OPTION_CHECK_STRLEN             0x0001
 #define PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR            0x0002
 #define PHP_HTTP_CURLE_OPTION_TRANSFORM_MS             0x0004
+#define PHP_HTTP_CURLE_OPTION_IGNORE_RC                        0x0008
 
 static ZEND_RESULT_CODE php_http_curle_option_set_ssl_verifyhost(php_http_option_t *opt, zval *val, void *userdata)
 {
@@ -826,6 +836,9 @@ static ZEND_RESULT_CODE php_http_curle_option_set_cookiesession(php_http_option_
                return FAILURE;
        }
        if (Z_TYPE_P(val) == IS_TRUE) {
+#if DEBUG_COOKIES
+               fprintf(stderr, "CURLOPT_COOKIELIST: SESS\n");
+#endif
                if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIELIST, "SESS")) {
                        return FAILURE;
                }
@@ -848,9 +861,19 @@ static ZEND_RESULT_CODE php_http_curle_option_set_cookiestore(php_http_option_t
        } else {
                storage->cookiestore = NULL;
        }
-       if (    CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEFILE, storage->cookiestore)
-               ||      CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEJAR, storage->cookiestore)
-       ) {
+
+#if DEBUG_COOKIES
+       fprintf(stderr, "CURLOPT_COOKIEFILE: %s\n", cookiestore);
+#endif
+       // does NOT enable ch->data.cookies until transfer; adds to ch->stsate.cookielist
+       if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEFILE, storage->cookiestore ? storage->cookiestore : "")) {
+               return FAILURE;
+       }
+#if DEBUG_COOKIES
+       fprintf(stderr, "CURLOPT_COOKIEJAR: %s\n", cookiestore);
+#endif
+       // enables ch->data.cookies
+       if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEJAR, storage->cookiestore)) {
                return FAILURE;
        }
 
@@ -942,6 +965,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;
@@ -1269,6 +1307,9 @@ static void php_http_curle_options_init(php_http_options_t *registry)
 #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 */
@@ -1288,6 +1329,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);
@@ -1316,6 +1362,14 @@ 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
+#if PHP_HTTP_CURL_VERSION(7,75,0)
+       php_http_option_register(registry, ZEND_STRL("aws_sigv4"), CURLOPT_AWS_SIGV4, IS_STRING);
+#endif
 
        /* redirects */
        if ((opt = php_http_option_register(registry, ZEND_STRL("redirect"), CURLOPT_FOLLOWLOCATION, IS_LONG))) {
@@ -1401,6 +1455,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))) {
@@ -1541,7 +1598,14 @@ static void php_http_curle_options_init(php_http_options_t *registry)
                        }
 #endif
 #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);
+                       if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("falsestart"), CURLOPT_SSL_FALSESTART, _IS_BOOL))) {
+                               opt->flags |= PHP_HTTP_CURLE_OPTION_IGNORE_RC;
+                       }
+#endif
+#if PHP_HTTP_CURL_VERSION(7,61,0) && PHP_HTTP_HAVE_LIBCURL_TLS13_CIPHERS
+                       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
                }
 
@@ -1578,6 +1642,12 @@ static void php_http_curle_options_init(php_http_options_t *registry)
                                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_CURL_VERSION(7,71,0)
+                       if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("issuercert"), CURLOPT_PROXY_ISSUERCERT, IS_STRING))) {
+                               opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+                               opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR;
+                       }
+#  endif
 #  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;
@@ -1620,11 +1690,42 @@ static void php_http_curle_options_init(php_http_options_t *registry)
                                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) && PHP_HTTP_HAVE_LIBCURL_TLS13_CIPHERS
+                       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 !PHP_HTTP_HAVE_LIBCURL_ALT_SVC
+       if (PHP_HTTP_CURL_FEATURE(CURL_VERSION_ALTSVC)) {
+# endif
+       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;
+       }
+# if !PHP_HTTP_HAVE_LIBCURL_ALT_SVC
+       }
+# endif
+#endif
+#if PHP_HTTP_CURL_VERSION(7,74,0)
+# if !PHP_HTTP_HAVE_LIBCURL_HSTS
+       if (PHP_HTTP_CURL_FEATURE(CURL_VERSION_HSTS)) {
+# endif
+       php_http_option_register(registry, ZEND_STRL("hsts_ctrl"), CURLOPT_HSTS_CTRL, IS_LONG);
+       if ((opt = php_http_option_register(registry, ZEND_STRL("hsts"), CURLOPT_HSTS, IS_STRING))) {
+               opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR;
+       }
+# if !PHP_HTTP_HAVE_LIBCURL_HSTS
+       }
+# endif
+#endif
 }
 
 static zval *php_http_curle_get_option(php_http_option_t *opt, HashTable *options, void *userdata)
@@ -1722,12 +1823,16 @@ static ZEND_RESULT_CODE php_http_curle_set_option(php_http_option_t *opt, zval *
                break;
        }
        if (rv != SUCCESS) {
-               php_error_docref(NULL, E_NOTICE, "Could not set option %s (%s)", opt->name->val, curl_easy_strerror(rc));
+               if (opt->flags & PHP_HTTP_CURLE_OPTION_IGNORE_RC) {
+                       rv = SUCCESS;
+               } else {
+                       php_error_docref(NULL, E_NOTICE, "Could not set option %s (%s)", opt->name->val, curl_easy_strerror(rc));
+               }
        }
        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;
@@ -1829,7 +1934,7 @@ static ZEND_RESULT_CODE php_http_curlm_option_set_share_cookies(php_http_option_
        return SUCCESS;
 }
 
-#if PHP_HTTP_CURL_VERSION(7,23,0)
+#if PHP_HTTP_HAVE_LIBCURL_SHARE_SSL
 static ZEND_RESULT_CODE php_http_curlm_option_set_share_ssl(php_http_option_t *opt, zval *value, void *userdata)
 {
        php_http_client_t *client = userdata;
@@ -1862,38 +1967,38 @@ 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 ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, 0))) {
@@ -1904,7 +2009,7 @@ static void php_http_curlm_options_init(php_http_options_t *registry)
                opt->setter = php_http_curlm_option_set_share_cookies;
                ZVAL_TRUE(&opt->defval);
        }
-#if PHP_HTTP_CURL_VERSION(7,23,0)
+#if PHP_HTTP_HAVE_LIBCURL_SHARE_SSL
        if ((opt = php_http_option_register(registry, ZEND_STRL("share_ssl"), 0, _IS_BOOL))) {
                opt->setter = php_http_curlm_option_set_share_ssl;
                ZVAL_TRUE(&opt->defval);
@@ -1962,9 +2067,10 @@ static ZEND_RESULT_CODE php_http_curlm_set_option(php_http_option_t *opt, zval *
 
 /* client ops */
 
-static ZEND_RESULT_CODE php_http_client_curl_handler_reset(php_http_client_curl_handler_t *curl)
+static ZEND_RESULT_CODE php_http_client_curl_handler_reset(php_http_client_curl_handler_t *handler)
 {
-       CURL *ch = curl->handle;
+       php_http_client_curl_t *curl = handler->client->ctx;
+       CURL *ch = handler->handle;
        php_http_curle_storage_t *st;
 
        if ((st = php_http_curle_get_storage(ch))) {
@@ -1993,27 +2099,55 @@ static ZEND_RESULT_CODE php_http_client_curl_handler_reset(php_http_client_curl_
 #endif
 
 #if PHP_HTTP_CURL_VERSION(7,21,3)
-       if (curl->options.resolve) {
-               curl_slist_free_all(curl->options.resolve);
-               curl->options.resolve = NULL;
+       if (handler->options.resolve) {
+               curl_slist_free_all(handler->options.resolve);
+               handler->options.resolve = NULL;
        }
 #endif
-       curl->options.retry.count = 0;
-       curl->options.retry.delay = 0;
-       curl->options.redirects = 0;
-       curl->options.encode_cookies = 1;
+       handler->options.retry.count = 0;
+       handler->options.retry.delay = 0;
+       handler->options.redirects = 0;
+       handler->options.encode_cookies = 1;
 
-       if (curl->options.headers) {
-               curl_slist_free_all(curl->options.headers);
-               curl->options.headers = NULL;
+       if (handler->options.headers) {
+               curl_slist_free_all(handler->options.headers);
+               handler->options.headers = NULL;
        }
-       if (curl->options.proxyheaders) {
-               curl_slist_free_all(curl->options.proxyheaders);
-               curl->options.proxyheaders = NULL;
+       if (handler->options.proxyheaders) {
+               curl_slist_free_all(handler->options.proxyheaders);
+               handler->options.proxyheaders = NULL;
        }
 
-       php_http_buffer_reset(&curl->options.cookies);
-       php_http_buffer_reset(&curl->options.ranges);
+       php_http_buffer_reset(&handler->options.cookies);
+       php_http_buffer_reset(&handler->options.ranges);
+
+#if ZTS
+       curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
+#endif
+       curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
+       curl_easy_setopt(ch, CURLOPT_FILETIME, 1L);
+       curl_easy_setopt(ch, CURLOPT_AUTOREFERER, 1L);
+       curl_easy_setopt(ch, CURLOPT_VERBOSE, 1L);
+       curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 0L);
+       curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, php_http_curle_header_callback);
+       curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, php_http_curle_body_callback);
+       curl_easy_setopt(ch, CURLOPT_DEBUGFUNCTION, php_http_curle_raw_callback);
+       curl_easy_setopt(ch, CURLOPT_READFUNCTION, php_http_curle_read_callback);
+       curl_easy_setopt(ch, CURLOPT_SEEKFUNCTION, php_http_curle_seek_callback);
+#if PHP_HTTP_CURL_VERSION(7,32,0)
+       curl_easy_setopt(ch, CURLOPT_XFERINFOFUNCTION, php_http_curle_xferinfo_callback);
+       curl_easy_setopt(ch, CURLOPT_XFERINFODATA, handler);
+#else
+       curl_easy_setopt(ch, CURLOPT_PROGRESSFUNCTION, php_http_curle_progress_callback);
+       curl_easy_setopt(ch, CURLOPT_PROGRESSDATA, handler);
+#endif
+       curl_easy_setopt(ch, CURLOPT_DEBUGDATA, handler);
+       curl_easy_setopt(ch, CURLOPT_WRITEDATA, handler);
+       curl_easy_setopt(ch, CURLOPT_HEADERDATA, handler);
+#if DEBUG_COOKIES
+       fprintf(stderr, "CURLOPT_SHARE: %p\n", curl->handle->share);
+#endif
+       curl_easy_setopt(ch, CURLOPT_SHARE, curl->handle->share);
 
        return SUCCESS;
 }
@@ -2021,7 +2155,6 @@ static ZEND_RESULT_CODE php_http_client_curl_handler_reset(php_http_client_curl_
 static php_http_client_curl_handler_t *php_http_client_curl_handler_init(php_http_client_t *h, php_resource_factory_t *rf)
 {
        void *handle;
-       php_http_client_curl_t *curl = h->ctx;
        php_http_client_curl_handler_t *handler;
 
        if (!(handle = php_resource_factory_handle_ctor(rf, NULL))) {
@@ -2039,31 +2172,6 @@ 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 ZTS
-       curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L);
-#endif
-       curl_easy_setopt(handle, CURLOPT_HEADER, 0L);
-       curl_easy_setopt(handle, CURLOPT_FILETIME, 1L);
-       curl_easy_setopt(handle, CURLOPT_AUTOREFERER, 1L);
-       curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L);
-       curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 0L);
-       curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, php_http_curle_header_callback);
-       curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, php_http_curle_body_callback);
-       curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, php_http_curle_raw_callback);
-       curl_easy_setopt(handle, CURLOPT_READFUNCTION, php_http_curle_read_callback);
-       curl_easy_setopt(handle, CURLOPT_SEEKFUNCTION, php_http_curle_seek_callback);
-#if PHP_HTTP_CURL_VERSION(7,32,0)
-       curl_easy_setopt(handle, CURLOPT_XFERINFOFUNCTION, php_http_curle_xferinfo_callback);
-       curl_easy_setopt(handle, CURLOPT_XFERINFODATA, handler);
-#else
-       curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, php_http_curle_progress_callback);
-       curl_easy_setopt(handle, CURLOPT_PROGRESSDATA, handler);
-#endif
-       curl_easy_setopt(handle, CURLOPT_DEBUGDATA, handler);
-       curl_easy_setopt(handle, CURLOPT_WRITEDATA, handler);
-       curl_easy_setopt(handle, CURLOPT_HEADERDATA, handler);
-       curl_easy_setopt(handle, CURLOPT_SHARE, curl->handle->share);
-
        php_http_client_curl_handler_reset(handler);
 
        return handler;
@@ -2187,12 +2295,19 @@ static void php_http_client_curl_handler_clear(php_http_client_curl_handler_t *h
 #endif
        curl_easy_setopt(handler->handle, CURLOPT_VERBOSE, 0L);
        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);
+       {
+               php_http_curle_storage_t *st = php_http_curle_get_storage(handler->handle);
+               curl_easy_setopt(handler->handle, CURLOPT_COOKIEJAR, st ? st->cookiestore : NULL);
+       }
+#endif
+#if DEBUG_COOKIES
+       fprintf(stderr, "CURLOPT_COOKIELIST: FLUSH\n");
+       fprintf(stderr, "CURLOPT_SHARE: (null)\n");
 #endif
+       curl_easy_setopt(handler->handle, CURLOPT_COOKIELIST, "FLUSH");
+       curl_easy_setopt(handler->handle, CURLOPT_SHARE, NULL);
 }
 
 static void php_http_client_curl_handler_dtor(php_http_client_curl_handler_t *handler)
@@ -2480,13 +2595,13 @@ 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_LIBEVENT
                        return php_http_curlm_use_eventloop(h, (*(zend_bool *) arg)
@@ -2589,13 +2704,13 @@ 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);                    \
-                       }                                                                      \
+#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)
@@ -2709,11 +2824,13 @@ PHP_MINIT_FUNCTION(http_client_curl)
                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 (info->iconv_ver_num) {
+                       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 ? tmp_ptr : NULL, 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
@@ -2800,6 +2917,12 @@ 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
+#if PHP_HTTP_CURL_VERSION(7,75,0)
+       REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AWS_SIGV4", CURLAUTH_AWS_SIGV4, CONST_CS|CONST_PERSISTENT);
 #endif
        REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_ANY", CURLAUTH_ANY, CONST_CS|CONST_PERSISTENT);
 
@@ -2827,6 +2950,16 @@ 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
+#if PHP_HTTP_CURL_VERSION(7,74,0)
+       REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HSTS_ENABLE", CURLHSTS_ENABLE, CONST_CS|CONST_PERSISTENT);
+       REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HSTS_READONLYFILE", CURLHSTS_READONLYFILE, CONST_CS|CONST_PERSISTENT);
+#endif
        return SUCCESS;
 }