back to dev
[m6w6/ext-http] / php_http_client_curl.c
index 289e43c372e0149214875963ca54c3e5458ec539..44b2c21a9cc819a842e50cabcc23d6dbbb13c558 100644 (file)
@@ -934,6 +934,9 @@ static STATUS php_http_curle_option_set_compress(php_http_option_t *opt, zval *v
        php_http_client_curl_handler_t *curl = userdata;
        CURL *ch = curl->handle;
 
+#if !PHP_HTTP_CURL_VERSION(7,21,6)
+#      define CURLOPT_ACCEPT_ENCODING CURLOPT_ENCODING
+#endif
        if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_ACCEPT_ENCODING, Z_BVAL_P(val) ? "" : NULL)) {
                return FAILURE;
        }
@@ -1148,7 +1151,7 @@ static STATUS php_http_curle_option_set_resolve(php_http_option_t *opt, zval *va
 }
 #endif
 
-#if PHP_HTTP_CURL_VERSION(7,21,4)
+#if PHP_HTTP_CURL_VERSION(7,21,4) && defined(PHP_HTTP_CURL_TLSAUTH_SRP)
 static STATUS php_http_curle_option_set_ssl_tlsauthtype(php_http_option_t *opt, zval *val, void *userdata)
 {
        php_http_client_curl_handler_t *curl = userdata;
@@ -1470,7 +1473,7 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR;
                }
 #endif
-#if PHP_HTTP_CURL_VERSION(7,21,4)
+#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))) {
                        opt->setter = php_http_curle_option_set_ssl_tlsauthtype;
                }
@@ -1682,7 +1685,7 @@ static void php_http_curlm_options_init(php_http_options_t *registry TSRMLS_DC)
        php_http_option_register(registry, ZEND_STRL("pipelining"), CURLMOPT_PIPELINING, IS_BOOL);
        /* chunk length threshold for pipelining */
 #if PHP_HTTP_CURL_VERSION(7,30,0)
-       php_http_option_register(registry, ZEND_STRL("chunk_lenght_penalty_size"), CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, IS_LONG);
+       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)
@@ -1701,7 +1704,7 @@ static void php_http_curlm_options_init(php_http_options_t *registry TSRMLS_DC)
        }
 #endif
        /* events */
-#ifdef PHP_HTTP_HAVE_EVENT
+#if PHP_HTTP_HAVE_EVENT
        if ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, IS_BOOL))) {
                opt->setter = php_http_curlm_option_set_use_eventloop;
        }
@@ -1720,7 +1723,7 @@ static STATUS php_http_curlm_set_option(php_http_option_t *opt, zval *val, void
 
        if (!val) {
                val = &opt->defval;
-       } else if (Z_TYPE_P(val) != opt->type && !(Z_TYPE_P(val) == IS_NULL && opt->type == IS_ARRAY)) {
+       } else if (opt->type && Z_TYPE_P(val) != opt->type && !(Z_TYPE_P(val) == IS_NULL && opt->type == IS_ARRAY)) {
                val = php_http_ztyp(opt->type, val);
        }
 
@@ -2061,29 +2064,44 @@ static void queue_dtor(php_http_client_enqueue_t *e)
        php_http_client_curl_handler_dtor(handler);
 }
 
-static php_resource_factory_t *create_rf(php_http_url_t *url TSRMLS_DC)
+static php_resource_factory_t *create_rf(php_http_client_t *h, php_http_client_enqueue_t *enqueue TSRMLS_DC)
 {
-       php_persistent_handle_factory_t *pf;
+       php_persistent_handle_factory_t *pf = NULL;
        php_resource_factory_t *rf = NULL;
-       char *id_str = NULL;
-       size_t id_len;
+       php_http_url_t *url = enqueue->request->http.info.request.url;
 
        if (!url || (!url->host && !url->path)) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot request empty URL");
                return NULL;
        }
 
-       id_len = spprintf(&id_str, 0, "%s:%d", STR_PTR(url->host), url->port ? url->port : 80);
+       /* only if the client itself is setup for persistence */
+       if (h->rf->dtor == (void (*)(void*)) php_persistent_handle_abandon) {
+               char *id_str = NULL;
+               size_t id_len;
+               int port = url->port ? url->port : 80;
+               zval **zport;
+
+               if (SUCCESS == zend_hash_find(enqueue->options, ZEND_STRS("port"), (void *) &zport)) {
+                       zval *zcpy = php_http_ztyp(IS_LONG, *zport);
+
+                       if (Z_LVAL_P(zcpy)) {
+                               port = Z_LVAL_P(zcpy);
+                       }
+                       zval_ptr_dtor(&zcpy);
+               }
+
+               id_len = spprintf(&id_str, 0, "%s:%d", STR_PTR(url->host), port);
+               pf = php_persistent_handle_concede(NULL, ZEND_STRL("http\\Client\\Curl\\Request"), id_str, id_len, NULL, NULL TSRMLS_CC);
+               efree(id_str);
+       }
 
-       pf = php_persistent_handle_concede(NULL, ZEND_STRL("http\\Client\\Curl\\Request"), id_str, id_len, NULL, NULL TSRMLS_CC);
        if (pf) {
                rf = php_resource_factory_init(NULL, php_persistent_handle_get_resource_factory_ops(), pf, (void (*)(void*)) php_persistent_handle_abandon);
        } else {
                rf = php_resource_factory_init(NULL, &php_http_curle_resource_factory_ops, NULL, NULL);
        }
 
-       efree(id_str);
-
        return rf;
 }
 
@@ -2096,7 +2114,7 @@ static STATUS php_http_client_curl_enqueue(php_http_client_t *h, php_http_client
        php_resource_factory_t *rf;
        TSRMLS_FETCH_FROM_CTX(h->ts);
 
-       rf = create_rf(enqueue->request->http.info.request.url TSRMLS_CC);
+       rf = create_rf(h, enqueue TSRMLS_CC);
        if (!rf) {
                return FAILURE;
        }
@@ -2307,9 +2325,43 @@ static STATUS php_http_client_curl_setopt(php_http_client_t *h, php_http_client_
        return SUCCESS;
 }
 
+static int apply_available_options(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+{
+       php_http_option_t *opt = pDest;
+       HashTable *ht;
+       zval *entry;
+       int c;
+
+       ht = va_arg(args, HashTable*);
+
+       MAKE_STD_ZVAL(entry);
+
+       if ((c = zend_hash_num_elements(&opt->suboptions.options))) {
+               array_init_size(entry, c);
+               zend_hash_apply_with_arguments(&opt->suboptions.options TSRMLS_CC, apply_available_options, 1, Z_ARRVAL_P(entry));
+       } else {
+               /* catch deliberate NULL options */
+               if (Z_TYPE(opt->defval) == IS_STRING && !Z_STRVAL(opt->defval)) {
+                       ZVAL_NULL(entry);
+               } else {
+                       ZVAL_COPY_VALUE(entry, &opt->defval);
+                       zval_copy_ctor(entry);
+               }
+       }
+
+       if (hash_key->nKeyLength) {
+               zend_hash_quick_update(ht, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &entry, sizeof(zval *), NULL);
+       } else {
+               zend_hash_index_update(ht, hash_key->h, (void *) &entry, sizeof(zval *), NULL);
+       }
+
+       return ZEND_HASH_APPLY_KEEP;
+}
+
 static STATUS php_http_client_curl_getopt(php_http_client_t *h, php_http_client_getopt_opt_t opt, void *arg, void **res)
 {
        php_http_client_enqueue_t *enqueue;
+       TSRMLS_FETCH_FROM_CTX(h->ts);
 
        switch (opt) {
        case PHP_HTTP_CLIENT_OPT_PROGRESS_INFO:
@@ -2330,6 +2382,14 @@ static STATUS php_http_client_curl_getopt(php_http_client_t *h, php_http_client_
                }
                break;
 
+       case PHP_HTTP_CLIENT_OPT_AVAILABLE_OPTIONS:
+               zend_hash_apply_with_arguments(&php_http_curle_options.options TSRMLS_CC, apply_available_options, 1, *(HashTable **) res);
+               break;
+
+       case PHP_HTTP_CLIENT_OPT_AVAILABLE_CONFIGURATION:
+               zend_hash_apply_with_arguments(&php_http_curlm_options.options TSRMLS_CC, apply_available_options, 1, *(HashTable **) res);
+               break;
+
        default:
                break;
        }
@@ -2411,7 +2471,7 @@ PHP_MINIT_FUNCTION(http_client_curl)
        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)
+#if PHP_HTTP_CURL_VERSION(7,21,4) && defined(PHP_HTTP_CURL_TLSAUTH_SRP)
        REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "TLSAUTH_SRP", CURL_TLSAUTH_SRP, CONST_CS|CONST_PERSISTENT);
 #endif