From 960586b99568624a207faa24fe56233582b6d0dc Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 28 Dec 2005 13:45:38 +0000 Subject: [PATCH] - hopefully some more appropriate fixes for the zval separation issues --- http_message_object.c | 7 +-- http_request_api.c | 76 +++++++++++++---------------- http_request_object.c | 88 +++++++++++++++------------------- http_url_api.c | 10 +--- php_http_api.h | 23 +++++++++ php_http_request_object.h | 1 + tests/HttpRequestPool_002.phpt | 2 +- tests/HttpRequest_001.phpt | 4 +- tests/HttpRequest_003.phpt | 31 +++++++++++- 9 files changed, 133 insertions(+), 109 deletions(-) diff --git a/http_message_object.c b/http_message_object.c index fa82822..aa63cab 100644 --- a/http_message_object.c +++ b/http_message_object.c @@ -368,10 +368,7 @@ static void _http_message_object_write_prop(zval *object, zval *member, zval *va } #endif - ALLOC_ZVAL(cpy); - *cpy = *value; - zval_copy_ctor(cpy); - INIT_PZVAL(cpy); + cpy = zval_copy(Z_TYPE_P(value), value); #ifdef WONKY switch (h) @@ -456,7 +453,7 @@ static void _http_message_object_write_prop(zval *object, zval *member, zval *va #endif break; } - zval_ptr_dtor(&cpy); + zval_free(&cpy); } static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC) diff --git a/http_request_api.c b/http_request_api.c index d96c180..f7d3089 100644 --- a/http_request_api.c +++ b/http_request_api.c @@ -170,28 +170,21 @@ PHP_MSHUTDOWN_FUNCTION(http_request) #define HTTP_CURL_OPT_SSL_STRING_(keyname,obdc ) HTTP_CURL_OPT_STRING_EX(keyname, SSL_##keyname, obdc) #define HTTP_CURL_OPT_STRING_EX(keyname, optname, obdc) \ if (!strcasecmp(key, #keyname)) { \ - int ok = 1; \ - zval *orig = *param; \ - convert_to_string_ex(param); \ + zval *copy = http_request_option_cache(request, #keyname, zval_copy(IS_STRING, *param)); \ if (obdc) { \ - HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_PP(param), ok = 0); \ + HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(copy), return FAILURE); \ } \ + HTTP_CURL_OPT(optname, Z_STRVAL_P(copy)); \ key = NULL; \ - if (ok) { \ - HTTP_CURL_OPT(optname, Z_STRVAL_PP(param)); \ - if (orig != *param) zval_ptr_dtor(param); \ - continue; \ - } \ - if (orig != *param) zval_ptr_dtor(param); \ - return FAILURE; \ + continue; \ } #define HTTP_CURL_OPT_LONG(keyname) HTTP_OPT_SSL_LONG_EX(keyname, keyname) #define HTTP_CURL_OPT_SSL_LONG(keyname) HTTP_CURL_OPT_LONG_EX(keyname, SSL##keyname) #define HTTP_CURL_OPT_SSL_LONG_(keyname) HTTP_CURL_OPT_LONG_EX(keyname, SSL_##keyname) #define HTTP_CURL_OPT_LONG_EX(keyname, optname) \ if (!strcasecmp(key, #keyname)) { \ - convert_to_long(*param); \ - HTTP_CURL_OPT(optname, Z_LVAL_PP(param)); \ + zval *copy = http_request_option_cache(request, #keyname, zval_copy(IS_LONG, *param)); \ + HTTP_CURL_OPT(optname, Z_LVAL_P(copy)); \ key = NULL; \ continue; \ } @@ -201,6 +194,9 @@ PHP_MSHUTDOWN_FUNCTION(http_request) #define http_request_option(r, o, k, t) _http_request_option_ex((r), (o), (k), sizeof(k), (t) TSRMLS_CC) #define http_request_option_ex(r, o, k, l, t) _http_request_option_ex((r), (o), (k), (l), (t) TSRMLS_CC) static inline zval *_http_request_option_ex(http_request *request, HashTable *options, char *key, size_t keylen, int type TSRMLS_DC); +#define http_request_option_cache(r, k, z) _http_request_option_cache_ex((r), (k), sizeof(k), 0, (z) TSRMLS_CC) +#define http_request_option_cache_ex(r, k, kl, h, z) _http_request_option_cache_ex((r), (k), (kl), (h), (z) TSRMLS_CC) +static inline zval *_http_request_option_cache_ex(http_request *r, char *key, size_t keylen, ulong h, zval *opt TSRMLS_DC); static size_t http_curl_read_callback(void *, size_t, size_t, void *); static int http_curl_progress_callback(void *, double, double, double, double); @@ -469,16 +465,12 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti zval **header_val; if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_P(zoption), (void **) &header_val, &pos)) { char header[1024] = {0}; - zval val; - - val = **header_val; - zval_copy_ctor(&val); - INIT_PZVAL(&val); - convert_to_string(&val); - snprintf(header, 1023, "%s: %s", header_key, Z_STRVAL(val)); + ZVAL_ADDREF(*header_val); + convert_to_string_ex(header_val); + snprintf(header, 1023, "%s: %s", header_key, Z_STRVAL_PP(header_val)); request->_cache.headers = curl_slist_append(request->_cache.headers, header); - zval_dtor(&val); + zval_ptr_dtor(header_val); } /* reset */ @@ -822,6 +814,8 @@ static inline zval *_http_request_option_ex(http_request *r, HashTable *options, zval **zoption; #ifdef ZEND_ENGINE_2 ulong h = zend_get_hash_value(key, keylen); +#else + ulong h = 0; #endif if (!options || @@ -833,34 +827,32 @@ static inline zval *_http_request_option_ex(http_request *r, HashTable *options, ) { return NULL; } + + return http_request_option_cache_ex(r, key, keylen, h, zval_copy(type, *zoption)); +} +/* }}} */ - if (Z_TYPE_PP(zoption) != type) { - switch (type) - { - case IS_BOOL: convert_to_boolean_ex(zoption); break; - case IS_LONG: convert_to_long_ex(zoption); break; - case IS_DOUBLE: convert_to_double_ex(zoption); break; - case IS_STRING: convert_to_string_ex(zoption); break; - case IS_ARRAY: convert_to_array_ex(zoption); break; - case IS_OBJECT: convert_to_object_ex(zoption); break; - default: - break; - } - } +/* {{{ static inline zval *http_request_option_cache(http_request *, char *key, zval *) */ +static inline zval *_http_request_option_cache_ex(http_request *r, char *key, size_t keylen, ulong h, zval *opt TSRMLS_DC) +{ + ZVAL_ADDREF(opt); - /* cache strings */ - if (type == IS_STRING) { - ZVAL_ADDREF(*zoption); #ifdef ZEND_ENGINE_2 - _zend_hash_quick_add_or_update(&r->_cache.options, key, keylen, h, zoption, sizeof(zval *), NULL, + if (h) { + _zend_hash_quick_add_or_update(&r->_cache.options, key, keylen, h, &opt, sizeof(zval *), NULL, zend_hash_quick_exists(&r->_cache.options, key, keylen, h)?HASH_UPDATE:HASH_ADD ZEND_FILE_LINE_CC); -#else - zend_hash_add_or_update(&r->_cache.options, key, keylen, zoption, sizeof(zval *), NULL, - zend_hash_exists(&r->_cache.options, key, keylen)?HASH_UPDATE:HASH_ADD); + } + else #endif + { + if (zend_hash_exists(&r->_cache.options, key, keylen)) { + zend_hash_update(&r->_cache.options, key, keylen, &opt, sizeof(zval *), NULL); + } else { + zend_hash_add(&r->_cache.options, key, keylen, &opt, sizeof(zval *), NULL); + } } - return *zoption; + return opt; } /* }}} */ diff --git a/http_request_object.c b/http_request_object.c index 8ff7b25..4b85676 100644 --- a/http_request_object.c +++ b/http_request_object.c @@ -53,6 +53,10 @@ HTTP_BEGIN_ARGS(setSslOptions, 0, 0) HTTP_ARG_VAL(ssl_options, 0) HTTP_END_ARGS; +HTTP_BEGIN_ARGS(addSslOptions, 0, 0) + HTTP_ARG_VAL(ssl_optins, 0) +HTTP_END_ARGS; + HTTP_EMPTY_ARGS(getHeaders, 0); HTTP_BEGIN_ARGS(setHeaders, 0, 0) HTTP_ARG_VAL(headers, 0) @@ -219,6 +223,7 @@ zend_function_entry http_request_object_fe[] = { HTTP_REQUEST_ME(getOptions, ZEND_ACC_PUBLIC) HTTP_REQUEST_ME(setSslOptions, ZEND_ACC_PUBLIC) HTTP_REQUEST_ME(getSslOptions, ZEND_ACC_PUBLIC) + HTTP_REQUEST_ME(addSslOptions, ZEND_ACC_PUBLIC) HTTP_REQUEST_ME(addHeaders, ZEND_ACC_PUBLIC) HTTP_REQUEST_ME(getHeaders, ZEND_ACC_PUBLIC) @@ -698,7 +703,7 @@ PHP_METHOD(HttpRequest, setOptions) char *key = NULL; ulong idx = 0; HashPosition pos; - zval *opts = NULL, *old_opts, *new_opts, **opt; + zval *opts = NULL, *old_opts, *new_opts, *add_opts, **opt; getObject(http_request_object, obj); if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) { @@ -712,59 +717,39 @@ PHP_METHOD(HttpRequest, setOptions) SET_PROP(obj, options, new_opts); RETURN_TRUE; } - - old_opts = GET_PROP(obj, options); - if (Z_TYPE_P(old_opts) == IS_ARRAY) { - array_copy(old_opts, new_opts); - } + 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, idx, opt) { if (key) { if (!strcmp(key, "headers")) { - zval **headers; - if (SUCCESS == zend_hash_find(Z_ARRVAL_P(new_opts), "headers", sizeof("headers"), (void **) &headers)) { - convert_to_array_ex(opt); - convert_to_array(*headers); - array_merge(*opt, *headers); - continue; - } + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addheaders", NULL, *opt); } else if (!strcmp(key, "cookies")) { - zval **cookies; - if (SUCCESS == zend_hash_find(Z_ARRVAL_P(new_opts), "cookies", sizeof("cookies"), (void **) &cookies)) { - convert_to_array_ex(opt); - convert_to_array(*cookies); - array_merge(*opt, *cookies); - continue; - } + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addcookies", NULL, *opt); } else if (!strcmp(key, "ssl")) { - zval **ssl; - if (SUCCESS == zend_hash_find(Z_ARRVAL_P(new_opts), "ssl", sizeof("ssl"), (void **) &ssl)) { - convert_to_array_ex(opt); - convert_to_array(*ssl); - array_merge(*opt, *ssl); - continue; - } - } else if ((Z_TYPE_PP(opt) == IS_STRING) && ((!strcasecmp(key, "url")) || (!strcasecmp(key, "uri")))) { - UPD_STRL(obj, url, Z_STRVAL_PP(opt), Z_STRLEN_PP(opt)); - continue; + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addssloptions", NULL, *opt); + } else if ((!strcasecmp(key, "url")) || (!strcasecmp(key, "uri"))) { + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "seturl", NULL, *opt); } else if (!strcmp(key, "method")) { - if (Z_TYPE_PP(opt) != IS_LONG) { - convert_to_long_ex(opt); - } - UPD_PROP(obj, long, method, Z_LVAL_PP(opt)); - continue; + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmethod", NULL, *opt); + } else { + ZVAL_ADDREF(*opt); + add_assoc_zval(add_opts, key, *opt); } - - ZVAL_ADDREF(*opt); - add_assoc_zval(new_opts, key, *opt); - /* reset */ key = NULL; } } + + old_opts = GET_PROP(obj, options); + if (Z_TYPE_P(old_opts) == IS_ARRAY) { + array_copy(old_opts, new_opts); + } + array_merge(add_opts, new_opts); SET_PROP(obj, options, new_opts); zval_ptr_dtor(&new_opts); + zval_ptr_dtor(&add_opts); RETURN_TRUE; } @@ -1274,18 +1259,13 @@ PHP_METHOD(HttpRequest, addRawPostData) } if (data_len) { - zval *data, *zdata = GET_PROP(obj, rawPostData); + zval *data = zval_copy(IS_STRING, GET_PROP(obj, rawPostData)); - ALLOC_ZVAL(data); - *data = *zdata; - zval_copy_ctor(data); - INIT_PZVAL(data); - convert_to_string(data); Z_STRVAL_P(data) = erealloc(Z_STRVAL_P(data), (Z_STRLEN_P(data) += data_len) + 1); Z_STRVAL_P(data)[Z_STRLEN_P(data)] = '\0'; memcpy(Z_STRVAL_P(data) + Z_STRLEN_P(data) - data_len, raw_data, data_len); SET_PROP(obj, rawPostData, data); - zval_ptr_dtor(&data); + zval_free(&data); } RETURN_TRUE; @@ -1506,8 +1486,9 @@ PHP_METHOD(HttpRequest, getResponseHeader) } data = GET_PROP(obj, responseData); - if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) { - convert_to_array(*headers); + if ( (Z_TYPE_P(data) == IS_ARRAY) && + (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) && + (Z_TYPE_PP(headers) == IS_ARRAY)) { if (!header_len || !header_name) { RETVAL_ZVAL(*headers, 1, 0); } else if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(headers), pretty_key(header_name, header_len, 1, 1), header_len + 1, (void **) &header)) { @@ -1552,7 +1533,9 @@ PHP_METHOD(HttpRequest, getResponseCookie) array_init(return_value); data = GET_PROP(obj, responseData); - if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) { + if ( (Z_TYPE_P(data) == IS_ARRAY) && + (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) && + (Z_TYPE_PP(headers) == IS_ARRAY)) { ulong idx = 0; char *key = NULL; zval **header = NULL; @@ -1645,7 +1628,8 @@ PHP_METHOD(HttpRequest, getResponseBody) getObject(http_request_object, obj); zval *data = GET_PROP(obj, responseData); - if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body)) { + if ( (Z_TYPE_P(data) == IS_ARRAY) && + (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body))) { RETURN_ZVAL(*body, 1, 0); } else { RETURN_FALSE; @@ -1705,6 +1689,10 @@ PHP_METHOD(HttpRequest, getResponseInfo) } info = GET_PROP(obj, responseInfo); + + if (Z_TYPE_P(info) != IS_ARRAY) { + RETURN_FALSE; + } if (info_len && info_name) { if (SUCCESS == zend_hash_find(Z_ARRVAL_P(info), pretty_key(info_name, info_len, 0, 0), info_len + 1, (void **) &infop)) { diff --git a/http_url_api.c b/http_url_api.c index 2fde306..7bacffc 100644 --- a/http_url_api.c +++ b/http_url_api.c @@ -299,13 +299,7 @@ PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, c return FAILURE; } } else { - zval *val; - - ALLOC_ZVAL(val); - *val = **data; - INIT_PZVAL(val); - zval_copy_ctor(val); - convert_to_string(val); + zval *val = zval_copy(IS_STRING, *data); if (PHPSTR_LEN(str)) { phpstr_append(str, arg_sep, arg_sep_len); @@ -322,7 +316,7 @@ PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, c efree(encoded_val); } - zval_ptr_dtor(&val); + zval_free(&val); } phpstr_dtor(&new_prefix); } diff --git a/php_http_api.h b/php_http_api.h index 9f8eda9..628837c 100644 --- a/php_http_api.h +++ b/php_http_api.h @@ -192,6 +192,29 @@ static inline zval *_convert_to_type_ex(int type, zval *z, zval **p) return z; } +#define zval_copy(t, z) _zval_copy((t), (z) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) +static inline zval *_zval_copy(int type, zval *z ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + zval *copy; + + copy = emalloc_rel(sizeof(zval)); + *copy = *z; + zval_copy_ctor(copy); + convert_to_type(type, copy); + copy->refcount = 0; + copy->is_ref = 0; + + return copy; +} + +#define zval_free(z) _zval_free(z) +static inline void _zval_free(zval **z) +{ + zval_dtor(*z); + FREE_ZVAL(*z); + *z = NULL; +} + #endif /* diff --git a/php_http_request_object.h b/php_http_request_object.h index 84f94d6..3433d51 100644 --- a/php_http_request_object.h +++ b/php_http_request_object.h @@ -48,6 +48,7 @@ extern STATUS _http_request_object_responsehandler(http_request_object *obj, zva PHP_METHOD(HttpRequest, __construct); PHP_METHOD(HttpRequest, setOptions); PHP_METHOD(HttpRequest, getOptions); +PHP_METHOD(HttpRequest, addSslOptions); PHP_METHOD(HttpRequest, setSslOptions); PHP_METHOD(HttpRequest, getSslOptions); PHP_METHOD(HttpRequest, addHeaders); diff --git a/tests/HttpRequestPool_002.phpt b/tests/HttpRequestPool_002.phpt index 26b1159..8195dad 100644 --- a/tests/HttpRequestPool_002.phpt +++ b/tests/HttpRequestPool_002.phpt @@ -47,5 +47,5 @@ echo "\nDone\n"; ?> --EXPECTREGEX-- .+TEST -\.+=200=\.+=200=\.+=200=\.+=200= +\.*=200=\.*=200=\.*=200=\.*=200= Done diff --git a/tests/HttpRequest_001.phpt b/tests/HttpRequest_001.phpt index 0ff1b5b..abe6506 100644 --- a/tests/HttpRequest_001.phpt +++ b/tests/HttpRequest_001.phpt @@ -27,24 +27,24 @@ Array ( [0] => Array ( - [redirect] => 11 [headers] => Array ( [X-Foo] => Bar [X-Bar] => Foo ) + [redirect] => 11 ) [1] => Array ( - [redirect] => 99 [headers] => Array ( [X-Bar] => Foo [X-Foo] => Bar ) + [redirect] => 99 ) ) diff --git a/tests/HttpRequest_003.phpt b/tests/HttpRequest_003.phpt index bed6735..3ce4fcb 100644 --- a/tests/HttpRequest_003.phpt +++ b/tests/HttpRequest_003.phpt @@ -4,18 +4,24 @@ HttpRequest SSL --FILE-- '3', 'ssl' => array('version' => '3', 'verifyhost' => '1')); $r = new HttpRequest('https://ssl.arweb.info/iworks/data.txt'); +$r->setOptions($o); $r->send(); var_dump($r->getResponseBody()); var_dump(is_object($r->getResponseMessage())); var_dump(is_object($r->getResponseMessage())); var_dump(is_object($r->getResponseMessage())); +var_dump($o); +$r->setOptions($o); +$r->send(); +var_dump($o); ?> --EXPECTF-- %sTEST @@ -23,3 +29,26 @@ string(10) "1234567890" bool(true) bool(true) bool(true) +array(2) { + ["redirect"]=> + string(1) "3" + ["ssl"]=> + array(2) { + ["version"]=> + string(1) "3" + ["verifyhost"]=> + string(1) "1" + } +} +array(2) { + ["redirect"]=> + string(1) "3" + ["ssl"]=> + array(2) { + ["version"]=> + string(1) "3" + ["verifyhost"]=> + string(1) "1" + } +} + -- 2.30.2