From 759c822dcd99fdf733399a5ed92dbea382ddc474 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Fri, 30 Mar 2012 11:54:57 +0000 Subject: [PATCH] let the request be able to carry client options --- php_http_client.c | 173 ++++++++++++++++++++------------------ php_http_client.h | 5 +- php_http_client_curl.c | 118 +++++++++++++------------- php_http_client_curl.h | 1 + php_http_client_request.c | 95 ++++++++++++++++++--- php_http_client_request.h | 8 +- 6 files changed, 244 insertions(+), 156 deletions(-) diff --git a/php_http_client.c b/php_http_client.c index 4bf7d88..06e90ba 100644 --- a/php_http_client.c +++ b/php_http_client.c @@ -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); diff --git a/php_http_client.h b/php_http_client.h index e642870..b5aeb57 100644 --- a/php_http_client.h +++ b/php_http_client.h @@ -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); diff --git a/php_http_client_curl.c b/php_http_client_curl.c index e878e1e..194afc0 100644 --- a/php_http_client_curl.c +++ b/php_http_client_curl.c @@ -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; } diff --git a/php_http_client_curl.h b/php_http_client_curl.h index 1b1f24b..b22e266 100644 --- a/php_http_client_curl.h +++ b/php_http_client_curl.h @@ -28,6 +28,7 @@ typedef struct php_http_client_curl { php_http_buffer_t cookies; long redirects; + unsigned range_request:1; struct { uint count; diff --git a/php_http_client_request.c b/php_http_client_request.c index 697dbb5..3059444 100644 --- a/php_http_client_request.c +++ b/php_http_client_request.c @@ -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; } diff --git a/php_http_client_request.h b/php_http_client_request.h index 36151d7..2087f4d 100644 --- a/php_http_client_request.h +++ b/php_http_client_request.h @@ -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); -- 2.30.2