let the request be able to carry client options
authorMichael Wallner <mike@php.net>
Fri, 30 Mar 2012 11:54:57 +0000 (11:54 +0000)
committerMichael Wallner <mike@php.net>
Fri, 30 Mar 2012 11:54:57 +0000 (11:54 +0000)
php_http_client.c
php_http_client.h
php_http_client_curl.c
php_http_client_curl.h
php_http_client_request.c
php_http_client_request.h

index 4bf7d88..06e90ba 100644 (file)
@@ -339,7 +339,7 @@ STATUS php_http_client_object_handle_request(zval *zclient, zval **zreq TSRMLS_D
                /* maybe a request is already set */
                *zreq = zend_read_property(php_http_client_class_entry, zclient, ZEND_STRL("request"), 0 TSRMLS_CC);
 
-               if (Z_TYPE_PP(zreq) != IS_OBJECT || !instanceof_function(Z_OBJCE_PP(zreq), php_http_client_request_class_entry TSRMLS_CC)) {
+               if (Z_TYPE_PP(zreq) != IS_OBJECT || !instanceof_function(Z_OBJCE_PP(zreq), php_http_client_request_get_class_entry() TSRMLS_CC)) {
                        php_http_error(HE_WARNING, PHP_HTTP_E_CLIENT, "The client does not have a valid request set");
                        return FAILURE;
                }
@@ -351,9 +351,12 @@ STATUS php_http_client_object_handle_request(zval *zclient, zval **zreq TSRMLS_D
        /* reset transfer info */
        zend_update_property_null(php_http_client_class_entry, zclient, ZEND_STRL("info") TSRMLS_CC);
 
-       /* set request options */
+       /* set client options */
        zoptions = zend_read_property(php_http_client_class_entry, zclient, ZEND_STRL("options"), 0 TSRMLS_CC);
        php_http_client_setopt(obj->client, PHP_HTTP_CLIENT_OPT_SETTINGS, Z_ARRVAL_P(zoptions));
+       /* set request options */
+       zoptions = zend_read_property(php_http_client_request_get_class_entry(), *zreq, ZEND_STRL("options"), 0 TSRMLS_CC);
+       php_http_client_setopt(obj->client, PHP_HTTP_CLIENT_OPT_SETTINGS, Z_ARRVAL_P(zoptions));
 
        /* set progress callback */
        if (SUCCESS == php_http_client_getopt(obj->client, PHP_HTTP_CLIENT_OPT_PROGRESS_INFO, &progress)) {
@@ -453,53 +456,35 @@ STATUS php_http_client_object_handle_response(zval *zclient TSRMLS_DC)
        return SUCCESS;
 }
 
-static int apply_pretty_key(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
-{
-       zval **zpp = pDest, *arr = va_arg(args, zval *);
-
-       if (hash_key->arKey && hash_key->nKeyLength > 1) {
-               char *tmp = php_http_pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 0);
-
-               Z_ADDREF_PP(zpp);
-               add_assoc_zval_ex(arr, tmp, hash_key->nKeyLength, *zpp);
-               efree(tmp);
-       }
-       return ZEND_HASH_APPLY_KEEP;
-}
-
-static void php_http_client_object_set_options(INTERNAL_FUNCTION_PARAMETERS)
+void php_http_client_options_set(zval *this_ptr, zval *opts TSRMLS_DC)
 {
        php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
        HashPosition pos;
-       zval *opts = NULL, *old_opts, *new_opts, *add_opts, **opt;
-
-       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
-               RETURN_FALSE;
-       }
+       zval *new_opts;
+       zend_class_entry *this_ce = Z_OBJCE_P(getThis());
+       zend_bool is_client = instanceof_function(this_ce, php_http_client_class_entry TSRMLS_CC);
 
        MAKE_STD_ZVAL(new_opts);
        array_init(new_opts);
 
        if (!opts || !zend_hash_num_elements(Z_ARRVAL_P(opts))) {
-               zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC);
+               zend_update_property(this_ce, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC);
                zval_ptr_dtor(&new_opts);
        } else {
+               zval *old_opts, *add_opts, **opt;
+
                MAKE_STD_ZVAL(add_opts);
                array_init(add_opts);
                /* some options need extra attention -- thus cannot use array_merge() directly */
                FOREACH_KEYVAL(pos, opts, key, opt) {
                        if (key.type == HASH_KEY_IS_STRING) {
 #define KEYMATCH(k, s) ((sizeof(s)==k.len) && !strcasecmp(k.str, s))
-                               if (KEYMATCH(key, "ssl")) {
-                                       zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addssloptions", NULL, *opt);
-                               } else if (KEYMATCH(key, "cookies")) {
-                                       zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addcookies", NULL, *opt);
-                               } else if (KEYMATCH(key, "recordHistory")) {
-                                       zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("recordHistory"), *opt TSRMLS_CC);
-                               } else if (KEYMATCH(key, "responseMessageClass")) {
-                                       zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmessageclass", NULL, *opt);
+                               if (Z_TYPE_PP(opt) == IS_ARRAY && (KEYMATCH(key, "ssl") || KEYMATCH(key, "cookies"))) {
+                                       php_http_client_options_set_subr(getThis(), key.str, key.len, *opt, 0 TSRMLS_CC);
+                               } else if (is_client && (KEYMATCH(key, "recordHistory") || KEYMATCH(key, "responseMessageClass"))) {
+                                       zend_update_property(this_ce, getThis(), key.str, key.len-1, *opt TSRMLS_CC);
                                } else if (Z_TYPE_PP(opt) == IS_NULL) {
-                                       old_opts = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
+                                       old_opts = zend_read_property(this_ce, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
                                        if (Z_TYPE_P(old_opts) == IS_ARRAY) {
                                                zend_symtable_del(Z_ARRVAL_P(old_opts), key.str, key.len);
                                        }
@@ -510,89 +495,75 @@ static void php_http_client_object_set_options(INTERNAL_FUNCTION_PARAMETERS)
                        }
                }
 
-               old_opts = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
+               old_opts = zend_read_property(this_ce, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
                if (Z_TYPE_P(old_opts) == IS_ARRAY) {
                        array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
                }
                array_join(Z_ARRVAL_P(add_opts), Z_ARRVAL_P(new_opts), 0, 0);
-               zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC);
+               zend_update_property(this_ce, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC);
                zval_ptr_dtor(&new_opts);
                zval_ptr_dtor(&add_opts);
        }
-
-       RETVAL_ZVAL(getThis(), 1, 0);
 }
 
-static inline void php_http_client_object_set_options_subr(INTERNAL_FUNCTION_PARAMETERS, char *key, size_t len, int overwrite, int prettify_keys)
+void php_http_client_options_set_subr(zval *this_ptr, char *key, size_t len, zval *opts, int overwrite TSRMLS_DC)
 {
-       zval *old_opts, *new_opts, *opts = NULL, **entry = NULL;
+       if (overwrite || (opts && zend_hash_num_elements(Z_ARRVAL_P(opts)))) {
+               zend_class_entry *this_ce = Z_OBJCE_P(getThis());
+               zval *old_opts, *new_opts, **entry = NULL;
 
-       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &opts)) {
                MAKE_STD_ZVAL(new_opts);
                array_init(new_opts);
-               old_opts = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
+               old_opts = zend_read_property(this_ce, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
                if (Z_TYPE_P(old_opts) == IS_ARRAY) {
                        array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
                }
 
-               if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(new_opts), key, len, (void *) &entry)) {
-                       if (overwrite) {
-                               zend_hash_clean(Z_ARRVAL_PP(entry));
-                       }
+               if (overwrite) {
                        if (opts && zend_hash_num_elements(Z_ARRVAL_P(opts))) {
-                               if (overwrite) {
-                                       array_copy(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry));
-                               } else {
-                                       array_join(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry), 0, prettify_keys ? ARRAY_JOIN_PRETTIFY : 0);
-                               }
+                               Z_ADDREF_P(opts);
+                               zend_symtable_update(Z_ARRVAL_P(new_opts), key, len, (void *) &opts, sizeof(zval *), NULL);
+                       } else {
+                               zend_symtable_del(Z_ARRVAL_P(new_opts), key, len);
                        }
-               } else if (opts) {
-                       if (prettify_keys) {
-                               zval *tmp;
-
-                               MAKE_STD_ZVAL(tmp);
-                               array_init_size(tmp, zend_hash_num_elements(Z_ARRVAL_P(opts)));
-                               zend_hash_apply_with_arguments(Z_ARRVAL_P(opts) TSRMLS_CC, apply_pretty_key, 1, tmp);
-                               opts = tmp;
+               } else if (opts && zend_hash_num_elements(Z_ARRVAL_P(opts))) {
+                       if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(new_opts), key, len, (void *) &entry)) {
+                               array_join(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry), 0, 0);
                        } else {
                                Z_ADDREF_P(opts);
+                               zend_symtable_update(Z_ARRVAL_P(new_opts), key, len, (void *) &opts, sizeof(zval *), NULL);
                        }
-                       add_assoc_zval_ex(new_opts, key, len, opts);
                }
-               zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC);
+
+               zend_update_property(this_ce, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC);
                zval_ptr_dtor(&new_opts);
        }
-
-       RETVAL_ZVAL(getThis(), 1, 0);
 }
 
-static inline void php_http_client_object_get_options_subr(INTERNAL_FUNCTION_PARAMETERS, char *key, size_t len)
+void php_http_client_options_get_subr(zval *this_ptr, char *key, size_t len, zval *return_value TSRMLS_DC)
 {
-       if (SUCCESS == zend_parse_parameters_none()) {
-               zval *opts, **options;
+       zend_class_entry *this_ce = Z_OBJCE_P(getThis());
+       zval **options, *opts = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
 
-               opts = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
-               array_init(return_value);
-
-               if (    (Z_TYPE_P(opts) == IS_ARRAY) &&
-                               (SUCCESS == zend_symtable_find(Z_ARRVAL_P(opts), key, len, (void *) &options))) {
-                       convert_to_array(*options);
-                       array_copy(Z_ARRVAL_PP(options), Z_ARRVAL_P(return_value));
-               }
+       if ((Z_TYPE_P(opts) == IS_ARRAY) && (SUCCESS == zend_symtable_find(Z_ARRVAL_P(opts), key, len, (void *) &options))) {
+               RETVAL_ZVAL(*options, 1, 0);
        }
 }
 
 PHP_METHOD(HttpClient, __construct)
 {
        with_error_handling(EH_THROW, php_http_exception_class_entry) {
-               zval *os;
+               zval *os, *opts = NULL;
 
                MAKE_STD_ZVAL(os);
                object_init_ex(os, spl_ce_SplObjectStorage);
                zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("observers"), os TSRMLS_CC);
                zval_ptr_dtor(&os);
 
-               php_http_client_object_set_options(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+               if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
+                       php_http_client_options_set(getThis(), opts TSRMLS_CC);
+               }
+
        } end_error_handling();
 }
 
@@ -719,7 +690,13 @@ PHP_METHOD(HttpClient, getTransferInfo)
 
 PHP_METHOD(HttpClient, setOptions)
 {
-       php_http_client_object_set_options(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+       zval *opts = NULL;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
+               php_http_client_options_set(getThis(), opts TSRMLS_CC);
+
+               RETVAL_ZVAL(getThis(), 1, 0);
+       }
 }
 
 PHP_METHOD(HttpClient, getOptions)
@@ -732,32 +709,60 @@ PHP_METHOD(HttpClient, getOptions)
 
 PHP_METHOD(HttpClient, setSslOptions)
 {
-       php_http_client_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRS("ssl"), 1, 0);
+       zval *opts = NULL;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
+               php_http_client_options_set_subr(getThis(), ZEND_STRS("ssl"), opts, 1 TSRMLS_CC);
+
+               RETVAL_ZVAL(getThis(), 1, 0);
+       }
 }
 
 PHP_METHOD(HttpClient, addSslOptions)
 {
-       php_http_client_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRS("ssl"), 0, 0);
+       zval *opts = NULL;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
+               php_http_client_options_set_subr(getThis(), ZEND_STRS("ssl"), opts, 0 TSRMLS_CC);
+
+               RETVAL_ZVAL(getThis(), 1, 0);
+       }
 }
 
 PHP_METHOD(HttpClient, getSslOptions)
 {
-       php_http_client_object_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRS("ssl"));
+       if (SUCCESS == zend_parse_parameters_none()) {
+               php_http_client_options_get_subr(getThis(), ZEND_STRS("ssl"), return_value TSRMLS_CC);
+       }
 }
 
 PHP_METHOD(HttpClient, setCookies)
 {
-       php_http_client_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRS("cookies"), 1, 0);
+       zval *opts = NULL;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
+               php_http_client_options_set_subr(getThis(), ZEND_STRS("cookies"), opts, 1 TSRMLS_CC);
+
+               RETVAL_ZVAL(getThis(), 1, 0);
+       }
 }
 
 PHP_METHOD(HttpClient, addCookies)
 {
-       php_http_client_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRS("cookies"), 0, 0);
+       zval *opts = NULL;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
+               php_http_client_options_set_subr(getThis(), ZEND_STRS("ssl"), opts, 0 TSRMLS_CC);
+
+               RETVAL_ZVAL(getThis(), 1, 0);
+       }
 }
 
 PHP_METHOD(HttpClient, getCookies)
 {
-       php_http_client_object_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRS("cookies"));
+       if (SUCCESS == zend_parse_parameters_none()) {
+               php_http_client_options_get_subr(getThis(), ZEND_STRS("cookies"), return_value TSRMLS_CC);
+       }
 }
 
 PHP_METHOD(HttpClient, enableCookies)
@@ -871,7 +876,7 @@ PHP_METHOD(HttpClient, setRequest)
 {
        zval *zreq = NULL;
 
-       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zreq, php_http_client_request_class_entry)) {
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zreq, php_http_client_request_get_class_entry())) {
                zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("request"), zreq TSRMLS_CC);
        }
        RETURN_ZVAL(getThis(), 1, 0);
@@ -891,7 +896,7 @@ PHP_METHOD(HttpClient, send)
        RETVAL_FALSE;
 
        with_error_handling(EH_THROW, php_http_exception_class_entry) {
-               if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O!", &zreq, php_http_client_request_class_entry)) {
+               if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O!", &zreq, php_http_client_request_get_class_entry())) {
                        if (SUCCESS == php_http_client_object_handle_request(getThis(), &zreq TSRMLS_CC)) {
                                php_http_client_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
                                php_http_message_object_t *req = zend_object_store_get_object(zreq TSRMLS_CC);
@@ -921,12 +926,12 @@ PHP_MINIT_FUNCTION(http_client)
 
        zend_declare_property_string(php_http_client_class_entry, ZEND_STRL("responseMessageClass"), "", ZEND_ACC_PRIVATE TSRMLS_CC);
        zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("observers"), ZEND_ACC_PRIVATE TSRMLS_CC);
-       zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("options"), ZEND_ACC_PRIVATE TSRMLS_CC);
        zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("transferInfo"), ZEND_ACC_PRIVATE TSRMLS_CC);
        zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("responseMessage"), ZEND_ACC_PRIVATE TSRMLS_CC);
        zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("requestMessage"), ZEND_ACC_PRIVATE TSRMLS_CC);
        zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("history"), ZEND_ACC_PRIVATE TSRMLS_CC);
 
+       zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("options"), ZEND_ACC_PROTECTED TSRMLS_CC);
        zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("request"), ZEND_ACC_PROTECTED TSRMLS_CC);
 
        zend_declare_property_bool(php_http_client_class_entry, ZEND_STRL("recordHistory"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
index e642870..b5aeb57 100644 (file)
@@ -177,8 +177,9 @@ zend_object_handlers *php_http_client_get_object_handlers(void);
 STATUS php_http_client_object_handle_request(zval *zclient, zval **zreq TSRMLS_DC);
 STATUS php_http_client_object_handle_response(zval *zclient TSRMLS_DC);
 
-STATUS php_http_client_object_requesthandler(php_http_client_object_t *obj, zval *this_ptr, char **meth, char **url, php_http_message_body_t **body TSRMLS_DC);
-STATUS php_http_client_object_responsehandler(php_http_client_object_t *obj, zval *this_ptr TSRMLS_DC);
+void php_http_client_options_set(zval *this_ptr, zval *opts TSRMLS_DC);
+void php_http_client_options_set_subr(zval *this_ptr, char *key, size_t len, zval *opts, int overwrite TSRMLS_DC);
+void php_http_client_options_get_subr(zval *this_ptr, char *key, size_t len, zval *return_value TSRMLS_DC);
 
 PHP_METHOD(HttpClient, __construct);
 PHP_METHOD(HttpClient, getObservers);
index e878e1e..194afc0 100644 (file)
@@ -242,7 +242,6 @@ static inline zval *get_option(HashTable *cache, HashTable *options, char *key,
 static STATUS set_options(php_http_client_t *h, HashTable *options)
 {
        zval *zoption;
-       int range_req = 0;
        php_http_client_curl_t *curl = h->ctx;
        CURL *ch = curl->handle;
        TSRMLS_FETCH_FROM_CTX(h->ts);
@@ -250,26 +249,26 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
        /* proxy */
        if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("proxyhost"), IS_STRING))) {
                curl_easy_setopt(ch, CURLOPT_PROXY, Z_STRVAL_P(zoption));
-               /* type */
-               if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("proxytype"), IS_LONG))) {
-                       curl_easy_setopt(ch, CURLOPT_PROXYTYPE, Z_LVAL_P(zoption));
-               }
-               /* port */
-               if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("proxyport"), IS_LONG))) {
-                       curl_easy_setopt(ch, CURLOPT_PROXYPORT, Z_LVAL_P(zoption));
-               }
-               /* user:pass */
-               if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("proxyauth"), IS_STRING)) && Z_STRLEN_P(zoption)) {
-                       curl_easy_setopt(ch, CURLOPT_PROXYUSERPWD, Z_STRVAL_P(zoption));
-               }
-               /* auth method */
-               if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("proxyauthtype"), IS_LONG))) {
-                       curl_easy_setopt(ch, CURLOPT_PROXYAUTH, Z_LVAL_P(zoption));
-               }
-               /* tunnel */
-               if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("proxytunnel"), IS_BOOL)) && Z_BVAL_P(zoption)) {
-                       curl_easy_setopt(ch, CURLOPT_HTTPPROXYTUNNEL, 1L);
-               }
+       }
+       /* type */
+       if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("proxytype"), IS_LONG))) {
+               curl_easy_setopt(ch, CURLOPT_PROXYTYPE, Z_LVAL_P(zoption));
+       }
+       /* port */
+       if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("proxyport"), IS_LONG))) {
+               curl_easy_setopt(ch, CURLOPT_PROXYPORT, Z_LVAL_P(zoption));
+       }
+       /* user:pass */
+       if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("proxyauth"), IS_STRING)) && Z_STRLEN_P(zoption)) {
+               curl_easy_setopt(ch, CURLOPT_PROXYUSERPWD, Z_STRVAL_P(zoption));
+       }
+       /* auth method */
+       if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("proxyauthtype"), IS_LONG))) {
+               curl_easy_setopt(ch, CURLOPT_PROXYAUTH, Z_LVAL_P(zoption));
+       }
+       /* tunnel */
+       if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("proxytunnel"), IS_BOOL)) && Z_BVAL_P(zoption)) {
+               curl_easy_setopt(ch, CURLOPT_HTTPPROXYTUNNEL, 1L);
        }
 #if PHP_HTTP_CURL_VERSION(7,19,4)
        if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("noproxy"), IS_STRING))) {
@@ -285,10 +284,6 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
                curl_easy_setopt(ch, CURLOPT_IPRESOLVE, Z_LVAL_P(zoption));
        }
 #if PHP_HTTP_CURL_VERSION(7,21,3)
-       if (curl->options.resolve) {
-               curl_slist_free_all(curl->options.resolve);
-               curl->options.resolve = NULL;
-       }
        if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("resolve"), IS_ARRAY))) {
                php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
                HashPosition pos;
@@ -301,6 +296,8 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
 
                        zval_ptr_dtor(&cpy);
                }
+
+               curl_easy_setopt(ch, CURLOPT_RESOLVE, curl->options.resolve);
        }
 #endif
 #if PHP_HTTP_CURL_VERSION(7,24,0)
@@ -338,24 +335,23 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
        /* outgoing interface */
        if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("interface"), IS_STRING))) {
                curl_easy_setopt(ch, CURLOPT_INTERFACE, Z_STRVAL_P(zoption));
+       }
+       if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("portrange"), IS_ARRAY))) {
+               zval **prs, **pre;
 
-               if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("portrange"), IS_ARRAY))) {
-                       zval **prs, **pre;
-
-                       zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
-                       if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &prs)) {
-                               zend_hash_move_forward(Z_ARRVAL_P(zoption));
-                               if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &pre)) {
-                                       zval *prs_cpy = php_http_ztyp(IS_LONG, *prs);
-                                       zval *pre_cpy = php_http_ztyp(IS_LONG, *pre);
+               zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
+               if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &prs)) {
+                       zend_hash_move_forward(Z_ARRVAL_P(zoption));
+                       if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &pre)) {
+                               zval *prs_cpy = php_http_ztyp(IS_LONG, *prs);
+                               zval *pre_cpy = php_http_ztyp(IS_LONG, *pre);
 
-                                       if (Z_LVAL_P(prs_cpy) && Z_LVAL_P(pre_cpy)) {
-                                               curl_easy_setopt(ch, CURLOPT_LOCALPORT, MIN(Z_LVAL_P(prs_cpy), Z_LVAL_P(pre_cpy)));
-                                               curl_easy_setopt(ch, CURLOPT_LOCALPORTRANGE, labs(Z_LVAL_P(prs_cpy)-Z_LVAL_P(pre_cpy))+1L);
-                                       }
-                                       zval_ptr_dtor(&prs_cpy);
-                                       zval_ptr_dtor(&pre_cpy);
+                               if (Z_LVAL_P(prs_cpy) && Z_LVAL_P(pre_cpy)) {
+                                       curl_easy_setopt(ch, CURLOPT_LOCALPORT, MIN(Z_LVAL_P(prs_cpy), Z_LVAL_P(pre_cpy)));
+                                       curl_easy_setopt(ch, CURLOPT_LOCALPORTRANGE, labs(Z_LVAL_P(prs_cpy)-Z_LVAL_P(pre_cpy))+1L);
                                }
+                               zval_ptr_dtor(&prs_cpy);
+                               zval_ptr_dtor(&pre_cpy);
                        }
                }
        }
@@ -394,8 +390,6 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
                        curl_easy_setopt(ch, CURLOPT_POST301, Z_BVAL_P(zoption) ? 1L : 0L);
 #endif
                }
-       } else {
-               curl->options.redirects = 0;
        }
 
        /* retries, defaults to 0 */
@@ -403,11 +397,7 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
                curl->options.retry.count = Z_LVAL_P(zoption);
                if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("retrydelay"), IS_DOUBLE))) {
                        curl->options.retry.delay = Z_DVAL_P(zoption);
-               } else {
-                       curl->options.retry.delay = 0;
                }
-       } else {
-               curl->options.retry.count = 0;
        }
 
        /* referer */
@@ -427,7 +417,7 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
 
        /* resume */
        if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("resume"), IS_LONG)) && (Z_LVAL_P(zoption) > 0)) {
-               range_req = 1;
+               curl->options.range_request = 1;
                curl_easy_setopt(ch, CURLOPT_RESUME_FROM, Z_LVAL_P(zoption));
        }
        /* or range of kind array(array(0,499), array(100,1499)) */
@@ -462,7 +452,7 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
                if (PHP_HTTP_BUFFER_LEN(&rs)) {
                        zval *cached_range;
 
-                       range_req = 1;
+                       curl->options.range_request = 1;
                        /* ditch last comma */
                        PHP_HTTP_BUFFER_VAL(&rs)[PHP_HTTP_BUFFER_LEN(&rs)-- -1] = '\0';
                        /* cache string */
@@ -473,18 +463,13 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
                }
        }
 
-       /* initialize headers */
-       if (curl->options.headers) {
-               curl_slist_free_all(curl->options.headers);
-               curl->options.headers = NULL;
-       }
        /* etag */
        if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("etag"), IS_STRING)) && Z_STRLEN_P(zoption)) {
                zend_bool is_quoted = !((Z_STRVAL_P(zoption)[0] != '"') || (Z_STRVAL_P(zoption)[Z_STRLEN_P(zoption)-1] != '"'));
                php_http_buffer_t header;
 
                php_http_buffer_init(&header);
-               php_http_buffer_appendf(&header, is_quoted?"%s: %s":"%s: \"%s\"", range_req?"If-Match":"If-None-Match", Z_STRVAL_P(zoption));
+               php_http_buffer_appendf(&header, is_quoted?"%s: %s":"%s: \"%s\"", curl->options.range_request?"If-Match":"If-None-Match", Z_STRVAL_P(zoption));
                php_http_buffer_fix(&header);
                curl->options.headers = curl_slist_append(curl->options.headers, PHP_HTTP_BUFFER_VAL(&header));
                php_http_buffer_dtor(&header);
@@ -503,7 +488,7 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
                        } else {
                                curl_easy_setopt(ch, CURLOPT_TIMEVALUE, (long) PHP_HTTP_G->env.request.time + Z_LVAL_P(zoption));
                        }
-                       curl_easy_setopt(ch, CURLOPT_TIMECONDITION, (long) (range_req ? CURL_TIMECOND_IFUNMODSINCE : CURL_TIMECOND_IFMODSINCE));
+                       curl_easy_setopt(ch, CURLOPT_TIMECONDITION, (long) (curl->options.range_request ? CURL_TIMECOND_IFUNMODSINCE : CURL_TIMECOND_IFMODSINCE));
                } else {
                        curl_easy_setopt(ch, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
                }
@@ -511,12 +496,11 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
 
        /* cookies, array('name' => 'value') */
        if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("cookies"), IS_ARRAY))) {
-               php_http_buffer_dtor(&curl->options.cookies);
                if (zend_hash_num_elements(Z_ARRVAL_P(zoption))) {
                        zval *urlenc_cookies = NULL;
                        /* check whether cookies should not be urlencoded; default is to urlencode them */
                        if ((!(urlenc_cookies = get_option(&curl->options.cache, options, ZEND_STRS("encodecookies"), IS_BOOL))) || Z_BVAL_P(urlenc_cookies)) {
-                               if (SUCCESS == php_http_url_encode_hash_ex(HASH_OF(zoption), &curl->options.cookies, ZEND_STRS(";"), ZEND_STRS("="), NULL, 0 TSRMLS_CC)) {
+                               if (SUCCESS == php_http_url_encode_hash_ex(HASH_OF(zoption), &curl->options.cookies, ZEND_STRL(";"), ZEND_STRL("="), NULL, 0 TSRMLS_CC)) {
                                        php_http_buffer_fix(&curl->options.cookies);
                                        curl_easy_setopt(ch, CURLOPT_COOKIE, curl->options.cookies.data);
                                }
@@ -891,7 +875,8 @@ static void php_http_client_curl_dtor(php_http_client_t *h)
 }
 static STATUS php_http_client_curl_reset(php_http_client_t *h)
 {
-       CURL *ch = ((php_http_client_curl_t *) h->ctx)->handle;
+       php_http_client_curl_t *curl = h->ctx;
+       CURL *ch = curl->handle;
        php_http_client_curl_storage_t *st;
 
        if ((st = get_storage(ch))) {
@@ -1019,6 +1004,23 @@ static STATUS php_http_client_curl_reset(php_http_client_t *h)
        curl_easy_setopt(ch, CURLOPT_UPLOAD, 0L);
        curl_easy_setopt(ch, CURLOPT_HTTPGET, 1L);
 
+#if PHP_HTTP_CURL_VERSION(7,21,3)
+       if (curl->options.resolve) {
+               curl_slist_free_all(curl->options.resolve);
+               curl->options.resolve = NULL;
+       }
+#endif
+       curl->options.retry.count = 0;
+       curl->options.retry.delay = 0;
+       curl->options.redirects = 0;
+
+       if (curl->options.headers) {
+               curl_slist_free_all(curl->options.headers);
+               curl->options.headers = NULL;
+       }
+
+       php_http_buffer_reset(&curl->options.cookies);
+
        return SUCCESS;
 }
 
index 1b1f24b..b22e266 100644 (file)
@@ -28,6 +28,7 @@ typedef struct php_http_client_curl {
                php_http_buffer_t cookies;
 
                long redirects;
+               unsigned range_request:1;
 
                struct {
                        uint count;
index 697dbb5..3059444 100644 (file)
@@ -39,6 +39,43 @@ PHP_HTTP_BEGIN_ARGS(addQuery, 1)
        PHP_HTTP_ARG_VAL(query_data, 0)
 PHP_HTTP_END_ARGS;
 
+PHP_HTTP_EMPTY_ARGS(getOptions);
+PHP_HTTP_BEGIN_ARGS(setOptions, 0)
+       PHP_HTTP_ARG_ARR(options, 1, 0)
+PHP_HTTP_END_ARGS;
+
+PHP_HTTP_EMPTY_ARGS(getSslOptions);
+PHP_HTTP_BEGIN_ARGS(setSslOptions, 0)
+       PHP_HTTP_ARG_ARR(ssl_options, 1, 0)
+PHP_HTTP_END_ARGS;
+
+PHP_HTTP_BEGIN_ARGS(addSslOptions, 0)
+       PHP_HTTP_ARG_ARR(ssl_options, 1, 0)
+PHP_HTTP_END_ARGS;
+
+
+static zend_class_entry *php_http_client_request_class_entry;
+
+zend_class_entry * php_http_client_request_get_class_entry(void)
+{
+       return php_http_client_request_class_entry;
+}
+
+static zend_function_entry php_http_client_request_method_entry[] = {
+       PHP_HTTP_CLIENT_REQUEST_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
+       PHP_HTTP_CLIENT_REQUEST_ME(getQuery, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_REQUEST_ME(setQuery, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_REQUEST_ME(addQuery, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_REQUEST_ME(getContentType, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_REQUEST_ME(setContentType, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_REQUEST_ME(setOptions, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_REQUEST_ME(getOptions, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_REQUEST_ME(setSslOptions, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_REQUEST_ME(getSslOptions, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_REQUEST_ME(addSslOptions, ZEND_ACC_PUBLIC)
+       EMPTY_FUNCTION_ENTRY
+};
+
 
 PHP_METHOD(HttpClientRequest, __construct)
 {
@@ -208,22 +245,60 @@ PHP_METHOD(HttpClientRequest, addQuery)
        RETVAL_ZVAL(getThis(), 1, 0);
 }
 
+PHP_METHOD(HttpClientRequest, setOptions)
+{
+       zval *opts = NULL;
 
-zend_class_entry *php_http_client_request_class_entry;
-zend_function_entry php_http_client_request_method_entry[] = {
-       PHP_HTTP_CLIENT_REQUEST_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
-       PHP_HTTP_CLIENT_REQUEST_ME(getQuery, ZEND_ACC_PUBLIC)
-       PHP_HTTP_CLIENT_REQUEST_ME(setQuery, ZEND_ACC_PUBLIC)
-       PHP_HTTP_CLIENT_REQUEST_ME(addQuery, ZEND_ACC_PUBLIC)
-       PHP_HTTP_CLIENT_REQUEST_ME(getContentType, ZEND_ACC_PUBLIC)
-       PHP_HTTP_CLIENT_REQUEST_ME(setContentType, ZEND_ACC_PUBLIC)
-       EMPTY_FUNCTION_ENTRY
-};
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
+               php_http_client_options_set(getThis(), opts TSRMLS_CC);
+
+               RETVAL_ZVAL(getThis(), 1, 0);
+       }
+}
+
+PHP_METHOD(HttpClientRequest, getOptions)
+{
+       if (SUCCESS == zend_parse_parameters_none()) {
+               RETURN_PROP(php_http_client_request_class_entry, "options");
+       }
+       RETURN_FALSE;
+}
+
+PHP_METHOD(HttpClientRequest, setSslOptions)
+{
+       zval *opts = NULL;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
+               php_http_client_options_set_subr(getThis(), ZEND_STRS("ssl"), opts, 1 TSRMLS_CC);
+
+               RETVAL_ZVAL(getThis(), 1, 0);
+       }
+}
+
+PHP_METHOD(HttpClientRequest, addSslOptions)
+{
+       zval *opts = NULL;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
+               php_http_client_options_set_subr(getThis(), ZEND_STRS("ssl"), opts, 0 TSRMLS_CC);
+
+               RETVAL_ZVAL(getThis(), 1, 0);
+       }
+}
+
+PHP_METHOD(HttpClientRequest, getSslOptions)
+{
+       if (SUCCESS == zend_parse_parameters_none()) {
+               php_http_client_options_get_subr(getThis(), ZEND_STRS("ssl"), return_value TSRMLS_CC);
+       }
+}
 
 PHP_MINIT_FUNCTION(http_client_request)
 {
        PHP_HTTP_REGISTER_CLASS(http\\Client, Request, http_client_request, php_http_message_class_entry, 0);
 
+       zend_declare_property_null(php_http_client_request_class_entry, ZEND_STRL("options"), ZEND_ACC_PROTECTED TSRMLS_CC);
+
        return SUCCESS;
 }
 
index 36151d7..2087f4d 100644 (file)
@@ -13,8 +13,7 @@
 #ifndef PHP_HTTP_CLIENT_REQUEST_H
 #define PHP_HTTP_CLIENT_REQUEST_H
 
-extern zend_class_entry *php_http_client_request_class_entry;
-extern zend_function_entry php_http_client_request_method_entry[];
+zend_class_entry *php_http_client_request_get_class_entry(void);
 
 PHP_METHOD(HttpClientRequest, __construct);
 PHP_METHOD(HttpClientRequest, setContentType);
@@ -22,6 +21,11 @@ PHP_METHOD(HttpClientRequest, getContentType);
 PHP_METHOD(HttpClientRequest, setQuery);
 PHP_METHOD(HttpClientRequest, getQuery);
 PHP_METHOD(HttpClientRequest, addQuery);
+PHP_METHOD(HttpClientRequest, setOptions);
+PHP_METHOD(HttpClientRequest, getOptions);
+PHP_METHOD(HttpClientRequest, addSslOptions);
+PHP_METHOD(HttpClientRequest, setSslOptions);
+PHP_METHOD(HttpClientRequest, getSslOptions);
 
 PHP_MINIT_FUNCTION(http_client_request);