fix leak
[m6w6/ext-http] / php_http_client_curl.c
index edafe03edce0983a8596e7ea2c8e66e631d11e09..baf99ceb30bd58dbc9adcb733d6a86285a7d9139 100644 (file)
@@ -194,7 +194,11 @@ static size_t php_http_curle_read_callback(void *data, size_t len, size_t n, voi
        return 0;
 }
 
+#if PHP_HTTP_CURL_VERSION(7,32,0)
+static int php_http_curle_xferinfo_callback(void *ctx, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
+#else
 static int php_http_curle_progress_callback(void *ctx, double dltotal, double dlnow, double ultotal, double ulnow)
+#endif
 {
        php_http_client_curl_handler_t *h = ctx;
        zend_bool update = 0;
@@ -792,9 +796,9 @@ static void php_http_curlm_timer_callback(CURLM *multi, long timeout_ms, void *t
 
 static php_http_options_t php_http_curle_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_CHECK_STRLEN             0x0001
+#define PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR            0x0002
+#define PHP_HTTP_CURLE_OPTION_TRANSFORM_MS             0x0004
 
 static STATUS php_http_curle_option_set_ssl_verifyhost(php_http_option_t *opt, zval *val, void *userdata)
 {
@@ -811,19 +815,20 @@ static STATUS php_http_curle_option_set_cookiestore(php_http_option_t *opt, zval
 {
        php_http_client_curl_handler_t *curl = userdata;
        CURL *ch = curl->handle;
+       php_http_curle_storage_t *storage = php_http_curle_get_storage(curl->handle);
 
-       if (val) {
-               php_http_curle_storage_t *storage = php_http_curle_get_storage(curl->handle);
-
-               if (storage->cookiestore) {
-                       pefree(storage->cookiestore, 1);
-               }
+       if (storage->cookiestore) {
+               pefree(storage->cookiestore, 1);
+       }
+       if (val && Z_STRLEN_P(val)) {
                storage->cookiestore = pestrndup(Z_STRVAL_P(val), Z_STRLEN_P(val), 1);
-               if (    CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEFILE, storage->cookiestore)
-                       ||      CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEJAR, storage->cookiestore)
-               ) {
-                       return FAILURE;
-               }
+       } 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)
+       ) {
+               return FAILURE;
        }
        return SUCCESS;
 }
@@ -866,6 +871,11 @@ static STATUS php_http_curle_option_set_cookies(php_http_option_t *opt, zval *va
                                }
                        }
                }
+       } else {
+               php_http_buffer_reset(&curl->options.cookies);
+               if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIE, NULL)) {
+                       return FAILURE;
+               }
        }
        return SUCCESS;
 }
@@ -921,13 +931,15 @@ static STATUS php_http_curle_option_set_etag(php_http_option_t *opt, zval *val,
 {
        php_http_client_curl_handler_t *curl = userdata;
        php_http_buffer_t header;
-       zend_bool is_quoted = !((Z_STRVAL_P(val)[0] != '"') || (Z_STRVAL_P(val)[Z_STRLEN_P(val)-1] != '"'));
 
-       php_http_buffer_init(&header);
-       php_http_buffer_appendf(&header, is_quoted?"%s: %s":"%s: \"%s\"", curl->options.range_request?"If-Match":"If-None-Match", Z_STRVAL_P(val));
-       php_http_buffer_fix(&header);
-       curl->options.headers = curl_slist_append(curl->options.headers, header.data);
-       php_http_buffer_dtor(&header);
+       if (Z_STRLEN_P(val)) {
+               zend_bool is_quoted = !((Z_STRVAL_P(val)[0] != '"') || (Z_STRVAL_P(val)[Z_STRLEN_P(val)-1] != '"'));
+               php_http_buffer_init(&header);
+               php_http_buffer_appendf(&header, is_quoted?"%s: %s":"%s: \"%s\"", curl->options.range_request?"If-Match":"If-None-Match", Z_STRVAL_P(val));
+               php_http_buffer_fix(&header);
+               curl->options.headers = curl_slist_append(curl->options.headers, header.data);
+               php_http_buffer_dtor(&header);
+       }
        return SUCCESS;
 }
 
@@ -1117,10 +1129,23 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
                opt->setter = php_http_curle_option_set_resolve;
        }
 #endif
-#if PHP_HTTP_CURL_VERSION(7,24,0)
+#if PHP_HTTP_HAVE_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;
        }
+# endif
+# if PHP_HTTP_CURL_VERSION(7,33,0)
+       if ((opt = php_http_option_register(registry, ZEND_STRL("dns_interface"), CURLOPT_DNS_INTERFACE, IS_STRING))) {
+               opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+       }
+       if ((opt = php_http_option_register(registry, ZEND_STRL("dns_local_ip4"), CURLOPT_DNS_LOCAL_IP4, IS_STRING))) {
+               opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+       }
+       if ((opt = php_http_option_register(registry, ZEND_STRL("dns_local_ip6"), CURLOPT_DNS_LOCAL_IP6, IS_STRING))) {
+               opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+       }
+# endif
 #endif
 
        /* limits */
@@ -1255,8 +1280,15 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
                opt->flags |= PHP_HTTP_CURLE_OPTION_TRANSFORM_MS;
                Z_DVAL(opt->defval) = 3;
        }
+#if PHP_HTTP_CURL_VERSION(7,36,0)
+       if ((opt = php_http_option_register(registry, ZEND_STRL("expect_100_timeout"), CURLOPT_EXPECT_100_TIMEOUT_MS, IS_DOUBLE))) {
+               opt->flags |= PHP_HTTP_CURLE_OPTION_TRANSFORM_MS;
+               Z_DVAL(opt->defval) = 1;
+       }
+#endif
 
        /* tcp */
+       php_http_option_register(registry, ZEND_STRL("tcp_nodelay"), CURLOPT_TCP_NODELAY, IS_BOOL);
 #if PHP_HTTP_CURL_VERSION(7,25,0)
        php_http_option_register(registry, ZEND_STRL("tcp_keepalive"), CURLOPT_TCP_KEEPALIVE, IS_BOOL);
        if ((opt = php_http_option_register(registry, ZEND_STRL("tcp_keepidle"), CURLOPT_TCP_KEEPIDLE, IS_LONG))) {
@@ -1275,14 +1307,21 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR;
                }
-               php_http_option_register(registry, ZEND_STRL("certtype"), CURLOPT_SSLCERTTYPE, IS_STRING);
-
+               if ((opt = php_http_option_register(registry, ZEND_STRL("certtype"), CURLOPT_SSLCERTTYPE, IS_STRING))) {
+                       opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+                       ZVAL_STRING(&opt->defval, "PEM", 0);
+               }
                if ((opt = php_http_option_register(registry, ZEND_STRL("key"), CURLOPT_SSLKEY, IS_STRING))) {
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR;
                }
-               php_http_option_register(registry, ZEND_STRL("keytype"), CURLOPT_SSLKEYTYPE, IS_STRING);
-               php_http_option_register(registry, ZEND_STRL("keypasswd"), CURLOPT_SSLKEYPASSWD, IS_STRING);
+               if ((opt = php_http_option_register(registry, ZEND_STRL("keytype"), CURLOPT_SSLKEYTYPE, IS_STRING))) {
+                       opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+                       ZVAL_STRING(&opt->defval, "PEM", 0);
+               }
+               if ((opt = php_http_option_register(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))) {
@@ -1326,6 +1365,14 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
 #endif
 #if PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)
                php_http_option_register(registry, ZEND_STRL("certinfo"), CURLOPT_CERTINFO, IS_BOOL);
+#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))) {
+                       ZVAL_BOOL(&opt->defval, 1);
+               }
+               if ((opt = php_http_option_register(registry, ZEND_STRL("enable_alpn"), CURLOPT_SSL_ENABLE_ALPN, IS_BOOL))) {
+                       ZVAL_BOOL(&opt->defval, 1);
+               }
 #endif
        }
 }
@@ -1347,6 +1394,7 @@ static STATUS php_http_curle_set_option(php_http_option_t *opt, zval *val, void
        php_http_client_curl_handler_t *curl = userdata;
        CURL *ch = curl->handle;
        zval tmp;
+       CURLcode rc = CURLE_OK;
        STATUS rv = SUCCESS;
        TSRMLS_FETCH_FROM_CTX(curl->client->ts);
 
@@ -1372,14 +1420,18 @@ static STATUS php_http_curle_set_option(php_http_option_t *opt, zval *val, void
                break;
 
        case IS_STRING:
-               if (!(opt->flags & PHP_HTTP_CURLE_OPTION_CHECK_STRLEN) || Z_STRLEN_P(val)) {
-                       if (!(opt->flags & PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR) || !Z_STRVAL_P(val) || SUCCESS == php_check_open_basedir(Z_STRVAL_P(val) TSRMLS_CC)) {
-                               if (opt->setter) {
-                                       rv = opt->setter(opt, val, curl);
-                               } else if (CURLE_OK != curl_easy_setopt(ch, opt->option, Z_STRVAL_P(val))) {
-                                       rv = FAILURE;
-                               }
+               if (opt->setter) {
+                       rv = opt->setter(opt, val, curl);
+               } else if ((opt->flags & PHP_HTTP_CURLE_OPTION_CHECK_STRLEN) && !Z_STRLEN_P(val)) {
+                       if (CURLE_OK != (rc = curl_easy_setopt(ch, opt->option, NULL))) {
+                               rv = FAILURE;
+                       }
+               } else if ((opt->flags & PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR) && Z_STRVAL_P(val) && SUCCESS != php_check_open_basedir(Z_STRVAL_P(val) TSRMLS_CC)) {
+                       if (CURLE_OK != (rc = curl_easy_setopt(ch, opt->option, NULL))) {
+                               rv = FAILURE;
                        }
+               } else if (CURLE_OK != (rc = curl_easy_setopt(ch, opt->option, Z_STRVAL_P(val)))) {
+                       rv = FAILURE;
                }
                break;
 
@@ -1413,7 +1465,7 @@ static STATUS php_http_curle_set_option(php_http_option_t *opt, zval *val, void
                break;
        }
        if (rv != SUCCESS) {
-               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not set option %s", opt->name.s);
+               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not set option %s (%s)", opt->name.s, curl_easy_strerror(rc));
        }
        return rv;
 }
@@ -1507,9 +1559,14 @@ static php_http_client_curl_handler_t *php_http_client_curl_handler_init(php_htt
        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_IOCTLFUNCTION, php_http_curle_ioctl_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_DEBUGDATA, handler);
        curl_easy_setopt(handle, CURLOPT_PROGRESSDATA, handler);
+#endif
+       curl_easy_setopt(handle, CURLOPT_DEBUGDATA, handler);
 
        php_http_client_curl_handler_reset(handler);
 
@@ -1620,7 +1677,11 @@ static void php_http_client_curl_handler_dtor(php_http_client_curl_handler_t *ha
        TSRMLS_FETCH_FROM_CTX(handler->client->ts);
 
        curl_easy_setopt(handler->handle, CURLOPT_NOPROGRESS, 1L);
+#if PHP_HTTP_CURL_VERSION(7,32,0)
+       curl_easy_setopt(handler->handle, CURLOPT_XFERINFOFUNCTION, NULL);
+#else
        curl_easy_setopt(handler->handle, CURLOPT_PROGRESSFUNCTION, NULL);
+#endif
        curl_easy_setopt(handler->handle, CURLOPT_VERBOSE, 0L);
        curl_easy_setopt(handler->handle, CURLOPT_DEBUGFUNCTION, NULL);