- improve internal array handling
authorMichael Wallner <mike@php.net>
Mon, 20 Nov 2006 11:15:06 +0000 (11:15 +0000)
committerMichael Wallner <mike@php.net>
Mon, 20 Nov 2006 11:15:06 +0000 (11:15 +0000)
- fix HttpMessage's header handling

13 files changed:
http_api.c
http_cookie_api.c
http_headers_api.c
http_message_api.c
http_message_object.c
http_querystring_api.c
http_request_api.c
http_request_body_api.c
http_request_object.c
http_url_api.c
php_http_api.h
php_http_request_int.h
php_http_std_defs.h

index f8f93e1..b77dd19 100644 (file)
@@ -584,6 +584,70 @@ failure:
 }
 /* }}} */
 
+/* {{{ array_join */
+int apply_array_append_func(void *pDest, int num_args, va_list args, zend_hash_key *hash_key)
+{
+       int flags;
+       char *key = NULL;
+       HashTable *dst;
+       zval **data = NULL, **value = (zval **) pDest;
+       
+       dst = va_arg(args, HashTable *);
+       flags = va_arg(args, int);
+       
+       if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) {
+               if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
+                       key = pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
+                       zend_hash_find(dst, key, hash_key->nKeyLength, (void *) &data);
+               } else {
+                       zend_hash_quick_find(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &data);
+               }
+               
+               ZVAL_ADDREF(*value);
+               if (data) {
+                       if (Z_TYPE_PP(data) != IS_ARRAY) {
+                               convert_to_array(*data);
+                       }
+                       add_next_index_zval(*data, *value);
+               } else if (key) {
+                       zend_hash_add(dst, key, hash_key->nKeyLength, value, sizeof(zval *), NULL);
+               } else {
+                       zend_hash_quick_add(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, value, sizeof(zval *), NULL);
+               }
+               
+               if (key) {
+                       efree(key);
+               }
+       }
+       
+       return ZEND_HASH_APPLY_KEEP;
+}
+
+int apply_array_merge_func(void *pDest, int num_args, va_list args, zend_hash_key *hash_key)
+{
+       int flags;
+       char *key = NULL;
+       HashTable *dst;
+       zval **value = (zval **) pDest;
+       
+       dst = va_arg(args, HashTable *);
+       flags = va_arg(args, int);
+       
+       if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) {
+               ZVAL_ADDREF(*value);
+               if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
+                       key = pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
+                       zend_hash_update(dst, key, hash_key->nKeyLength, (void *) value, sizeof(zval *), NULL);
+                       efree(key);
+               } else {
+                       zend_hash_quick_update(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) value, sizeof(zval *), NULL);
+               }
+       }
+       
+       return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
 /*
  * Local variables:
  * tab-width: 4
index b487e20..360b793 100644 (file)
@@ -316,17 +316,14 @@ PHP_HTTP_API void _http_cookie_list_tostring(http_cookie_list *list, char **str,
 {
        phpstr buf;
        zval **val;
-       ulong idx = 0;
-       uint keylen = 0;
-       char *key = NULL;
+       HashKey key = initHashKey(0);
        HashPosition pos;
        
        phpstr_init(&buf);
        
-       FOREACH_HASH_KEYLENVAL(pos, &list->cookies, key, keylen, idx, val) {
-               if (key && keylen) {
-                       append_encoded(&buf, key, keylen-1, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
-                       key = NULL;
+       FOREACH_HASH_KEYVAL(pos, &list->cookies, key, val) {
+               if (key.type == HASH_KEY_IS_STRING && key.len) {
+                       append_encoded(&buf, key.str, key.len-1, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
                }
        }
        
@@ -342,10 +339,9 @@ PHP_HTTP_API void _http_cookie_list_tostring(http_cookie_list *list, char **str,
                efree(date);
        }
        
-       FOREACH_HASH_KEYLENVAL(pos, &list->extras, key, keylen, idx, val) {
-               if (key && keylen) {
-                       append_encoded(&buf, key, keylen-1, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
-                       key = NULL;
+       FOREACH_HASH_KEYVAL(pos, &list->extras, key, val) {
+               if (key.type == HASH_KEY_IS_STRING && key.len) {
+                       append_encoded(&buf, key.str, key.len-1, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
                }
        }
        
index 9fd3b75..ef5099f 100644 (file)
@@ -423,9 +423,7 @@ PHP_HTTP_API STATUS _http_parse_headers_ex(const char *header, HashTable *header
 /* {{{ void http_get_request_headers(HashTable *) */
 PHP_HTTP_API void _http_get_request_headers(HashTable *headers TSRMLS_DC)
 {
-       char *key = NULL;
-       ulong idx = 0;
-       uint keylen = 0;
+       HashKey key = initHashKey(0);
        zval **hsv, **header;
        HashPosition pos;
        
@@ -438,17 +436,16 @@ PHP_HTTP_API void _http_get_request_headers(HashTable *headers TSRMLS_DC)
 #endif
                
                if (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv) && Z_TYPE_PP(hsv) == IS_ARRAY) {
-                       FOREACH_KEYLEN(pos, *hsv, key, keylen, idx) {
-                               if (key && keylen > 6 && !strncmp(key, "HTTP_", 5)) {
-                                       keylen -= 6;
-                                       key = pretty_key(estrndup(key + 5, keylen), keylen, 1, 1);
+                       FOREACH_KEY(pos, *hsv, key) {
+                               if (key.type == HASH_KEY_IS_STRING && key.len > 6 && !strncmp(key.str, "HTTP_", 5)) {
+                                       key.len -= 5;
+                                       key.str = pretty_key(estrndup(key.str + 5, key.len - 1), key.len - 1, 1, 1);
                                        
                                        zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv), (void *) &header, &pos);
                                        ZVAL_ADDREF(*header);
-                                       zend_hash_add(HTTP_G->request.headers, key, keylen + 1, (void *) header, sizeof(zval *), NULL);
+                                       zend_hash_add(HTTP_G->request.headers, key.str, key.len, (void *) header, sizeof(zval *), NULL);
                                        
-                                       STR_SET(key, NULL)
-                                       keylen = 0;
+                                       efree(key.str);
                                }
                        }
                }
index 4da4e88..85b2b00 100644 (file)
@@ -308,9 +308,9 @@ PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, const char
 PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_t *length)
 {
        phpstr str;
-       char *key, *data;
-       ulong idx;
+       HashKey key = initHashKey(0);
        zval **header;
+       char *data;
        HashPosition pos1;
 
        phpstr_init_ex(&str, 4096, 0);
@@ -336,24 +336,22 @@ PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_
                        break;
        }
 
-       FOREACH_HASH_KEYVAL(pos1, &msg->hdrs, key, idx, header) {
-               if (key) {
+       FOREACH_HASH_KEYVAL(pos1, &msg->hdrs, key, header) {
+               if (key.type == HASH_KEY_IS_STRING) {
                        HashPosition pos2;
                        zval **single_header;
 
                        switch (Z_TYPE_PP(header)) {
                                case IS_STRING:
-                                       phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key, Z_STRVAL_PP(header));
+                                       phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(header));
                                        break;
 
                                case IS_ARRAY:
                                        FOREACH_VAL(pos2, *header, single_header) {
-                                               phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key, Z_STRVAL_PP(single_header));
+                                               phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(single_header));
                                        }
                                        break;
                        }
-
-                       key = NULL;
                }
        }
 
@@ -500,16 +498,13 @@ PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC)
        switch (message->type) {
                case HTTP_MSG_RESPONSE:
                {
-                       char *key;
-                       uint len;
-                       ulong idx;
+                       HashKey key = initHashKey(0);
                        zval **val;
                        HashPosition pos;
 
-                       FOREACH_HASH_KEYLENVAL(pos, &message->hdrs, key, len, idx, val) {
-                               if (key) {
-                                       http_send_header_zval_ex(key, len-1, val, 1);
-                                       key = NULL;
+                       FOREACH_HASH_KEYVAL(pos, &message->hdrs, key, val) {
+                               if (key.type == HASH_KEY_IS_STRING) {
+                                       http_send_header_zval_ex(key.str, key.len-1, val, 1);
                                }
                        }
                        rs =    SUCCESS == http_send_status(message->http.info.response.code) &&
index 5624e21..495cd28 100644 (file)
@@ -827,12 +827,10 @@ PHP_METHOD(HttpMessage, getHeaders)
        NO_ARGS;
 
        if (return_value_used) {
-               zval headers;
                getObject(http_message_object, obj);
 
-               INIT_ZARR(headers, &obj->message->hdrs);
                array_init(return_value);
-               array_copy(&headers, return_value);
+               array_copy(&obj->message->hdrs, Z_ARRVAL_P(return_value));
        }
 }
 /* }}} */
@@ -846,7 +844,7 @@ PHP_METHOD(HttpMessage, getHeaders)
  */
 PHP_METHOD(HttpMessage, setHeaders)
 {
-       zval *new_headers = NULL, old_headers;
+       zval *new_headers = NULL;
        getObject(http_message_object, obj);
 
        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!", &new_headers)) {
@@ -855,8 +853,7 @@ PHP_METHOD(HttpMessage, setHeaders)
 
        zend_hash_clean(&obj->message->hdrs);
        if (new_headers) {
-               INIT_ZARR(old_headers, &obj->message->hdrs);
-               array_copy(new_headers, &old_headers);
+               array_copy(Z_ARRVAL_P(new_headers), &obj->message->hdrs);
        }
 }
 /* }}} */
@@ -873,7 +870,7 @@ PHP_METHOD(HttpMessage, setHeaders)
  */
 PHP_METHOD(HttpMessage, addHeaders)
 {
-       zval old_headers, *new_headers;
+       zval *new_headers;
        zend_bool append = 0;
        getObject(http_message_object, obj);
 
@@ -881,12 +878,7 @@ PHP_METHOD(HttpMessage, addHeaders)
                return;
        }
 
-       INIT_ZARR(old_headers, &obj->message->hdrs);
-       if (append) {
-               array_append(new_headers, &old_headers);
-       } else {
-               array_merge(new_headers, &old_headers);
-       }
+       array_join(Z_ARRVAL_P(new_headers), &obj->message->hdrs, append, ARRAY_JOIN_STRONLY|ARRAY_JOIN_PRETTIFY);
 }
 /* }}} */
 
@@ -1298,7 +1290,7 @@ PHP_METHOD(HttpMessage, toMessageTypeObject)
 #ifdef HTTP_HAVE_CURL
                                int method;
                                char *url;
-                               zval tmp, body, *array, *headers, *host = http_message_header(obj->message, "Host");
+                               zval body, *array, *headers, *host = http_message_header(obj->message, "Host");
                                php_url hurl, *purl = php_url_parse(obj->message->http.info.request.url);
                                
                                MAKE_STD_ZVAL(array);
@@ -1322,8 +1314,7 @@ PHP_METHOD(HttpMessage, toMessageTypeObject)
                                
                                MAKE_STD_ZVAL(headers);
                                array_init(headers);
-                               INIT_ZARR(tmp, &obj->message->hdrs);
-                               array_copy(&tmp, headers);
+                               array_copy(&obj->message->hdrs, Z_ARRVAL_P(headers));
                                add_assoc_zval(array, "headers", headers);
                                
                                object_init_ex(return_value, http_request_object_ce);
@@ -1343,9 +1334,7 @@ PHP_METHOD(HttpMessage, toMessageTypeObject)
                        {
 #ifndef WONKY
                                HashPosition pos1, pos2;
-                               ulong idx;
-                               uint key_len;
-                               char *key = NULL;
+                               HashKey key = initHashKey(0);
                                zval **header, **h, *body;
                                
                                if (obj->message->http.info.response.code) {
@@ -1354,30 +1343,30 @@ PHP_METHOD(HttpMessage, toMessageTypeObject)
                                
                                object_init_ex(return_value, http_response_object_ce);
                                
-                               FOREACH_HASH_KEYLENVAL(pos1, &obj->message->hdrs, key, key_len, idx, header) {
-                                       if (key) {
-                                               zval zkey;
+                               FOREACH_HASH_KEYVAL(pos1, &obj->message->hdrs, key, header) {
+                                       if (key.type == HASH_KEY_IS_STRING) {
+                                               zval *zkey;
                                                
-                                               INIT_PZVAL(&zkey);
-                                               ZVAL_STRINGL(&zkey, key, key_len, 0);
+                                               MAKE_STD_ZVAL(zkey);
+                                               ZVAL_STRINGL(zkey, key.str, key.len - 1, 1);
                                                
                                                switch (Z_TYPE_PP(header)) {
                                                        case IS_ARRAY:
                                                        case IS_OBJECT:
                                                                FOREACH_HASH_VAL(pos2, HASH_OF(*header), h) {
                                                                        ZVAL_ADDREF(*h);
-                                                                       zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, &zkey, *h);
+                                                                       zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *h);
                                                                        zval_ptr_dtor(h);
                                                                }
                                                                break;
                                                        
                                                        default:
                                                                ZVAL_ADDREF(*header);
-                                                               zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, &zkey, *header);
+                                                               zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *header);
                                                                zval_ptr_dtor(header);
                                                                break;
                                                }
-                                               key = NULL;
+                                               zval_ptr_dtor(&zkey);
                                        }
                                }
                                
index 4c45664..09a767f 100644 (file)
@@ -43,52 +43,50 @@ PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *i
 {
        HashPosition pos;
        zval **entry = NULL;
-       char *xlate_str = NULL, *xkey, *kstr = NULL;
+       char *xlate_str = NULL, *xkey;
        size_t xlate_len = 0, xlen;
-       uint klen = 0;
-       ulong kidx = 0;
+       HashKey key = initHashKey(0);
        
-       FOREACH_KEYLENVAL(pos, param, kstr, klen, kidx, entry) {
-               if (kstr) {
-                       if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(kstr, klen-1, &xkey, &xlen, oe, ie)) {
-                               http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", klen-1, kstr, ie, oe);
+       FOREACH_KEYVAL(pos, param, key, entry) {
+               if (key.type == HASH_KEY_IS_STRING) {
+                       if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(key.str, key.len-1, &xkey, &xlen, oe, ie)) {
+                               http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", key.len-1, key.str, ie, oe);
                                return FAILURE;
                        }
                }
                
                if (Z_TYPE_PP(entry) == IS_STRING) {
                        if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), &xlate_str, &xlate_len, oe, ie)) {
-                               if (kstr) {
+                               if (key.type == HASH_KEY_IS_STRING) {
                                        efree(xkey);
                                }
                                http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", Z_STRLEN_PP(entry), Z_STRVAL_PP(entry), ie, oe);
                                return FAILURE;
                        }
-                       if (kstr) {
+                       if (key.type == HASH_KEY_IS_STRING) {
                                add_assoc_stringl_ex(array, xkey, xlen+1, xlate_str, xlate_len, 0);
                        } else {
-                               add_index_stringl(array, kidx, xlate_str, xlate_len, 0);
+                               add_index_stringl(array, key.num, xlate_str, xlate_len, 0);
                        }
                } else if (Z_TYPE_PP(entry) == IS_ARRAY) {
                        zval *subarray;
                        
                        MAKE_STD_ZVAL(subarray);
                        array_init(subarray);
-                       if (kstr) {
+                       if (key.type == HASH_KEY_IS_STRING) {
                                add_assoc_zval_ex(array, xkey, xlen+1, subarray);
                        } else {
-                               add_index_zval(array, kidx, subarray);
+                               add_index_zval(array, key.num, subarray);
                        }
                        if (SUCCESS != http_querystring_xlate(subarray, *entry, ie, oe)) {
-                               if (kstr) {
+                               if (key.type == HASH_KEY_IS_STRING) {
                                        efree(xkey);
                                }
                                return FAILURE;
                        }
                }
                
-               if (kstr) {
-                       kstr = NULL;
+               if (key.type == HASH_KEY_IS_STRING) {
                        efree(xkey);
                }
        }
@@ -147,18 +145,15 @@ PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC)
 static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC)
 {
        int rv = 0;
-       char *key = NULL;
-       uint keylen = 0;
-       ulong idx = 0;
+       HashKey key = initHashKey(0);
        HashPosition pos;
        zval **params_entry = NULL;
        
-       FOREACH_KEYLENVAL(pos, params, key, keylen, idx, params_entry) {
+       FOREACH_KEYVAL(pos, params, key, params_entry) {
                /* only public properties */
-               if ((!key || *key) && http_querystring_modify_array_ex(qarray, key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG, key, keylen, idx, *params_entry)) {
+               if ((key.type != HASH_KEY_IS_STRING || *key.str) && http_querystring_modify_array_ex(qarray, key.type, key.str, key.len, key.num, *params_entry)) {
                        rv = 1;
                }
-               key = NULL;
        }
        
        return rv;
index 62b66bd..fa8ea70 100644 (file)
@@ -309,8 +309,7 @@ PHP_HTTP_API STATUS _http_request_enable_cookies(http_request *request)
        TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
        
        HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0);
-       if (initialized) {
-               curl_easy_setopt(request->ch, CURLOPT_COOKIEFILE, "");
+       if (initialized && CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIEFILE, "")) {
                return SUCCESS;
        }
        http_error(HE_WARNING, HTTP_E_REQUEST, "Could not enable cookies for this session");
@@ -327,16 +326,14 @@ PHP_HTTP_API STATUS _http_request_reset_cookies(http_request *request, int sessi
        HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0);
        if (session_only) {
 #if HTTP_CURL_VERSION(7,15,4)
-               if (initialized) {
-                       curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "SESS");
+               if (initialized && CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "SESS")) {
                        return SUCCESS;
                }
 #endif
                http_error(HE_WARNING, HTTP_E_REQUEST, "Could not reset session cookies (need libcurl >= v7.15.4)");
        } else {
 #if HTTP_CURL_VERSION(7,14,1)
-               if (initialized) {
-                       curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "ALL");
+               if (initialized && CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "ALL")) {
                        return SUCCESS;
                }
 #endif
@@ -637,28 +634,22 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti
                request->_cache.headers = NULL;
        }
        if ((zoption = http_request_option(request, options, "headers", IS_ARRAY))) {
-               char *header_key = NULL;
-               ulong header_idx;
+               HashKey header_key = initHashKey(0);
+               zval **header_val;
                HashPosition pos;
 
-               FOREACH_KEY(pos, zoption, header_key, header_idx) {
-                       if (header_key) {
-                               zval **header_val;
-                               if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_P(zoption), (void *) &header_val, &pos)) {
-                                       char header[1024] = {0};
-                                       
-                                       ZVAL_ADDREF(*header_val);
-                                       convert_to_string_ex(header_val);
-                                       if (!strcasecmp(header_key, "range")) {
-                                               range_req = 1;
-                                       }
-                                       snprintf(header, lenof(header), "%s: %s", header_key, Z_STRVAL_PP(header_val));
-                                       request->_cache.headers = curl_slist_append(request->_cache.headers, header);
-                                       zval_ptr_dtor(header_val);
+               FOREACH_KEYVAL(pos, zoption, header_key, header_val) {
+                       if (header_key.type == HASH_KEY_IS_STRING) {
+                               char header[1024] = {0};
+                               
+                               ZVAL_ADDREF(*header_val);
+                               convert_to_string_ex(header_val);
+                               if (!strcasecmp(header_key.str, "range")) {
+                                       range_req = 1;
                                }
-
-                               /* reset */
-                               header_key = NULL;
+                               snprintf(header, lenof(header), "%s: %s", header_key.str, Z_STRVAL_PP(header_val));
+                               request->_cache.headers = curl_slist_append(request->_cache.headers, header);
+                               zval_ptr_dtor(header_val);
                        }
                }
        }
@@ -706,20 +697,14 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti
                                }
                        } else {
                                HashPosition pos;
-                               char *cookie_key = NULL;
-                               ulong cookie_idx;
+                               HashKey cookie_key = initHashKey(0);
+                               zval **cookie_val;
                                
-                               FOREACH_KEY(pos, zoption, cookie_key, cookie_idx) {
-                                       if (cookie_key) {
-                                               zval **cookie_val;
-                                               if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_P(zoption), (void *) &cookie_val, &pos)) {
-                                                       zval *val = zval_copy(IS_STRING, *cookie_val);
-                                                       phpstr_appendf(&request->_cache.cookies, "%s=%s; ", cookie_key, Z_STRVAL_P(val));
-                                                       zval_free(&val);
-                                               }
-
-                                               /* reset */
-                                               cookie_key = NULL;
+                               FOREACH_KEYVAL(pos, zoption, cookie_key, cookie_val) {
+                                       if (cookie_key.type == HASH_KEY_IS_STRING) {
+                                               zval *val = zval_copy(IS_STRING, *cookie_val);
+                                               phpstr_appendf(&request->_cache.cookies, "%s=%s; ", cookie_key.str, Z_STRVAL_P(val));
+                                               zval_free(&val);
                                        }
                                }
                                
@@ -767,13 +752,12 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti
 
        /* ssl */
        if ((zoption = http_request_option(request, options, "ssl", IS_ARRAY))) {
-               ulong idx;
-               char *key = NULL;
+               HashKey key = initHashKey(0);
                zval **param;
                HashPosition pos;
 
-               FOREACH_KEYVAL(pos, zoption, key, idx, param) {
-                       if (key) {
+               FOREACH_KEYVAL(pos, zoption, key, param) {
+                       if (key.type == HASH_KEY_IS_STRING) {
                                HTTP_CURL_OPT_STRING(CURLOPT_SSLCERT, 0, 1);
                                HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTTYPE, 0, 0);
                                HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTPASSWD, 0, 0);
@@ -793,9 +777,6 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti
                                HTTP_CURL_OPT_STRING(CURLOPT_CAPATH, -3, 1);
                                HTTP_CURL_OPT_STRING(CURLOPT_RANDOM_FILE, -3, 1);
                                HTTP_CURL_OPT_STRING(CURLOPT_EGDSOCKET, -3, 1);
-
-                               /* reset key */
-                               key = NULL;
                        }
                }
        }
index a577023..bc1648c 100644 (file)
@@ -99,22 +99,21 @@ PHP_HTTP_API http_request_body *_http_request_body_init_ex(http_request_body *bo
 PHP_HTTP_API http_request_body *_http_request_body_fill(http_request_body *body, HashTable *fields, HashTable *files ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
 {
        if (files && (zend_hash_num_elements(files) > 0)) {
-               char *key = NULL;
-               ulong idx;
+               HashKey key = initHashKey(0);
                zval **data;
                HashPosition pos;
                struct curl_httppost *http_post_data[2] = {NULL, NULL};
 
                /* normal data */
                if (fields) {
-                       FOREACH_HASH_KEYVAL(pos, fields, key, idx, data) {
-                               if (key) {
+                       FOREACH_HASH_KEYVAL(pos, fields, key, data) {
+                               if (key.type == HASH_KEY_IS_STRING) {
                                        CURLcode err;
                                        zval *orig = *data;
                                        
                                        convert_to_string_ex(data);
                                        err = curl_formadd(&http_post_data[0], &http_post_data[1],
-                                               CURLFORM_COPYNAME,                      key,
+                                               CURLFORM_COPYNAME,                      key.str,
                                                CURLFORM_COPYCONTENTS,          Z_STRVAL_PP(data),
                                                CURLFORM_CONTENTSLENGTH,        (long) Z_STRLEN_PP(data),
                                                CURLFORM_END
@@ -129,9 +128,6 @@ PHP_HTTP_API http_request_body *_http_request_body_fill(http_request_body *body,
                                                curl_formfree(http_post_data[0]);
                                                return NULL;
                                        }
-       
-                                       /* reset */
-                                       key = NULL;
                                }
                        }
                }
index 3b40bd2..c56562a 100644 (file)
@@ -748,26 +748,26 @@ static inline void _http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM
        array_init(new_opts);
        old_opts = GET_PROP(options);
        if (Z_TYPE_P(old_opts) == IS_ARRAY) {
-               array_copy(old_opts, new_opts);
+               array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
        }
 
-       if (prettify_keys && opts) {
-               zend_hash_apply_with_arguments(Z_ARRVAL_P(opts), apply_pretty_key, 0);
-       }
        if (SUCCESS == zend_hash_find(Z_ARRVAL_P(new_opts), key, len, (void *) &entry)) {
                if (overwrite) {
                        zend_hash_clean(Z_ARRVAL_PP(entry));
                }
                if (opts && zend_hash_num_elements(Z_ARRVAL_P(opts))) {
                        if (overwrite) {
-                               array_copy(opts, *entry);
+                               array_copy(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry));
                        } else {
-                               array_merge(opts, *entry);
+                               array_join(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry), 0, prettify_keys ? ARRAY_JOIN_PRETTIFY : 0);
                        }
                }
        } else if (opts) {
+               if (prettify_keys) {
+                       zend_hash_apply_with_arguments(Z_ARRVAL_P(opts), apply_pretty_key, 0);
+               }
                ZVAL_ADDREF(opts);
-               add_assoc_zval(new_opts, key, opts);
+               add_assoc_zval_ex(new_opts, key, len, opts);
        }
        SET_PROP(options, new_opts);
        zval_ptr_dtor(&new_opts);
@@ -790,7 +790,7 @@ static inline void _http_request_get_options_subr(INTERNAL_FUNCTION_PARAMETERS,
                if (    (Z_TYPE_P(opts) == IS_ARRAY) && 
                                (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), key, len, (void *) &options))) {
                        convert_to_array(*options);
-                       array_copy(*options, return_value);
+                       array_copy(Z_ARRVAL_PP(options), Z_ARRVAL_P(return_value));
                }
        }
 }
@@ -844,8 +844,7 @@ PHP_METHOD(HttpRequest, __construct)
  */
 PHP_METHOD(HttpRequest, setOptions)
 {
-       char *key = NULL;
-       ulong idx = 0;
+       HashKey key = initHashKey(0);
        HashPosition pos;
        zval *opts = NULL, *old_opts, *new_opts, *add_opts, **opt;
 
@@ -865,42 +864,40 @@ PHP_METHOD(HttpRequest, setOptions)
        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")) {
+       FOREACH_KEYVAL(pos, opts, key, opt) {
+               if (key.type == HASH_KEY_IS_STRING) {
+                       if (!strcmp(key.str, "headers")) {
                                zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addheaders", NULL, *opt);
-                       } else if (!strcmp(key, "cookies")) {
+                       } else if (!strcmp(key.str, "cookies")) {
                                zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addcookies", NULL, *opt);
-                       } else if (!strcmp(key, "ssl")) {
+                       } else if (!strcmp(key.str, "ssl")) {
                                zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addssloptions", NULL, *opt);
-                       } else if ((!strcasecmp(key, "url")) || (!strcasecmp(key, "uri"))) {
+                       } else if ((!strcasecmp(key.str, "url")) || (!strcasecmp(key.str, "uri"))) {
                                zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "seturl", NULL, *opt);
-                       } else if (!strcmp(key, "method")) {
+                       } else if (!strcmp(key.str, "method")) {
                                zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmethod", NULL, *opt);
 #if HTTP_CURL_VERSION(7,14,1)
-                       } else if (!strcmp(key, "resetcookies")) {
+                       } else if (!strcmp(key.str, "resetcookies")) {
                                getObject(http_request_object, obj);
                                http_request_reset_cookies(obj->request, 0);
 #endif
-                       } else if (!strcmp(key, "enablecookies")) {
+                       } else if (!strcmp(key.str, "enablecookies")) {
                                getObject(http_request_object, obj);
                                http_request_enable_cookies(obj->request);
-                       } else if (!strcasecmp(key, "recordHistory")) {
+                       } else if (!strcasecmp(key.str, "recordHistory")) {
                                UPD_PROP(bool, recordHistory, 1);
                        } else {
                                ZVAL_ADDREF(*opt);
-                               add_assoc_zval(add_opts, key, *opt);
+                               add_assoc_zval_ex(add_opts, key.str, key.len, *opt);
                        }
-                       /* reset */
-                       key = NULL;
                }
        }
        
        old_opts = GET_PROP(options);
        if (Z_TYPE_P(old_opts) == IS_ARRAY) {
-               array_copy(old_opts, new_opts);
+               array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
        }
-       array_merge(add_opts, new_opts);
+       array_join(Z_ARRVAL_P(add_opts), Z_ARRVAL_P(new_opts), 0, 0);
        SET_PROP(options, new_opts);
        zval_ptr_dtor(&new_opts);
        zval_ptr_dtor(&add_opts);
@@ -1320,9 +1317,9 @@ PHP_METHOD(HttpRequest, addPostFields)
                array_init(new_post);
                old_post = GET_PROP(postFields);
                if (Z_TYPE_P(old_post) == IS_ARRAY) {
-                       array_copy(old_post, new_post);
+                       array_copy(Z_ARRVAL_P(old_post), Z_ARRVAL_P(new_post));
                }
-               array_merge(post_data, new_post);
+               array_join(Z_ARRVAL_P(post_data), Z_ARRVAL_P(new_post), 0, 0);
                SET_PROP(postFields, new_post);
                zval_ptr_dtor(&new_post);
        }
@@ -1352,7 +1349,7 @@ PHP_METHOD(HttpRequest, setPostFields)
        MAKE_STD_ZVAL(post);
        array_init(post);
        if (post_data && zend_hash_num_elements(Z_ARRVAL_P(post_data))) {
-               array_copy(post_data, post);
+               array_copy(Z_ARRVAL_P(post_data), Z_ARRVAL_P(post));
        }
        SET_PROP(postFields, post);
        zval_ptr_dtor(&post);
@@ -1498,7 +1495,7 @@ PHP_METHOD(HttpRequest, addPostFile)
        array_init(new_post);
        old_post = GET_PROP(postFiles);
        if (Z_TYPE_P(old_post) == IS_ARRAY) {
-               array_copy(old_post, new_post);
+               array_copy(Z_ARRVAL_P(old_post), Z_ARRVAL_P(new_post));
        }
        add_next_index_zval(new_post, entry);
        SET_PROP(postFiles, new_post);
@@ -1530,7 +1527,7 @@ PHP_METHOD(HttpRequest, setPostFiles)
        MAKE_STD_ZVAL(post);
        array_init(post);
        if (files && (Z_TYPE_P(files) == IS_ARRAY)) {
-               array_copy(files, post);
+               array_copy(Z_ARRVAL_P(files), Z_ARRVAL_P(post));
        }
        SET_PROP(postFiles, post);
        zval_ptr_dtor(&post);
@@ -1770,8 +1767,8 @@ PHP_METHOD(HttpRequest, getResponseCookies)
                
                if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|la!", &flags, &allowed_extras_array)) {
                        int i = 0;
-                       ulong idx = 0;
-                       char *key = NULL, **allowed_extras = NULL;
+                       HashKey key = initHashKey(0);
+                       char **allowed_extras = NULL;
                        zval **header = NULL, **entry = NULL, *message = GET_PROP(responseMessage);
                        HashPosition pos, pos1, pos2;
                        
@@ -1790,8 +1787,8 @@ PHP_METHOD(HttpRequest, getResponseCookies)
                                        }
                                }
                                
-                               FOREACH_HASH_KEYVAL(pos1, &msg->message->hdrs, key, idx, header) {
-                                       if (key && !strcasecmp(key, "Set-Cookie")) {
+                               FOREACH_HASH_KEYVAL(pos1, &msg->message->hdrs, key, header) {
+                                       if (key.type == HASH_KEY_IS_STRING && !strcasecmp(key.str, "Set-Cookie")) {
                                                http_cookie_list list;
                                                
                                                if (Z_TYPE_PP(header) == IS_ARRAY) {
@@ -1826,8 +1823,6 @@ PHP_METHOD(HttpRequest, getResponseCookies)
                                                        zval_ptr_dtor(header);
                                                }
                                        }
-                                       /* reset key */
-                                       key = NULL;
                                }
                                
                                if (allowed_extras) {
index 9068378..fe1d834 100644 (file)
@@ -374,9 +374,7 @@ PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_
 /* {{{ http_urlencode_hash_recursive */
 PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, const char *arg_sep, size_t arg_sep_len, const char *prefix, size_t prefix_len TSRMLS_DC)
 {
-       char *key = NULL;
-       uint len = 0;
-       ulong idx = 0;
+       HashKey key = initHashKey(0);
        zval **data = NULL;
        HashPosition pos;
 
@@ -388,7 +386,7 @@ PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, c
                return SUCCESS;
        }
        
-       FOREACH_HASH_KEYLENVAL(pos, ht, key, len, idx, data) {
+       FOREACH_HASH_KEYVAL(pos, ht, key, data) {
                char *encoded_key;
                int encoded_len;
                phpstr new_prefix;
@@ -398,18 +396,17 @@ PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, c
                        return FAILURE;
                }
                
-               if (key) {
-                       if (!*key) {
+               if (key.type == HASH_KEY_IS_STRING) {
+                       if (!*key.str) {
                                /* only public properties */
                                continue;
                        }
-                       if (len && key[len - 1] == '\0') {
-                               --len;
+                       if (key.len && key.str[key.len - 1] == '\0') {
+                               --key.len;
                        }
-                       encoded_key = php_url_encode(key, len, &encoded_len);
-                       key = NULL;
+                       encoded_key = php_url_encode(key.str, key.len, &encoded_len);
                } else {
-                       encoded_len = spprintf(&encoded_key, 0, "%ld", idx);
+                       encoded_len = spprintf(&encoded_key, 0, "%ld", key.num);
                }
                
                {
index 2e6efca..f2c5312 100644 (file)
@@ -305,6 +305,42 @@ static inline void _zval_free(zval **z)
        *z = NULL;
 }
 
+typedef struct _HashKey {
+       int type;
+       int dup;
+       char *str;
+       uint len;
+       ulong num;
+} HashKey;
+#define initHashKey(dup) {0, (dup), NULL, 0, 0}
+
+#define FOREACH_VAL(pos, array, val) FOREACH_HASH_VAL(pos, Z_ARRVAL_P(array), val)
+#define FOREACH_HASH_VAL(pos, hash, val) \
+       for (   zend_hash_internal_pointer_reset_ex(hash, &pos); \
+                       zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \
+                       zend_hash_move_forward_ex(hash, &pos))
+
+#define FOREACH_KEY(pos, array, key) FOREACH_HASH_KEY(pos, Z_ARRVAL_P(array), key)
+#define FOREACH_HASH_KEY(pos, hash, _key) \
+       for (   zend_hash_internal_pointer_reset_ex(hash, &pos); \
+                       ((_key).type = zend_hash_get_current_key_ex(hash, &(_key).str, &(_key).len, &(_key).num, (_key).dup, &pos)) != HASH_KEY_NON_EXISTANT; \
+                       zend_hash_move_forward_ex(hash, &pos)) \
+
+#define FOREACH_KEYVAL(pos, array, key, val) FOREACH_HASH_KEYVAL(pos, Z_ARRVAL_P(array), key, val)
+#define FOREACH_HASH_KEYVAL(pos, hash, _key, val) \
+       for (   zend_hash_internal_pointer_reset_ex(hash, &pos); \
+                       ((_key).type = zend_hash_get_current_key_ex(hash, &(_key).str, &(_key).len, &(_key).num, (_key).dup, &pos)) != HASH_KEY_NON_EXISTANT && \
+                       zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \
+                       zend_hash_move_forward_ex(hash, &pos))
+
+#define array_copy(src, dst) zend_hash_copy(dst, src, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *))
+#define ARRAY_JOIN_STRONLY 1
+#define ARRAY_JOIN_PRETTIFY 2
+#define array_join(src, dst, append, flags) zend_hash_apply_with_arguments(src, (append)?apply_array_append_func:apply_array_merge_func, 2, dst, (int)flags)
+
+extern int apply_array_append_func(void *pDest, int num_args, va_list args, zend_hash_key *hash_key);
+extern int apply_array_merge_func(void *pDest, int num_args, va_list args, zend_hash_key *hash_key);
+
 #endif
 
 /*
index e744964..7bf5db1 100644 (file)
                HTTP_CURL_OPT_STRING_EX(K+lenof("CURLOPT_KEY")+ldiff, OPTION, obdc); \
        }
 #define HTTP_CURL_OPT_STRING_EX(keyname, optname, obdc) \
-       if (!strcasecmp(key, keyname)) { \
+       if (!strcasecmp(key.str, keyname)) { \
                zval *copy = http_request_option_cache_ex(request, keyname, strlen(keyname)+1, 0, zval_copy(IS_STRING, *param)); \
                if (obdc) { \
                        HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(copy), return FAILURE); \
                } \
                HTTP_CURL_OPT(optname, Z_STRVAL_P(copy)); \
-               key = NULL; \
                continue; \
        }
 #define HTTP_CURL_OPT_LONG(OPTION, ldiff) \
                HTTP_CURL_OPT_LONG_EX(K+lenof("CURLOPT_KEY")+ldiff, OPTION); \
        }
 #define HTTP_CURL_OPT_LONG_EX(keyname, optname) \
-       if (!strcasecmp(key, keyname)) { \
+       if (!strcasecmp(key.str, keyname)) { \
                zval *copy = zval_copy(IS_LONG, *param); \
                HTTP_CURL_OPT(optname, Z_LVAL_P(copy)); \
-               key = NULL; \
                zval_free(&copy); \
                continue; \
        }
index fd96018..f851983 100644 (file)
@@ -141,72 +141,6 @@ typedef int STATUS;
 #define HTTP_PHP_INI_ENTRY_EX(entry, default, scope, updater, displayer, global) \
        STD_PHP_INI_ENTRY_EX(entry, default, scope, updater, global, zend_http_globals, http_globals, displayer)
 
-/* {{{ arrays */
-#define FOREACH_VAL(pos, array, val) FOREACH_HASH_VAL(pos, Z_ARRVAL_P(array), val)
-#define FOREACH_HASH_VAL(pos, hash, val) \
-       for (   zend_hash_internal_pointer_reset_ex(hash, &pos); \
-                       zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \
-                       zend_hash_move_forward_ex(hash, &pos))
-
-#define FOREACH_KEY(pos, array, strkey, numkey) FOREACH_HASH_KEY(pos, Z_ARRVAL_P(array), strkey, numkey)
-#define FOREACH_HASH_KEY(pos, hash, strkey, numkey) \
-       for (   zend_hash_internal_pointer_reset_ex(hash, &pos); \
-                       zend_hash_get_current_key_ex(hash, &strkey, NULL, &numkey, 0, &pos) != HASH_KEY_NON_EXISTANT; \
-                       zend_hash_move_forward_ex(hash, &pos)) \
-
-#define FOREACH_KEYLEN(pos, array, strkey, keylen, numkey) FOREACH_HASH_KEYLEN(pos, Z_ARRVAL_P(array), strkey, keylen, numkey)
-#define FOREACH_HASH_KEYLEN(pos, hash, strkey, keylen, numkey) \
-       for (   zend_hash_internal_pointer_reset_ex(hash, &pos); \
-                       zend_hash_get_current_key_ex(hash, &strkey, &keylen, &numkey, 0, &pos) != HASH_KEY_NON_EXISTANT; \
-                       zend_hash_move_forward_ex(hash, &pos)) \
-
-#define FOREACH_KEYVAL(pos, array, strkey, numkey, val) FOREACH_HASH_KEYVAL(pos, Z_ARRVAL_P(array), strkey, numkey, val)
-#define FOREACH_HASH_KEYVAL(pos, hash, strkey, numkey, val) \
-       for (   zend_hash_internal_pointer_reset_ex(hash, &pos); \
-                       zend_hash_get_current_key_ex(hash, &strkey, NULL, &numkey, 0, &pos) != HASH_KEY_NON_EXISTANT && \
-                       zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \
-                       zend_hash_move_forward_ex(hash, &pos))
-
-#define FOREACH_KEYLENVAL(pos, array, strkey, keylen, numkey, val) FOREACH_HASH_KEYLENVAL(pos, Z_ARRVAL_P(array), strkey, keylen, numkey, val)
-#define FOREACH_HASH_KEYLENVAL(pos, hash, strkey, keylen, numkey, val) \
-       for (   zend_hash_internal_pointer_reset_ex(hash, &pos); \
-                       zend_hash_get_current_key_ex(hash, &strkey, &keylen, &numkey, 0, &pos) != HASH_KEY_NON_EXISTANT && \
-                       zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \
-                       zend_hash_move_forward_ex(hash, &pos))
-
-#define array_copy(src, dst)   zend_hash_copy(Z_ARRVAL_P(dst), Z_ARRVAL_P(src), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *))
-#define array_merge(src, dst)  zend_hash_merge(Z_ARRVAL_P(dst), Z_ARRVAL_P(src), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *), 1)
-#define array_append(src, dst) \
-       { \
-               ulong idx; \
-               uint klen; \
-               char *key = NULL; \
-               zval **data; \
-               HashPosition pos; \
-                \
-               for (   zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(src), &pos); \
-                               zend_hash_get_current_key_ex(Z_ARRVAL_P(src), &key, &klen, &idx, 0, &pos) != HASH_KEY_NON_EXISTANT && \
-                               zend_hash_get_current_data_ex(Z_ARRVAL_P(src), (void *) &data, &pos) == SUCCESS; \
-                               zend_hash_move_forward_ex(Z_ARRVAL_P(src), &pos)) \
-               { \
-                       if (key) { \
-                               zval **tmp; \
-                                \
-                               if (SUCCESS == zend_hash_find(Z_ARRVAL_P(dst), key, klen, (void *) &tmp)) { \
-                                       if (Z_TYPE_PP(tmp) != IS_ARRAY) { \
-                                               convert_to_array_ex(tmp); \
-                                       } \
-                                       ZVAL_ADDREF(*data); \
-                                       add_next_index_zval(*tmp, *data); \
-                               } else { \
-                                       ZVAL_ADDREF(*data); \
-                                       add_assoc_zval(dst, key, *data); \
-                               } \
-                               key = NULL; \
-                       } \
-               } \
-       }
-/* }}} */
 
 #define HTTP_LONG_CONSTANT(name, const) REGISTER_LONG_CONSTANT(name, const, CONST_CS | CONST_PERSISTENT)