- hopefully some more appropriate fixes for the zval separation issues
authorMichael Wallner <mike@php.net>
Wed, 28 Dec 2005 13:45:38 +0000 (13:45 +0000)
committerMichael Wallner <mike@php.net>
Wed, 28 Dec 2005 13:45:38 +0000 (13:45 +0000)
http_message_object.c
http_request_api.c
http_request_object.c
http_url_api.c
php_http_api.h
php_http_request_object.h
tests/HttpRequestPool_002.phpt
tests/HttpRequest_001.phpt
tests/HttpRequest_003.phpt

index fa828229b7afd6b6d3b531855674863b35d7ae55..aa63cab0b47fc8b98c325a6371a313606912954d 100644 (file)
@@ -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)
index d96c1808a9fb4d68b4c02ea4c8230f7786095e97..f7d308997f653d71275938f494cbb57bbd758d23 100644 (file)
@@ -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;
 }
 /* }}} */
 
index 8ff7b25ed21fcb98874fa877f5f23d3572e80fd6..4b85676f3e47a5fbec98c2f2964795d9aac6c600 100644 (file)
@@ -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)) {
index 2fde306a74154dee0f3ecdedb6b2fd08967b80ea..7bacffc3e73e26120c8ddbc58e7f52ec1df63eb4 100644 (file)
@@ -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);
        }
index 9f8eda9537900929c8313eb28fc7b8e45a97a966..628837c90c6a9941daed926ab0e1d849d904086f 100644 (file)
@@ -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
 
 /*
index 84f94d68f01b6b969360919fae878bed4a53df31..3433d51f95c8cb3009ecc740c671b6f1026bf5fa 100644 (file)
@@ -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);
index 26b11593caec8b869011a4fcd96f925ad5beb51a..8195dadc67885fa17185ae4c3e93a14b45b3843f 100644 (file)
@@ -47,5 +47,5 @@ echo "\nDone\n";
 ?>
 --EXPECTREGEX--
 .+TEST
-\.+=200=\.+=200=\.+=200=\.+=200=
+\.*=200=\.*=200=\.*=200=\.*=200=
 Done
index 0ff1b5baa881e617d25eb5fc27937b69e646de47..abe65065417eb4a06291abc39e1abcc867b9e208 100644 (file)
@@ -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
         )
 
 )
index bed6735263b4031c89820bb27497fdf4487c493e..3ce4fcb65324607c0866f8b1523fe88c8ad79f7b 100644 (file)
@@ -4,18 +4,24 @@ HttpRequest SSL
 <?php
 include 'skip.inc';
 checkmin(5);
-checkcls('HttpRequest');
 checkurl('arweb.info');
+skipif(!http_support(HTTP_SUPPORT_SSLREQUESTS), 'need ssl-request support')
 ?>
 --FILE--
 <?php
 echo "-TEST\n";
+$o = array('redirect' => '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"
+  }
+}
+