Merge branch 'master' into phpng
authorMichael Wallner <mike@php.net>
Fri, 7 Aug 2015 09:36:04 +0000 (11:36 +0200)
committerMichael Wallner <mike@php.net>
Fri, 7 Aug 2015 09:36:04 +0000 (11:36 +0200)
Conflicts:
php_http_client.c
php_http_client_curl.c
php_http_env_request.c
php_http_env_response.c
php_http_header_parser.c

1  2 
config9.m4
php_http_client_curl.c
php_http_env_request.c
php_http_header_parser.c
php_http_querystring.c
php_http_url.c
tests/helper/server.inc

diff --combined config9.m4
index b82a3a77a316234bf1767175314ab392ba71288a,273f03873dbca17a314cfe755fdaeebb9c61a0e4..c38107c01bc17f23b1b88a4989b1644b49c5fcd6
@@@ -93,6 -93,34 +93,34 @@@ if test "$PHP_HTTP" != "no"; the
                fi
        ])
        
+       dnl
+       dnl HTTP_CURL_SSL_LIB_CHECK(ssllib[, code-if-yes[, code-if-not])
+       dnl
+       AC_DEFUN([HTTP_CURL_SSL_LIB_CHECK], [
+               AC_MSG_CHECKING([for $1 support in libcurl])
+               AC_TRY_RUN([
+                       #include <curl/curl.h>
+                       int main(int argc, char *argv[]) {
+                               curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
+                               if (data && data->ssl_version && *data->ssl_version) {
+                                       const char *ptr = data->ssl_version;
+                                       while(*ptr == ' ') ++ptr;
+                                       return strncasecmp(ptr, "$1", sizeof("$1")-1);
+                               }
+                               return 1;
+                       }
+               ], [
+                       AC_MSG_RESULT([yes])
+                       $2
+               ], [
+                       AC_MSG_RESULT([no])
+                       $3
+               ], [
+                       AC_MSG_RESULT([no])
+                       $3
+               ])
+       ])
+       
  
  dnl ----
  dnl STDC
@@@ -288,58 -316,33 +316,33 @@@ dnl ---
                                AC_MSG_RESULT([yes])
                                AC_DEFINE([PHP_HTTP_HAVE_SSL], [1], [ ])
                        
-                               AC_MSG_CHECKING([for openssl support in libcurl])
-                               AC_TRY_RUN([
-                                       #include <curl/curl.h>
-                                       int main(int argc, char *argv[]) {
-                                               curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
-                                               if (data && data->ssl_version && *data->ssl_version) {
-                                                       const char *ptr = data->ssl_version;
-                                                       while(*ptr == ' ') ++ptr;
-                                                       return strncasecmp(ptr, "OpenSSL", sizeof("OpenSSL")-1);
-                                               }
-                                               return 1;
-                                       }
-                               ], [
-                                       AC_MSG_RESULT([yes])
+                               HTTP_CURL_SSL_LIB_CHECK(OpenSSL, [
                                        AC_CHECK_HEADER([openssl/ssl.h], [
                                                AC_CHECK_HEADER([openssl/crypto.h], [
                                                        AC_DEFINE([PHP_HTTP_HAVE_OPENSSL], [1], [ ])
                                                        CURL_SSL_LIBS="ssl crypto"
                                                ])
                                        ])
-                               ], [
-                                       AC_MSG_RESULT([no])
-                               ], [
-                                       AC_MSG_RESULT([no])
                                ])
-                       
-                               AC_MSG_CHECKING([for gnutls support in libcurl])
-                               AC_TRY_RUN([
-                                       #include <curl/curl.h>
-                                       int main(int argc, char *argv[]) {
-                                               curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
-                                               if (data && data->ssl_version && *data->ssl_version) {
-                                                       const char *ptr = data->ssl_version;
-                                                       while(*ptr == ' ') ++ptr;
-                                                       return strncasecmp(ptr, "GnuTLS", sizeof("GnuTLS")-1);
-                                               }
-                                               return 1;
-                                       }
-                               ], [
-                                       AC_MSG_RESULT([yes])
+                               HTTP_CURL_SSL_LIB_CHECK(GnuTLS, [
                                        AC_CHECK_HEADER([gnutls.h], [
                                                AC_CHECK_HEADER([gcrypt.h], [
                                                        AC_DEFINE([PHP_HTTP_HAVE_GNUTLS], [1], [ ])
                                                        CURL_SSL_LIBS="gnutls gcrypt"
                                                ])
                                        ])
-                               ], [
-                                       AC_MSG_RESULT([no])
-                               ], [
-                                       AC_MSG_RESULT([no])
+                               ])
+                               HTTP_CURL_SSL_LIB_CHECK(NSS, [
+                                       AC_DEFINE([PHP_HTTP_HAVE_NSS], [1], [ ])
+                               ])
+                               HTTP_CURL_SSL_LIB_CHECK(SecureTransport, [
+                                       AC_DEFINE([PHP_HTTP_HAVE_DARWINSSL], [1], [ ])
+                               ])
+                               HTTP_CURL_SSL_LIB_CHECK(GSKit, [
+                                       AC_DEFINE([PHP_HTTP_HAVE_GSKIT], [1], [ ])
                                ])
                        else
+                               dnl no CURL_SSL
                                AC_MSG_RESULT([no])
                        fi
                        
@@@ -656,7 -659,4 +659,7 @@@ dnl ---
        PHP_INSTALL_HEADERS(ext/http, $PHP_HTTP_HEADERS)
  
        AC_DEFINE([HAVE_HTTP], [1], [Have extended HTTP support])
 +      if $HTTP_HAVE_A_REQUEST_LIB; then
 +              AC_DEFINE([PHP_HTTP_HAVE_CLIENT], [1], [Have HTTP client support])
 +      fi
  fi
diff --combined php_http_client_curl.c
index cb530649b1e87a4a72318a8815373ed88d1f3b01,78c552a2ce723dbd8d9ea76edf8dbe08482ab129..a4e84ced00cec07c97a0e44fdeecbff04d16914e
@@@ -76,15 -76,15 +76,15 @@@ typedef struct php_http_client_curl_han
                php_http_buffer_t cookies;
                php_http_buffer_t ranges;
  
 -              long redirects;
 -              unsigned range_request:1;
 -              unsigned encode_cookies:1;
 -
                struct {
                        uint count;
                        double delay;
                } retry;
  
 +              long redirects;
 +              unsigned range_request:1;
 +              unsigned encode_cookies:1;
 +
        } options;
  
  } php_http_client_curl_handler_t;
@@@ -110,7 -110,7 +110,7 @@@ static inline php_http_curle_storage_t 
        return st;
  }
  
 -static void *php_http_curle_ctor(void *opaque, void *init_arg TSRMLS_DC)
 +static void *php_http_curle_ctor(void *opaque, void *init_arg)
  {
        void *ch;
  
        return NULL;
  }
  
 -static void *php_http_curle_copy(void *opaque, void *handle TSRMLS_DC)
 +static void *php_http_curle_copy(void *opaque, void *handle)
  {
        void *ch;
  
        return NULL;
  }
  
 -static void php_http_curle_dtor(void *opaque, void *handle TSRMLS_DC)
 +static void php_http_curle_dtor(void *opaque, void *handle)
  {
        php_http_curle_storage_t *st = php_http_curle_get_storage(handle);
  
@@@ -156,12 -156,12 +156,12 @@@ static php_resource_factory_ops_t php_h
        php_http_curle_dtor
  };
  
 -static void *php_http_curlm_ctor(void *opaque, void *init_arg TSRMLS_DC)
 +static void *php_http_curlm_ctor(void *opaque, void *init_arg)
  {
        return curl_multi_init();
  }
  
 -static void php_http_curlm_dtor(void *opaque, void *handle TSRMLS_DC)
 +static void php_http_curlm_dtor(void *opaque, void *handle)
  {
        curl_multi_cleanup(handle);
  }
@@@ -178,10 -178,11 +178,10 @@@ static size_t php_http_curle_read_callb
  {
        php_http_message_body_t *body = ctx;
  
 -      if (body && body->stream_id) {
 +      if (body && body->res) {
                php_stream *s = php_http_message_body_stream(body);
  
                if (s) {
 -                      TSRMLS_FETCH_FROM_CTX(body->ts);
                        return php_stream_read(s, data, len * n);
                } else abort();
        }
@@@ -220,6 -221,7 +220,6 @@@ static int php_http_curle_progress_call
  static int php_http_curle_seek_callback(void *userdata, curl_off_t offset, int origin)
  {
        php_http_message_body_t *body = userdata;
 -      TSRMLS_FETCH_FROM_CTX(body->ts);
  
        if (!body) {
                return 1;
@@@ -314,161 -316,131 +314,161 @@@ static int php_http_curle_body_callback
  
  static ZEND_RESULT_CODE php_http_curle_get_info(CURL *ch, HashTable *info)
  {
 -      char *c;
 -      long l;
 -      double d;
 -      struct curl_slist *s, *p;
 -      zval *subarray, array;
 -      INIT_PZVAL_ARRAY(&array, info);
 +      char *c = NULL;
 +      long l = 0;
 +      double d = 0;
 +      struct curl_slist *s = NULL, *p = NULL;
 +      zval tmp = {{0}};
  
        /* BEGIN::CURLINFO */
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_EFFECTIVE_URL, &c)) {
 -              add_assoc_string_ex(&array, "effective_url", sizeof("effective_url"), c ? c : "", 1);
 +              ZVAL_STRING(&tmp, STR_PTR(c));
 +              zend_hash_str_update(info, "effective_url", lenof("effective_url"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_RESPONSE_CODE, &l)) {
 -              add_assoc_long_ex(&array, "response_code", sizeof("response_code"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "response_code", lenof("response_code"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_TOTAL_TIME, &d)) {
 -              add_assoc_double_ex(&array, "total_time", sizeof("total_time"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "total_time", lenof("total_time"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_NAMELOOKUP_TIME, &d)) {
 -              add_assoc_double_ex(&array, "namelookup_time", sizeof("namelookup_time"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "namelookup_time", lenof("namelookup_time"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_CONNECT_TIME, &d)) {
 -              add_assoc_double_ex(&array, "connect_time", sizeof("connect_time"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "connect_time", lenof("connect_time"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_PRETRANSFER_TIME, &d)) {
 -              add_assoc_double_ex(&array, "pretransfer_time", sizeof("pretransfer_time"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "pretransfer_time", lenof("pretransfer_time"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_SIZE_UPLOAD, &d)) {
 -              add_assoc_double_ex(&array, "size_upload", sizeof("size_upload"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "size_upload", lenof("size_upload"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_SIZE_DOWNLOAD, &d)) {
 -              add_assoc_double_ex(&array, "size_download", sizeof("size_download"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "size_download", lenof("size_download"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_SPEED_DOWNLOAD, &d)) {
 -              add_assoc_double_ex(&array, "speed_download", sizeof("speed_download"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "speed_download", lenof("speed_download"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_SPEED_UPLOAD, &d)) {
 -              add_assoc_double_ex(&array, "speed_upload", sizeof("speed_upload"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "speed_upload", lenof("speed_upload"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_HEADER_SIZE, &l)) {
 -              add_assoc_long_ex(&array, "header_size", sizeof("header_size"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "header_size", lenof("header_size"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_REQUEST_SIZE, &l)) {
 -              add_assoc_long_ex(&array, "request_size", sizeof("request_size"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "request_size", lenof("request_size"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_SSL_VERIFYRESULT, &l)) {
 -              add_assoc_long_ex(&array, "ssl_verifyresult", sizeof("ssl_verifyresult"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "ssl_verifyresult", lenof("ssl_verifyresult"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_FILETIME, &l)) {
 -              add_assoc_long_ex(&array, "filetime", sizeof("filetime"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "filetime", lenof("filetime"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) {
 -              add_assoc_double_ex(&array, "content_length_download", sizeof("content_length_download"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "content_length_download", lenof("content_length_download"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_CONTENT_LENGTH_UPLOAD, &d)) {
 -              add_assoc_double_ex(&array, "content_length_upload", sizeof("content_length_upload"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "content_length_upload", lenof("content_length_upload"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_STARTTRANSFER_TIME, &d)) {
 -              add_assoc_double_ex(&array, "starttransfer_time", sizeof("starttransfer_time"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "starttransfer_time", lenof("starttransfer_time"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_CONTENT_TYPE, &c)) {
 -              add_assoc_string_ex(&array, "content_type", sizeof("content_type"), c ? c : "", 1);
 +              ZVAL_STRING(&tmp, STR_PTR(c));
 +              zend_hash_str_update(info, "content_type", lenof("content_type"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_REDIRECT_TIME, &d)) {
 -              add_assoc_double_ex(&array, "redirect_time", sizeof("redirect_time"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "redirect_time", lenof("redirect_time"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_REDIRECT_COUNT, &l)) {
 -              add_assoc_long_ex(&array, "redirect_count", sizeof("redirect_count"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "redirect_count", lenof("redirect_count"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_HTTP_CONNECTCODE, &l)) {
 -              add_assoc_long_ex(&array, "connect_code", sizeof("connect_code"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "connect_code", lenof("connect_code"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_HTTPAUTH_AVAIL, &l)) {
 -              add_assoc_long_ex(&array, "httpauth_avail", sizeof("httpauth_avail"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "httpauth_avail", lenof("httpauth_avail"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_PROXYAUTH_AVAIL, &l)) {
 -              add_assoc_long_ex(&array, "proxyauth_avail", sizeof("proxyauth_avail"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "proxyauth_avail", lenof("proxyauth_avail"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_OS_ERRNO, &l)) {
 -              add_assoc_long_ex(&array, "os_errno", sizeof("os_errno"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "os_errno", lenof("os_errno"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_NUM_CONNECTS, &l)) {
 -              add_assoc_long_ex(&array, "num_connects", sizeof("num_connects"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "num_connects", lenof("num_connects"), &tmp);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_SSL_ENGINES, &s)) {
 -              MAKE_STD_ZVAL(subarray);
 -              array_init(subarray);
 +              array_init(&tmp);
                for (p = s; p; p = p->next) {
                        if (p->data) {
 -                              add_next_index_string(subarray, p->data, 1);
 +                              add_next_index_string(&tmp, p->data);
                        }
                }
 -              add_assoc_zval_ex(&array, "ssl_engines", sizeof("ssl_engines"), subarray);
 +              zend_hash_str_update(info, "ssl_engines", lenof("ssl_engines"), &tmp);
                curl_slist_free_all(s);
        }
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_REDIRECT_URL, &c)) {
 -              add_assoc_string_ex(&array, "redirect_url", sizeof("redirect_url"), c ? c : "", 1);
 +              ZVAL_STRING(&tmp, STR_PTR(c));
 +              zend_hash_str_update(info, "redirect_url", lenof("redirect_url"), &tmp);
        }
  #if PHP_HTTP_CURL_VERSION(7,19,0)
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_PRIMARY_IP, &c)) {
 -              add_assoc_string_ex(&array, "primary_ip", sizeof("primary_ip"), c ? c : "", 1);
 +              ZVAL_STRING(&tmp, STR_PTR(c));
 +              zend_hash_str_update(info, "primary_ip", lenof("primary_ip"), &tmp);
        }
  #endif
  #if PHP_HTTP_CURL_VERSION(7,19,0)
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_APPCONNECT_TIME, &d)) {
 -              add_assoc_double_ex(&array, "appconnect_time", sizeof("appconnect_time"), d);
 +              ZVAL_DOUBLE(&tmp, d);
 +              zend_hash_str_update(info, "appconnect_time", lenof("appconnect_time"), &tmp);
        }
  #endif
  #if PHP_HTTP_CURL_VERSION(7,19,4)
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_CONDITION_UNMET, &l)) {
 -              add_assoc_long_ex(&array, "condition_unmet", sizeof("condition_unmet"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "condition_unmet", lenof("condition_unmet"), &tmp);
        }
  #endif
  #if PHP_HTTP_CURL_VERSION(7,21,0)
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_PRIMARY_PORT, &l)) {
 -              add_assoc_long_ex(&array, "primary_port", sizeof("primary_port"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "primary_port", lenof("primary_port"), &tmp);
        }
  #endif
  #if PHP_HTTP_CURL_VERSION(7,21,0)
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_LOCAL_IP, &c)) {
 -              add_assoc_string_ex(&array, "local_ip", sizeof("local_ip"), c ? c : "", 1);
 +              ZVAL_STRING(&tmp, STR_PTR(c));
 +              zend_hash_str_update(info, "local_ip", lenof("local_ip"), &tmp);
        }
  #endif
  #if PHP_HTTP_CURL_VERSION(7,21,0)
        if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_LOCAL_PORT, &l)) {
 -              add_assoc_long_ex(&array, "local_port", sizeof("local_port"), l);
 +              ZVAL_LONG(&tmp, l);
 +              zend_hash_str_update(info, "local_port", lenof("local_port"), &tmp);
        }
  #endif
  
  
  #if PHP_HTTP_CURL_VERSION(7,34,0)
        {
 -              zval *ti_array;
 +              zval ti_array, subarray;
                struct curl_tlssessioninfo *ti;
  
                if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_TLS_SESSION, &ti)) {
 -                      const char *backend;
 +                      char *backend;
  
 -                      MAKE_STD_ZVAL(subarray);
 -                      ZVAL_NULL(subarray);
 -                      MAKE_STD_ZVAL(ti_array);
 -                      array_init(ti_array);
 +                      ZVAL_NULL(&subarray);
 +                      array_init(&ti_array);
  
                        switch (ti->backend) {
                        case CURLSSLBACKEND_NONE:
                                {
                                        SSL_CTX *ctx = ti->internals;
  
 -                                      array_init(subarray);
 -                                      add_assoc_long_ex(subarray, ZEND_STRS("number"), SSL_CTX_sess_number(ctx));
 -                                      add_assoc_long_ex(subarray, ZEND_STRS("connect"), SSL_CTX_sess_connect(ctx));
 -                                      add_assoc_long_ex(subarray, ZEND_STRS("connect_good"), SSL_CTX_sess_connect_good(ctx));
 -                                      add_assoc_long_ex(subarray, ZEND_STRS("connect_renegotiate"), SSL_CTX_sess_connect_renegotiate(ctx));
 -                                      add_assoc_long_ex(subarray, ZEND_STRS("hits"), SSL_CTX_sess_hits(ctx));
 -                                      add_assoc_long_ex(subarray, ZEND_STRS("cache_full"), SSL_CTX_sess_cache_full(ctx));
 +                                      array_init(&subarray);
 +                                      add_assoc_long_ex(&subarray, ZEND_STRL("number"), SSL_CTX_sess_number(ctx));
 +                                      add_assoc_long_ex(&subarray, ZEND_STRL("connect"), SSL_CTX_sess_connect(ctx));
 +                                      add_assoc_long_ex(&subarray, ZEND_STRL("connect_good"), SSL_CTX_sess_connect_good(ctx));
 +                                      add_assoc_long_ex(&subarray, ZEND_STRL("connect_renegotiate"), SSL_CTX_sess_connect_renegotiate(ctx));
 +                                      add_assoc_long_ex(&subarray, ZEND_STRL("hits"), SSL_CTX_sess_hits(ctx));
 +                                      add_assoc_long_ex(&subarray, ZEND_STRL("cache_full"), SSL_CTX_sess_cache_full(ctx));
                                }
  #endif
                                break;
                                        gnutls_session_t sess = ti->internals;
                                        char *desc;
  
 -                                      array_init(subarray);
 +                                      array_init(&subarray);
                                        if ((desc = gnutls_session_get_desc(sess))) {
 -                                              add_assoc_string_ex(subarray, ZEND_STRS("desc"), desc, 1);
 +                                              add_assoc_string_ex(&subarray, ZEND_STRL("desc"), desc);
                                                gnutls_free(desc);
                                        }
 -                                      add_assoc_bool_ex(subarray, ZEND_STRS("resumed"), gnutls_session_is_resumed(sess));
 +                                      add_assoc_bool_ex(&subarray, ZEND_STRL("resumed"), gnutls_session_is_resumed(sess));
                                }
  #endif
                                break;
                        case CURLSSLBACKEND_QSOSSL:
                                backend = "qsossl";
                                break;
- #endif
+ #else
                        case CURLSSLBACKEND_GSKIT:
                                backend = "gskit";
                                break;
+ #endif
                        case CURLSSLBACKEND_POLARSSL:
                                backend = "polarssl";
                                break;
                        default:
                                backend = "unknown";
                        }
 -                      add_assoc_string_ex(ti_array, ZEND_STRS("backend"), estrdup(backend), 0);
 -                      add_assoc_zval_ex(ti_array, ZEND_STRS("internals"), subarray);
 -                      add_assoc_zval_ex(&array, "tls_session", sizeof("tls_session"), ti_array);
 +                      add_assoc_string_ex(&ti_array, ZEND_STRL("backend"), backend);
 +                      add_assoc_zval_ex(&ti_array, ZEND_STRL("internals"), &subarray);
 +                      zend_hash_str_update(info, "tls_session", lenof("tls_session"), &ti_array);
                }
        }
  #endif
  
- #if PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)
+ #if (PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)) || (PHP_HTTP_CURL_VERSION(7,34,0) && defined(PHP_HTTP_HAVE_NSS)) || (PHP_HTTP_CURL_VERSION(7,42,0) && defined(PHP_HTTP_HAVE_GNUTLS)) || (PHP_HTTP_CURL_VERSION(7,39,0) && defined(PHP_HTTP_HAVE_GSKIT))
        {
                int i;
 -              zval *ci_array;
 +              zval ci_array, subarray;
                struct curl_certinfo *ci;
                char *colon, *keyname;
  
                if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_CERTINFO, &ci)) {
 -                      MAKE_STD_ZVAL(ci_array);
 -                      array_init(ci_array);
 +                      array_init(&ci_array);
  
                        for (i = 0; i < ci->num_of_certs; ++i) {
                                s = ci->certinfo[i];
  
 -                              MAKE_STD_ZVAL(subarray);
 -                              array_init(subarray);
 +                              array_init(&subarray);
                                for (p = s; p; p = p->next) {
                                        if (p->data) {
                                                if ((colon = strchr(p->data, ':'))) {
                                                        keyname = estrndup(p->data, colon - p->data);
 -                                                      add_assoc_string_ex(subarray, keyname, colon - p->data + 1, colon + 1, 1);
 +                                                      add_assoc_string_ex(&subarray, keyname, colon - p->data, colon + 1);
                                                        efree(keyname);
                                                } else {
 -                                                      add_next_index_string(subarray, p->data, 1);
 +                                                      add_next_index_string(&subarray, p->data);
                                                }
                                        }
                                }
 -                              add_next_index_zval(ci_array, subarray);
 +                              add_next_index_zval(&ci_array, &subarray);
                        }
 -                      add_assoc_zval_ex(&array, "certinfo", sizeof("certinfo"), ci_array);
 +                      zend_hash_str_update(info, "certinfo", lenof("certinfo"), &ci_array);
                }
        }
  #endif
        {
                php_http_curle_storage_t *st = php_http_curle_get_storage(ch);
  
 -              add_assoc_long_ex(&array, "curlcode", sizeof("curlcode"), st->errorcode);
 -              add_assoc_string_ex(&array, "error", sizeof("error"), st->errorbuffer, 1);
 +              ZVAL_LONG(&tmp, st->errorcode);
 +              zend_hash_str_update(info, "curlcode", lenof("curlcode"), &tmp);
 +              ZVAL_STRING(&tmp, st->errorbuffer);
 +              zend_hash_str_update(info, "error", lenof("error"), &tmp);
        }
  
        return SUCCESS;
@@@ -602,14 -577,14 +603,14 @@@ static int compare_queue(php_http_clien
        return handle == ((php_http_client_curl_handler_t *) e->opaque)->handle;
  }
  
 -static php_http_message_t *php_http_curlm_responseparser(php_http_client_curl_handler_t *h TSRMLS_DC)
 +static php_http_message_t *php_http_curlm_responseparser(php_http_client_curl_handler_t *h)
  {
        php_http_message_t *response;
        php_http_header_parser_t parser;
        zval *zh;
  
 -      response = php_http_message_init(NULL, 0, h->response.body TSRMLS_CC);
 -      php_http_header_parser_init(&parser TSRMLS_CC);
 +      response = php_http_message_init(NULL, 0, h->response.body);
 +      php_http_header_parser_init(&parser);
        while (h->response.headers.used) {
                php_http_header_parser_state_t st = php_http_header_parser_parse(&parser,
                                &h->response.headers, PHP_HTTP_HEADER_PARSER_CLEANUP, &response->hdrs,
        php_http_message_body_addref(h->response.body);
  
        /* let's update the response headers */
 -      if ((zh = php_http_message_header(response, ZEND_STRL("Content-Length"), 1))) {
 -              zend_hash_update(&response->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), &zh, sizeof(zval *), NULL);
 +      if ((zh = php_http_message_header(response, ZEND_STRL("Content-Length")))) {
 +              Z_TRY_ADDREF_P(zh);
 +              zend_hash_str_update(&response->hdrs, "X-Original-Content-Length", lenof("X-Original-Content-Length"), zh);
        }
 -      if ((zh = php_http_message_header(response, ZEND_STRL("Transfer-Encoding"), 0))) {
 -              zend_hash_update(&response->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), (void *) &zh, sizeof(zval *), NULL);
 -              zend_hash_del(&response->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding"));
 +      if ((zh = php_http_message_header(response, ZEND_STRL("Transfer-Encoding")))) {
 +              Z_TRY_ADDREF_P(zh);
 +              zend_hash_str_update(&response->hdrs, "X-Original-Transfer-Encoding", lenof("X-Original-Transfer-Encoding"), zh);
 +              zend_hash_str_del(&response->hdrs, "Transfer-Encoding", lenof("Transfer-Encoding"));
        }
 -      if ((zh = php_http_message_header(response, ZEND_STRL("Content-Range"), 0))) {
 -              zend_hash_update(&response->hdrs, "X-Original-Content-Range", sizeof("X-Original-Content-Range"), &zh, sizeof(zval *), NULL);
 -              zend_hash_del(&response->hdrs, "Content-Range", sizeof("Content-Range"));
 +      if ((zh = php_http_message_header(response, ZEND_STRL("Content-Range")))) {
 +              Z_TRY_ADDREF_P(zh);
 +              zend_hash_str_update(&response->hdrs, "X-Original-Content-Range", lenof("X-Original-Content-Range"), zh);
 +              zend_hash_str_del(&response->hdrs, "Content-Range", lenof("Content-Range"));
        }
 -      if ((zh = php_http_message_header(response, ZEND_STRL("Content-Encoding"), 0))) {
 -              zend_hash_update(&response->hdrs, "X-Original-Content-Encoding", sizeof("X-Original-Content-Encoding"), &zh, sizeof(zval *), NULL);
 -              zend_hash_del(&response->hdrs, "Content-Encoding", sizeof("Content-Encoding"));
 +      if ((zh = php_http_message_header(response, ZEND_STRL("Content-Encoding")))) {
 +              Z_TRY_ADDREF_P(zh);
 +              zend_hash_str_update(&response->hdrs, "X-Original-Content-Encoding", lenof("X-Original-Content-Encoding"), zh);
 +              zend_hash_str_del(&response->hdrs, "Content-Encoding", lenof("Content-Encoding"));
        }
        php_http_message_update_headers(response);
  
@@@ -664,6 -635,7 +665,6 @@@ static void php_http_curlm_responsehand
        php_http_curle_storage_t *st, *err = NULL;
        php_http_client_enqueue_t *enqueue;
        php_http_client_curl_t *curl = context->ctx;
 -      TSRMLS_FETCH_FROM_CTX(context->ts);
  
        do {
                CURLMsg *msg = curl_multi_info_read(curl->handle, &remaining);
  
                        if ((enqueue = php_http_client_enqueued(context, msg->easy_handle, compare_queue))) {
                                php_http_client_curl_handler_t *handler = enqueue->opaque;
 -                              php_http_message_t *response = php_http_curlm_responseparser(handler TSRMLS_CC);
 +                              php_http_message_t *response = php_http_curlm_responseparser(handler);
  
                                if (response) {
                                        context->callback.response.func(context->callback.response.arg, context, &handler->queue, &response);
                int i = 0;
  
                do {
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s; %s (%s)", curl_easy_strerror(err[i].errorcode), err[i].errorbuffer, STR_PTR(err[i].url));
 +                      php_error_docref(NULL, E_WARNING, "%s; %s (%s)", curl_easy_strerror(err[i].errorcode), err[i].errorbuffer, STR_PTR(err[i].url));
                        if (err[i].url) {
                                efree(err[i].url);
                        }
@@@ -743,6 -715,7 +744,6 @@@ static void php_http_curlm_timeout_call
  #endif
        if (curl->useevents) {
                CURLMcode rc;
 -              TSRMLS_FETCH_FROM_CTX(context->ts);
  
                /* ignore and use -1,0 on timeout */
                (void) socket;
                while (CURLM_CALL_MULTI_PERFORM == (rc = curl_multi_socket_action(curl->handle, CURL_SOCKET_TIMEOUT, 0, &curl->unfinished)));
  
                if (CURLM_OK != rc) {
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s",  curl_multi_strerror(rc));
 +                      php_error_docref(NULL, E_WARNING, "%s",  curl_multi_strerror(rc));
                }
  
                php_http_curlm_responsehandler(context);
@@@ -768,11 -741,12 +769,11 @@@ static void php_http_curlm_event_callba
  #endif
        if (curl->useevents) {
                CURLMcode rc = CURLM_OK;
 -              TSRMLS_FETCH_FROM_CTX(context->ts);
  
                while (CURLM_CALL_MULTI_PERFORM == (rc = curl_multi_socket_action(curl->handle, socket, etoca(action), &curl->unfinished)));
  
                if (CURLM_OK != rc) {
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", curl_multi_strerror(rc));
 +                      php_error_docref(NULL, E_WARNING, "%s", curl_multi_strerror(rc));
                }
  
                php_http_curlm_responsehandler(context);
@@@ -795,6 -769,7 +796,6 @@@ static int php_http_curlm_socket_callba
        if (curl->useevents) {
                int events = EV_PERSIST;
                php_http_curlm_event_t *ev = assign_data;
 -              TSRMLS_FETCH_FROM_CTX(context->ts);
  
                if (!ev) {
                        ev = ecalloc(1, sizeof(php_http_curlm_event_t));
                                return 0;
  
                        default:
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown socket action %d", action);
 +                              php_error_docref(NULL, E_WARNING, "Unknown socket action %d", action);
                                return -1;
                }
  
@@@ -875,7 -850,7 +876,7 @@@ static ZEND_RESULT_CODE php_http_curle_
        php_http_client_curl_handler_t *curl = userdata;
        CURL *ch = curl->handle;
  
 -      if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, Z_BVAL_P(val) ? 2 : 0)) {
 +      if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, Z_TYPE_P(val) == IS_TRUE ? 2 : 0)) {
                return FAILURE;
        }
        return SUCCESS;
@@@ -890,7 -865,7 +891,7 @@@ static ZEND_RESULT_CODE php_http_curle_
        if (storage->cookiestore) {
                pefree(storage->cookiestore, 1);
        }
 -      if (val && Z_STRLEN_P(val)) {
 +      if (val && Z_TYPE_P(val) == IS_STRING && Z_STRLEN_P(val)) {
                storage->cookiestore = pestrndup(Z_STRVAL_P(val), Z_STRLEN_P(val), 1);
        } else {
                storage->cookiestore = NULL;
@@@ -907,12 -882,11 +908,12 @@@ static ZEND_RESULT_CODE php_http_curle_
  {
        php_http_client_curl_handler_t *curl = userdata;
        CURL *ch = curl->handle;
 -      TSRMLS_FETCH_FROM_CTX(curl->client->ts);
  
        if (val && Z_TYPE_P(val) != IS_NULL) {
 +              HashTable *ht = HASH_OF(val);
 +
                if (curl->options.encode_cookies) {
 -                      if (SUCCESS == php_http_url_encode_hash_ex(HASH_OF(val), &curl->options.cookies, ZEND_STRL(";"), ZEND_STRL("="), NULL, 0 TSRMLS_CC)) {
 +                      if (SUCCESS == php_http_url_encode_hash_ex(ht, &curl->options.cookies, ZEND_STRL(";"), ZEND_STRL("="), NULL, 0)) {
                                php_http_buffer_fix(&curl->options.cookies);
                                if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIE, curl->options.cookies.data)) {
                                        return FAILURE;
                                return FAILURE;
                        }
                } else {
 -                      HashPosition pos;
 -                      php_http_array_hashkey_t cookie_key = php_http_array_hashkey_init(0);
 -                      zval **cookie_val;
 +                      php_http_arrkey_t cookie_key;
 +                      zval *cookie_val;
  
 -                      FOREACH_KEYVAL(pos, val, cookie_key, cookie_val) {
 -                              zval *zv = php_http_ztyp(IS_STRING, *cookie_val);
 +                      ZEND_HASH_FOREACH_KEY_VAL(ht, cookie_key.h, cookie_key.key, cookie_val)
 +                      {
 +                              zend_string *zs = zval_get_string(cookie_val);
  
 -                              php_http_array_hashkey_stringify(&cookie_key);
 -                              php_http_buffer_appendf(&curl->options.cookies, "%s=%s; ", cookie_key.str, Z_STRVAL_P(zv));
 -                              php_http_array_hashkey_stringfree(&cookie_key);
 +                              php_http_arrkey_stringify(&cookie_key, NULL);
 +                              php_http_buffer_appendf(&curl->options.cookies, "%s=%s; ", cookie_key.key->val, zs->val);
 +                              php_http_arrkey_dtor(&cookie_key);
  
 -                              zval_ptr_dtor(&zv);
 +                              zend_string_release(zs);
                        }
 +                      ZEND_HASH_FOREACH_END();
  
                        php_http_buffer_fix(&curl->options.cookies);
                        if (curl->options.cookies.used) {
@@@ -956,7 -929,7 +957,7 @@@ static ZEND_RESULT_CODE php_http_curle_
  {
        php_http_client_curl_handler_t *curl = userdata;
  
 -      curl->options.encode_cookies = Z_BVAL_P(val);
 +      curl->options.encode_cookies = Z_TYPE_P(val) == IS_TRUE;
        return SUCCESS;
  }
  
@@@ -964,6 -937,7 +965,6 @@@ static ZEND_RESULT_CODE php_http_curle_
  {
        php_http_client_curl_handler_t *curl = userdata;
        CURL *ch = curl->handle;
 -      TSRMLS_FETCH_FROM_CTX(curl->client->ts);
  
        if (Z_LVAL_P(val)) {
                if (Z_LVAL_P(val) > 0) {
                                return FAILURE;
                        }
                } else {
 -                      if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_TIMEVALUE, (long) sapi_get_request_time(TSRMLS_C) + Z_LVAL_P(val))) {
 +                      if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_TIMEVALUE, (long) sapi_get_request_time() + Z_LVAL_P(val))) {
                                return FAILURE;
                        }
                }
@@@ -996,7 -970,7 +997,7 @@@ static ZEND_RESULT_CODE php_http_curle_
  #if !PHP_HTTP_CURL_VERSION(7,21,6)
  #     define CURLOPT_ACCEPT_ENCODING CURLOPT_ENCODING
  #endif
 -      if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_ACCEPT_ENCODING, Z_BVAL_P(val) ? "" : NULL)) {
 +      if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_ACCEPT_ENCODING, Z_TYPE_P(val) == IS_TRUE ? "" : NULL)) {
                return FAILURE;
        }
        return SUCCESS;
@@@ -1007,7 -981,7 +1008,7 @@@ static ZEND_RESULT_CODE php_http_curle_
        php_http_client_curl_handler_t *curl = userdata;
        php_http_buffer_t header;
  
 -      if (Z_STRLEN_P(val)) {
 +      if (val && Z_TYPE_P(val) == IS_STRING && Z_STRLEN_P(val)) {
                zend_bool is_quoted = !((Z_STRVAL_P(val)[0] != '"') || (Z_STRVAL_P(val)[Z_STRLEN_P(val)-1] != '"'));
                php_http_buffer_init(&header);
                php_http_buffer_appendf(&header, is_quoted?"%s: %s":"%s: \"%s\"", curl->options.range_request?"If-Match":"If-None-Match", Z_STRVAL_P(val));
@@@ -1022,29 -996,32 +1023,29 @@@ static ZEND_RESULT_CODE php_http_curle_
  {
        php_http_client_curl_handler_t *curl = userdata;
        CURL *ch = curl->handle;
 -      TSRMLS_FETCH_FROM_CTX(curl->client->ts);
  
        php_http_buffer_reset(&curl->options.ranges);
  
        if (val && Z_TYPE_P(val) != IS_NULL) {
 -              HashPosition pos;
 -              zval **rr, **rb, **re;
 -
 -              FOREACH_VAL(pos, val, rr) {
 -                      if (Z_TYPE_PP(rr) == IS_ARRAY) {
 -                              if (2 == php_http_array_list(Z_ARRVAL_PP(rr) TSRMLS_CC, 2, &rb, &re)) {
 -                                      if (    ((Z_TYPE_PP(rb) == IS_LONG) || ((Z_TYPE_PP(rb) == IS_STRING) && is_numeric_string(Z_STRVAL_PP(rb), Z_STRLEN_PP(rb), NULL, NULL, 1))) &&
 -                                                      ((Z_TYPE_PP(re) == IS_LONG) || ((Z_TYPE_PP(re) == IS_STRING) && is_numeric_string(Z_STRVAL_PP(re), Z_STRLEN_PP(re), NULL, NULL, 1)))) {
 -                                              zval *rbl = php_http_ztyp(IS_LONG, *rb);
 -                                              zval *rel = php_http_ztyp(IS_LONG, *re);
 -
 -                                              if ((Z_LVAL_P(rbl) >= 0) && (Z_LVAL_P(rel) >= 0)) {
 -                                                      php_http_buffer_appendf(&curl->options.ranges, "%ld-%ld,", Z_LVAL_P(rbl), Z_LVAL_P(rel));
 +              zval *rr, *rb, *re;
 +              zend_long rbl, rel;
 +              HashTable *ht = HASH_OF(val);
 +
 +              ZEND_HASH_FOREACH_VAL(ht, rr)
 +              {
 +                      if (Z_TYPE_P(rr) == IS_ARRAY) {
 +                              if (2 == php_http_array_list(Z_ARRVAL_P(rr), 2, &rb, &re)) {
 +                                      if (    ((Z_TYPE_P(rb) == IS_LONG) || ((Z_TYPE_P(rb) == IS_STRING) && is_numeric_string(Z_STRVAL_P(rb), Z_STRLEN_P(rb), &rbl, NULL, 1))) &&
 +                                                      ((Z_TYPE_P(re) == IS_LONG) || ((Z_TYPE_P(re) == IS_STRING) && is_numeric_string(Z_STRVAL_P(re), Z_STRLEN_P(re), &rel, NULL, 1)))) {
 +                                              if ((rbl >= 0) && (rel >= 0)) {
 +                                                      php_http_buffer_appendf(&curl->options.ranges, "%ld-%ld,", rbl, rel);
                                                }
 -                                              zval_ptr_dtor(&rbl);
 -                                              zval_ptr_dtor(&rel);
                                        }
  
                                }
                        }
                }
 +              ZEND_HASH_FOREACH_END();
  
                if (curl->options.ranges.used) {
                        curl->options.range_request = 1;
@@@ -1107,16 -1084,26 +1108,16 @@@ static ZEND_RESULT_CODE php_http_curle_
        php_http_client_curl_handler_t *curl = userdata;
        CURL *ch = curl->handle;
        long localport = 0, localportrange = 0;
 -      TSRMLS_FETCH_FROM_CTX(curl->client->ts);
  
        if (val && Z_TYPE_P(val) != IS_NULL) {
 -              zval **z_port_start, *zps_copy = NULL, **z_port_end, *zpe_copy = NULL;
 +              zval *zps, *zpe;
  
 -              switch (php_http_array_list(Z_ARRVAL_P(val) TSRMLS_CC, 2, &z_port_start, &z_port_end)) {
 +              switch (php_http_array_list(Z_ARRVAL_P(val), 2, &zps, &zpe)) {
                case 2:
 -                      zps_copy = php_http_ztyp(IS_LONG, *z_port_start);
 -                      zpe_copy = php_http_ztyp(IS_LONG, *z_port_end);
 -                      localportrange = labs(Z_LVAL_P(zps_copy)-Z_LVAL_P(zpe_copy))+1L;
 +                      localportrange = labs(zval_get_long(zps)-zval_get_long(zpe))+1L;
                        /* no break */
                case 1:
 -                      if (!zps_copy) {
 -                              zps_copy = php_http_ztyp(IS_LONG, *z_port_start);
 -                      }
 -                      localport = (zpe_copy && Z_LVAL_P(zpe_copy) > 0) ? MIN(Z_LVAL_P(zps_copy), Z_LVAL_P(zpe_copy)) : Z_LVAL_P(zps_copy);
 -                      zval_ptr_dtor(&zps_copy);
 -                      if (zpe_copy) {
 -                              zval_ptr_dtor(&zpe_copy);
 -                      }
 +                      localport = (zval_get_long(zpe) > 0) ? MIN(zval_get_long(zps), zval_get_long(zpe)) : zval_get_long(zps);
                        break;
                default:
                        break;
  static ZEND_RESULT_CODE php_http_curle_option_set_proxyheader(php_http_option_t *opt, zval *val, void *userdata)
  {
        php_http_client_curl_handler_t *curl = userdata;
 -      TSRMLS_FETCH_FROM_CTX(curl->client->ts);
  
        if (val && Z_TYPE_P(val) != IS_NULL) {
 -              php_http_array_hashkey_t header_key = php_http_array_hashkey_init(0);
 -              zval **header_val, *header_cpy;
 -              HashPosition pos;
 +              php_http_arrkey_t header_key;
 +              zval *header_val;
                php_http_buffer_t header;
  
                php_http_buffer_init(&header);
 -              FOREACH_KEYVAL(pos, val, header_key, header_val) {
 -                      if (header_key.type == HASH_KEY_IS_STRING) {
 -                              header_cpy = php_http_ztyp(IS_STRING, *header_val);
 -                              php_http_buffer_appendf(&header, "%s: %s", header_key.str, Z_STRVAL_P(header_cpy));
 +              ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(val), header_key.h, header_key.key, header_val)
 +              {
 +                      if (header_key.key) {
 +                              zend_string *zs = zval_get_string(header_val);
 +
 +                              php_http_buffer_appendf(&header, "%s: %s", header_key.key->val, zs->val);
 +                              zend_string_release(zs);
 +
                                php_http_buffer_fix(&header);
                                curl->options.proxyheaders = curl_slist_append(curl->options.proxyheaders, header.data);
                                php_http_buffer_reset(&header);
  
 -                              zval_ptr_dtor(&header_cpy);
                        }
                }
 +              ZEND_HASH_FOREACH_END();
                php_http_buffer_dtor(&header);
        }
        if (CURLE_OK != curl_easy_setopt(curl->handle, CURLOPT_PROXYHEADER, curl->options.proxyheaders)) {
@@@ -1174,18 -1159,18 +1175,18 @@@ static ZEND_RESULT_CODE php_http_curle_
  {
        php_http_client_curl_handler_t *curl = userdata;
        CURL *ch = curl->handle;
 -      TSRMLS_FETCH_FROM_CTX(curl->client->ts);
  
        if (val && Z_TYPE_P(val) != IS_NULL) {
 -              php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
 -              HashPosition pos;
 -              zval **data;
 +              HashTable *ht = HASH_OF(val);
 +              zval *data;
  
 -              FOREACH_KEYVAL(pos, val, key, data) {
 -                      zval *cpy = php_http_ztyp(IS_STRING, *data);
 -                      curl->options.resolve = curl_slist_append(curl->options.resolve, Z_STRVAL_P(cpy));
 -                      zval_ptr_dtor(&cpy);
 +              ZEND_HASH_FOREACH_VAL(ht, data)
 +              {
 +                      zend_string *zs = zval_get_string(data);
 +                      curl->options.resolve = curl_slist_append(curl->options.resolve, zs->val);
 +                      zend_string_release(zs);
                }
 +              ZEND_HASH_FOREACH_END();
  
                if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_RESOLVE, curl->options.resolve)) {
                        return FAILURE;
@@@ -1223,7 -1208,7 +1224,7 @@@ static ZEND_RESULT_CODE php_http_curle_
  }
  #endif
  
 -static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
 +static void php_http_curle_options_init(php_http_options_t *registry)
  {
        php_http_option_t *opt;
  
        if ((opt = php_http_option_register(registry, ZEND_STRL("proxyauthtype"), CURLOPT_PROXYAUTH, IS_LONG))) {
                Z_LVAL(opt->defval) = CURLAUTH_ANYSAFE;
        }
 -      php_http_option_register(registry, ZEND_STRL("proxytunnel"), CURLOPT_HTTPPROXYTUNNEL, IS_BOOL);
 +      php_http_option_register(registry, ZEND_STRL("proxytunnel"), CURLOPT_HTTPPROXYTUNNEL, _IS_BOOL);
  #if PHP_HTTP_CURL_VERSION(7,19,4)
        php_http_option_register(registry, ZEND_STRL("noproxy"), CURLOPT_NOPROXY, IS_STRING);
  #endif
                opt->setter = php_http_curle_option_set_proxyheader;
        }
  #endif
+ #if PHP_HTTP_CURL_VERSION(7,43,0)
+       if ((opt = php_http_option_register(registry, ZEND_STRL("proxy_service_name"), CURLOPT_PROXY_SERVICE_NAME, IS_STRING))) {
+               opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+       }
+ #endif
  
  #if PHP_HTTP_CURL_VERSION(7,40,0)
        if ((opt = php_http_option_register(registry, ZEND_STRL("unix_socket_path"), CURLOPT_UNIX_SOCKET_PATH, IS_STRING))) {
                Z_LVAL(opt->defval) = 5;
        }
        */
 -      php_http_option_register(registry, ZEND_STRL("fresh_connect"), CURLOPT_FRESH_CONNECT, IS_BOOL);
 -      php_http_option_register(registry, ZEND_STRL("forbid_reuse"), CURLOPT_FORBID_REUSE, IS_BOOL);
 +      php_http_option_register(registry, ZEND_STRL("fresh_connect"), CURLOPT_FRESH_CONNECT, _IS_BOOL);
 +      php_http_option_register(registry, ZEND_STRL("forbid_reuse"), CURLOPT_FORBID_REUSE, _IS_BOOL);
  
        /* outgoing interface */
        php_http_option_register(registry, ZEND_STRL("interface"), CURLOPT_INTERFACE, IS_STRING);
        if ((opt = php_http_option_register(registry, ZEND_STRL("httpauthtype"), CURLOPT_HTTPAUTH, IS_LONG))) {
                Z_LVAL(opt->defval) = CURLAUTH_ANYSAFE;
        }
+ #if PHP_HTTP_CURL_VERSION(7,43,0)
+       if ((opt = php_http_option_register(registry, ZEND_STRL("service_name"), CURLOPT_SERVICE_NAME, IS_STRING))) {
+               opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+       }
+ #endif
  
        /* redirects */
        if ((opt = php_http_option_register(registry, ZEND_STRL("redirect"), CURLOPT_FOLLOWLOCATION, IS_LONG))) {
                opt->setter = php_http_curle_option_set_redirect;
        }
 -      php_http_option_register(registry, ZEND_STRL("unrestricted_auth"), CURLOPT_UNRESTRICTED_AUTH, IS_BOOL);
 +      php_http_option_register(registry, ZEND_STRL("unrestricted_auth"), CURLOPT_UNRESTRICTED_AUTH, _IS_BOOL);
  #if PHP_HTTP_CURL_VERSION(7,19,1)
        php_http_option_register(registry, ZEND_STRL("postredir"), CURLOPT_POSTREDIR, IS_LONG);
  #endif
        if ((opt = php_http_option_register(registry, ZEND_STRL("referer"), CURLOPT_REFERER, IS_STRING))) {
                opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
        }
 -      if ((opt = php_http_option_register(registry, ZEND_STRL("autoreferer"), CURLOPT_AUTOREFERER, IS_BOOL))) {
 +      if ((opt = php_http_option_register(registry, ZEND_STRL("autoreferer"), CURLOPT_AUTOREFERER, _IS_BOOL))) {
                ZVAL_BOOL(&opt->defval, 1);
        }
  
        /* useragent */
        if ((opt = php_http_option_register(registry, ZEND_STRL("useragent"), CURLOPT_USERAGENT, IS_STRING))) {
                /* don't check strlen, to allow sending no useragent at all */
 -              ZVAL_STRING(&opt->defval,
 +              ZVAL_PSTRING(&opt->defval,
                                "PECL_HTTP/" PHP_PECL_HTTP_VERSION " "
                                "PHP/" PHP_VERSION " "
 -                              "libcurl/" LIBCURL_VERSION
 -                      , 0);
 +                              "libcurl/" LIBCURL_VERSION);
        }
  
        /* resume */
        }
  
        /* compression */
 -      if ((opt = php_http_option_register(registry, ZEND_STRL("compress"), 0, IS_BOOL))) {
 +      if ((opt = php_http_option_register(registry, ZEND_STRL("compress"), 0, _IS_BOOL))) {
                opt->setter = php_http_curle_option_set_compress;
        }
  
        }
  
        /* cookies */
 -      if ((opt = php_http_option_register(registry, ZEND_STRL("encodecookies"), 0, IS_BOOL))) {
 +      if ((opt = php_http_option_register(registry, ZEND_STRL("encodecookies"), 0, _IS_BOOL))) {
                opt->setter = php_http_curle_option_set_encodecookies;
                ZVAL_BOOL(&opt->defval, 1);
        }
        }
  
        /* cookiesession, don't load session cookies from cookiestore */
 -      php_http_option_register(registry, ZEND_STRL("cookiesession"), CURLOPT_COOKIESESSION, IS_BOOL);
 +      php_http_option_register(registry, ZEND_STRL("cookiesession"), CURLOPT_COOKIESESSION, _IS_BOOL);
        /* cookiestore, read initial cookies from that file and store cookies back into that file */
        if ((opt = php_http_option_register(registry, ZEND_STRL("cookiestore"), 0, IS_STRING))) {
                opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
  #endif
  
        /* tcp */
 -      php_http_option_register(registry, ZEND_STRL("tcp_nodelay"), CURLOPT_TCP_NODELAY, IS_BOOL);
 +      php_http_option_register(registry, ZEND_STRL("tcp_nodelay"), CURLOPT_TCP_NODELAY, _IS_BOOL);
  #if PHP_HTTP_CURL_VERSION(7,25,0)
 -      php_http_option_register(registry, ZEND_STRL("tcp_keepalive"), CURLOPT_TCP_KEEPALIVE, IS_BOOL);
 +      php_http_option_register(registry, ZEND_STRL("tcp_keepalive"), CURLOPT_TCP_KEEPALIVE, _IS_BOOL);
        if ((opt = php_http_option_register(registry, ZEND_STRL("tcp_keepidle"), CURLOPT_TCP_KEEPIDLE, IS_LONG))) {
                Z_LVAL(opt->defval) = 60;
        }
                }
                if ((opt = php_http_option_register(registry, ZEND_STRL("certtype"), CURLOPT_SSLCERTTYPE, IS_STRING))) {
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
 -                      ZVAL_STRING(&opt->defval, "PEM", 0);
 +                      ZVAL_PSTRING(&opt->defval, "PEM");
                }
                if ((opt = php_http_option_register(registry, ZEND_STRL("key"), CURLOPT_SSLKEY, IS_STRING))) {
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
                }
                if ((opt = php_http_option_register(registry, ZEND_STRL("keytype"), CURLOPT_SSLKEYTYPE, IS_STRING))) {
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
 -                      ZVAL_STRING(&opt->defval, "PEM", 0);
 +                      ZVAL_PSTRING(&opt->defval, "PEM");
                }
                if ((opt = php_http_option_register(registry, ZEND_STRL("keypasswd"), CURLOPT_SSLKEYPASSWD, IS_STRING))) {
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
                }
                php_http_option_register(registry, ZEND_STRL("engine"), CURLOPT_SSLENGINE, IS_STRING);
                php_http_option_register(registry, ZEND_STRL("version"), CURLOPT_SSLVERSION, IS_LONG);
 -              if ((opt = php_http_option_register(registry, ZEND_STRL("verifypeer"), CURLOPT_SSL_VERIFYPEER, IS_BOOL))) {
 +              if ((opt = php_http_option_register(registry, ZEND_STRL("verifypeer"), CURLOPT_SSL_VERIFYPEER, _IS_BOOL))) {
                        ZVAL_BOOL(&opt->defval, 1);
                }
 -              if ((opt = php_http_option_register(registry, ZEND_STRL("verifyhost"), CURLOPT_SSL_VERIFYHOST, IS_BOOL))) {
 +              if ((opt = php_http_option_register(registry, ZEND_STRL("verifyhost"), CURLOPT_SSL_VERIFYHOST, _IS_BOOL))) {
                        ZVAL_BOOL(&opt->defval, 1);
                        opt->setter = php_http_curle_option_set_ssl_verifyhost;
                }
  #if PHP_HTTP_CURL_VERSION(7,41,0)
 -              php_http_option_register(registry, ZEND_STRL("verifystatus"), CURLOPT_SSL_VERIFYSTATUS, IS_BOOL);
 +              php_http_option_register(registry, ZEND_STRL("verifystatus"), CURLOPT_SSL_VERIFYSTATUS, _IS_BOOL);
  #endif
                php_http_option_register(registry, ZEND_STRL("cipher_list"), CURLOPT_SSL_CIPHER_LIST, IS_STRING);
                if ((opt = php_http_option_register(registry, ZEND_STRL("cainfo"), CURLOPT_CAINFO, IS_STRING))) {
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR;
  #ifdef PHP_HTTP_CURL_CAINFO
 -                      ZVAL_STRING(&opt->defval, PHP_HTTP_CURL_CAINFO, 0);
 +                      ZVAL_PSTRING(&opt->defval, PHP_HTTP_CURL_CAINFO);
  #endif
                }
                if ((opt = php_http_option_register(registry, ZEND_STRL("capath"), CURLOPT_CAPATH, IS_STRING))) {
                }
  #     endif
  #endif
- #if PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)
-               php_http_option_register(registry, ZEND_STRL("certinfo"), CURLOPT_CERTINFO, _IS_BOOL);
+ #if (PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)) || (PHP_HTTP_CURL_VERSION(7,34,0) && defined(PHP_HTTP_HAVE_NSS)) || (PHP_HTTP_CURL_VERSION(7,42,0) && defined(PHP_HTTP_HAVE_GNUTLS)) || (PHP_HTTP_CURL_VERSION(7,39,0) && defined(PHP_HTTP_HAVE_GSKIT))
 -              php_http_option_register(registry, ZEND_STRL("certinfo"), CURLOPT_CERTINFO, IS_BOOL);
++              if ((opt = php_http_option_register(registry, ZEND_STRL("certinfo"), CURLOPT_CERTINFO, _IS_BOOL))) {
++                      ZVAL_FALSE(&opt->defval);
++              }
  #endif
  #if PHP_HTTP_CURL_VERSION(7,36,0)
 -              if ((opt = php_http_option_register(registry, ZEND_STRL("enable_npn"), CURLOPT_SSL_ENABLE_NPN, IS_BOOL))) {
 +              if ((opt = php_http_option_register(registry, ZEND_STRL("enable_npn"), CURLOPT_SSL_ENABLE_NPN, _IS_BOOL))) {
                        ZVAL_BOOL(&opt->defval, 1);
                }
 -              if ((opt = php_http_option_register(registry, ZEND_STRL("enable_alpn"), CURLOPT_SSL_ENABLE_ALPN, IS_BOOL))) {
 +              if ((opt = php_http_option_register(registry, ZEND_STRL("enable_alpn"), CURLOPT_SSL_ENABLE_ALPN, _IS_BOOL))) {
                        ZVAL_BOOL(&opt->defval, 1);
                }
  #endif
                if ((opt = php_http_option_register(registry, ZEND_STRL("tlsauthpass"), CURLOPT_TLSAUTH_PASSWORD, IS_STRING))) {
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
                }
 -              php_http_option_register(registry, ZEND_STRL("falsestart"), CURLOPT_SSL_FALSESTART, IS_BOOL);
+ #endif
+ #if PHP_HTTP_CURL_VERSION(7,42,0) && (defined(PHP_HTTP_HAVE_NSS) || defined(PHP_HTTP_HAVE_DARWINSSL))
++              php_http_option_register(registry, ZEND_STRL("falsestart"), CURLOPT_SSL_FALSESTART, _IS_BOOL);
  #endif
        }
  }
@@@ -1540,12 -1539,8 +1556,12 @@@ static zval *php_http_curle_get_option(
        zval *option;
  
        if ((option = php_http_option_get(opt, options, NULL))) {
 -              option = php_http_ztyp(opt->type, option);
 -              zend_hash_quick_update(&curl->options.cache, opt->name.s, opt->name.l, opt->name.h, &option, sizeof(zval *), NULL);
 +              zval zopt;
 +
 +              ZVAL_DUP(&zopt, option);
 +              convert_to_explicit_type(&zopt, opt->type);
 +              zend_hash_update(&curl->options.cache, opt->name, &zopt);
 +              return zend_hash_find(&curl->options.cache, opt->name);
        }
        return option;
  }
@@@ -1557,16 -1552,17 +1573,16 @@@ static ZEND_RESULT_CODE php_http_curle_
        zval tmp;
        CURLcode rc = CURLE_OK;
        ZEND_RESULT_CODE rv = SUCCESS;
 -      TSRMLS_FETCH_FROM_CTX(curl->client->ts);
  
        if (!val) {
                val = &opt->defval;
        }
  
        switch (opt->type) {
 -      case IS_BOOL:
 +      case _IS_BOOL:
                if (opt->setter) {
                        rv = opt->setter(opt, val, curl);
 -              } else if (CURLE_OK != curl_easy_setopt(ch, opt->option, (long) Z_BVAL_P(val))) {
 +              } else if (CURLE_OK != curl_easy_setopt(ch, opt->option, (long) (Z_TYPE_P(val) == IS_TRUE))) {
                        rv = FAILURE;
                }
                break;
        case IS_STRING:
                if (opt->setter) {
                        rv = opt->setter(opt, val, curl);
 +              } else if (!val || Z_TYPE_P(val) == IS_NULL) {
 +                      if (CURLE_OK != (rc = curl_easy_setopt(ch, opt->option, NULL))) {
 +                              rv = FAILURE;
 +                      }
                } else if ((opt->flags & PHP_HTTP_CURLE_OPTION_CHECK_STRLEN) && !Z_STRLEN_P(val)) {
                        if (CURLE_OK != (rc = curl_easy_setopt(ch, opt->option, NULL))) {
                                rv = FAILURE;
                        }
 -              } else if ((opt->flags & PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR) && Z_STRVAL_P(val) && SUCCESS != php_check_open_basedir(Z_STRVAL_P(val) TSRMLS_CC)) {
 +              } else if ((opt->flags & PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR) && Z_STRVAL_P(val) && SUCCESS != php_check_open_basedir(Z_STRVAL_P(val))) {
                        if (CURLE_OK != (rc = curl_easy_setopt(ch, opt->option, NULL))) {
                                rv = FAILURE;
                        }
                break;
        }
        if (rv != SUCCESS) {
 -              php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not set option %s (%s)", opt->name.s, curl_easy_strerror(rc));
 +              php_error_docref(NULL, E_NOTICE, "Could not set option %s (%s)", opt->name->val, curl_easy_strerror(rc));
        }
        return rv;
  }
@@@ -1642,10 -1634,12 +1658,10 @@@ static ZEND_RESULT_CODE php_http_curlm_
        CURLM *ch = curl->handle;
        HashTable tmp_ht;
        char **bl = NULL;
 -      TSRMLS_FETCH_FROM_CTX(client->ts);
  
        /* array of char *, ending with a NULL */
        if (value && Z_TYPE_P(value) != IS_NULL) {
 -              zval **entry;
 -              HashPosition pos;
 +              zval *entry;
                HashTable *ht = HASH_OF(value);
                int c = zend_hash_num_elements(ht);
                char **ptr = ecalloc(c + 1, sizeof(char *));
                zend_hash_init(&tmp_ht, c, NULL, ZVAL_PTR_DTOR, 0);
                array_join(ht, &tmp_ht, 0, ARRAY_JOIN_STRINGIFY);
  
 -              FOREACH_HASH_VAL(pos, &tmp_ht, entry) {
 -                      *ptr++ = Z_STRVAL_PP(entry);
 +              ZEND_HASH_FOREACH_VAL(&tmp_ht, entry)
 +              {
 +                      *ptr++ = Z_STRVAL_P(entry);
                }
 +              ZEND_HASH_FOREACH_END();
        }
  
        if (CURLM_OK != curl_multi_setopt(ch, opt->option, bl)) {
@@@ -1708,11 -1700,11 +1724,11 @@@ static ZEND_RESULT_CODE php_http_curlm_
  {
        php_http_client_t *client = userdata;
  
 -      return php_http_curlm_use_eventloop(client, value && Z_BVAL_P(value));
 +      return php_http_curlm_use_eventloop(client, value && Z_TYPE_P(value) == IS_TRUE);
  }
  #endif
  
 -static void php_http_curlm_options_init(php_http_options_t *registry TSRMLS_DC)
 +static void php_http_curlm_options_init(php_http_options_t *registry)
  {
        php_http_option_t *opt;
  
        php_http_option_register(registry, ZEND_STRL("max_total_connections"), CURLMOPT_MAX_TOTAL_CONNECTIONS, IS_LONG);
  #endif
        /* enable/disable HTTP pipelining */
 -      php_http_option_register(registry, ZEND_STRL("pipelining"), CURLMOPT_PIPELINING, IS_BOOL);
 +      php_http_option_register(registry, ZEND_STRL("pipelining"), CURLMOPT_PIPELINING, _IS_BOOL);
        /* chunk length threshold for pipelining */
  #if PHP_HTTP_CURL_VERSION(7,30,0)
        php_http_option_register(registry, ZEND_STRL("chunk_length_penalty_size"), CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, IS_LONG);
  #endif
        /* events */
  #if PHP_HTTP_HAVE_EVENT
 -      if ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, IS_BOOL))) {
 +      if ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, _IS_BOOL))) {
                opt->setter = php_http_curlm_option_set_use_eventloop;
        }
  #endif
@@@ -1773,24 -1765,20 +1789,24 @@@ static ZEND_RESULT_CODE php_http_curlm_
        zval *orig = val;
        CURLMcode rc = CURLM_UNKNOWN_OPTION;
        ZEND_RESULT_CODE rv = SUCCESS;
 -      TSRMLS_FETCH_FROM_CTX(client->ts);
  
        if (!val) {
                val = &opt->defval;
        } else if (opt->type && Z_TYPE_P(val) != opt->type && !(Z_TYPE_P(val) == IS_NULL && opt->type == IS_ARRAY)) {
 -              val = php_http_ztyp(opt->type, val);
 +              zval zopt;
 +
 +              ZVAL_DUP(&zopt, val);
 +              convert_to_explicit_type(&zopt, opt->type);
 +
 +              val = &zopt;
        }
  
        if (opt->setter) {
                rv = opt->setter(opt, val, client);
        } else {
                switch (opt->type) {
 -              case IS_BOOL:
 -                      if (CURLM_OK != (rc = curl_multi_setopt(ch, opt->option, (long) Z_BVAL_P(val)))) {
 +              case _IS_BOOL:
 +                      if (CURLM_OK != (rc = curl_multi_setopt(ch, opt->option, (long) zend_is_true(val)))) {
                                rv = FAILURE;
                        }
                        break;
        }
  
        if (val && val != orig && val != &opt->defval) {
 -              zval_ptr_dtor(&val);
 +              zval_ptr_dtor(val);
        }
  
        if (rv != SUCCESS) {
 -              php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not set option %s (%s)", opt->name.s, curl_easy_strerror(rc));
 +              php_error_docref(NULL, E_NOTICE, "Could not set option %s (%s)", opt->name->val, curl_easy_strerror(rc));
        }
        return rv;
  }
@@@ -1876,9 -1864,10 +1892,9 @@@ static php_http_client_curl_handler_t *
  {
        void *handle;
        php_http_client_curl_handler_t *handler;
 -      TSRMLS_FETCH_FROM_CTX(h->ts);
  
 -      if (!(handle = php_resource_factory_handle_ctor(rf, NULL TSRMLS_CC))) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to initialize curl handle");
 +      if (!(handle = php_resource_factory_handle_ctor(rf, NULL))) {
 +              php_error_docref(NULL, E_WARNING, "Failed to initialize curl handle");
                return NULL;
        }
  
        handler->rf = rf;
        handler->client = h;
        handler->handle = handle;
 -      handler->response.body = php_http_message_body_init(NULL, NULL TSRMLS_CC);
 +      handler->response.body = php_http_message_body_init(NULL, NULL);
        php_http_buffer_init(&handler->response.headers);
        php_http_buffer_init(&handler->options.cookies);
        php_http_buffer_init(&handler->options.ranges);
@@@ -1927,10 -1916,11 +1943,10 @@@ static ZEND_RESULT_CODE php_http_client
        size_t body_size;
        php_http_message_t *msg = enqueue->request;
        php_http_curle_storage_t *storage = php_http_curle_get_storage(curl->handle);
 -      TSRMLS_FETCH_FROM_CTX(curl->client->ts);
  
        /* request url */
        if (!PHP_HTTP_INFO(msg).request.url) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot request empty URL");
 +              php_error_docref(NULL, E_WARNING, "Cannot request empty URL");
                return FAILURE;
        }
        storage->errorbuffer[0] = '\0';
        /* request headers */
        php_http_message_update_headers(msg);
        if (zend_hash_num_elements(&msg->hdrs)) {
 -              php_http_array_hashkey_t header_key = php_http_array_hashkey_init(0);
 -              zval **header_val, *header_cpy;
 -              HashPosition pos;
 +              php_http_arrkey_t header_key;
 +              zval *header_val;
 +              zend_string *header_str;
                php_http_buffer_t header;
  #if !PHP_HTTP_CURL_VERSION(7,23,0)
 -              zval **ct = NULL;
 -
 -              zend_hash_find(&msg->hdrs, ZEND_STRS("Content-Length"), (void *) &ct);
 +              zval *ct = zend_hash_str_find(&msg->hdrs, ZEND_STRL("Content-Length"));
  #endif
  
                php_http_buffer_init(&header);
 -              FOREACH_HASH_KEYVAL(pos, &msg->hdrs, header_key, header_val) {
 -                      if (header_key.type == HASH_KEY_IS_STRING) {
 +              ZEND_HASH_FOREACH_KEY_VAL(&msg->hdrs, header_key.h, header_key.key, header_val)
 +              {
 +                      if (header_key.key) {
  #if !PHP_HTTP_CURL_VERSION(7,23,0)
                                /* avoid duplicate content-length header */
 -                              if (ct && *ct == *header_val) {
 +                              if (ct && ct == header_val) {
                                        continue;
                                }
  #endif
 -                              header_cpy = php_http_ztyp(IS_STRING, *header_val);
 -                              php_http_buffer_appendf(&header, "%s: %s", header_key.str, Z_STRVAL_P(header_cpy));
 +                              header_str = zval_get_string(header_val);
 +                              php_http_buffer_appendf(&header, "%s: %s", header_key.key->val, header_str->val);
                                php_http_buffer_fix(&header);
                                curl->options.headers = curl_slist_append(curl->options.headers, header.data);
                                php_http_buffer_reset(&header);
 -
 -                              zval_ptr_dtor(&header_cpy);
 +                              zend_string_release(header_str);
                        }
                }
 +              ZEND_HASH_FOREACH_END();
                php_http_buffer_dtor(&header);
        }
        curl_easy_setopt(curl->handle, CURLOPT_HTTPHEADER, curl->options.headers);
                        curl_easy_setopt(curl->handle, CURLOPT_CUSTOMREQUEST, PHP_HTTP_INFO(msg).request.method);
                }
        } else {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot use empty request method");
 +              php_error_docref(NULL, E_WARNING, "Cannot use empty request method");
                return FAILURE;
        }
  
@@@ -2038,9 -2029,11 +2054,9 @@@ static void php_http_client_curl_handle
  
  static void php_http_client_curl_handler_dtor(php_http_client_curl_handler_t *handler)
  {
 -      TSRMLS_FETCH_FROM_CTX(handler->client->ts);
 -
        php_http_client_curl_handler_clear(handler);
  
 -      php_resource_factory_handle_dtor(handler->rf, handler->handle TSRMLS_CC);
 +      php_resource_factory_handle_dtor(handler->rf, handler->handle);
        php_resource_factory_free(&handler->rf);
  
        php_http_message_body_free(&handler->response.body);
        php_http_buffer_dtor(&handler->options.cookies);
        zend_hash_destroy(&handler->options.cache);
  
 +#if PHP_HTTP_CURL_VERSION(7,21,3)
 +      if (handler->options.resolve) {
 +              curl_slist_free_all(handler->options.resolve);
 +              handler->options.resolve = NULL;
 +      }
 +#endif
 +
        if (handler->options.headers) {
                curl_slist_free_all(handler->options.headers);
                handler->options.headers = NULL;
        }
  
 +      if (handler->options.proxyheaders) {
 +              curl_slist_free_all(handler->options.proxyheaders);
 +              handler->options.proxyheaders = NULL;
 +      }
 +
        efree(handler);
  }
  
  static php_http_client_t *php_http_client_curl_init(php_http_client_t *h, void *handle)
  {
        php_http_client_curl_t *curl;
 -      TSRMLS_FETCH_FROM_CTX(h->ts);
  
 -      if (!handle && !(handle = php_resource_factory_handle_ctor(h->rf, NULL TSRMLS_CC))) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to initialize curl handle");
 +      if (!handle && !(handle = php_resource_factory_handle_ctor(h->rf, NULL))) {
 +              php_error_docref(NULL, E_WARNING, "Failed to initialize curl handle");
                return NULL;
        }
  
  static void php_http_client_curl_dtor(php_http_client_t *h)
  {
        php_http_client_curl_t *curl = h->ctx;
 -      TSRMLS_FETCH_FROM_CTX(h->ts);
  
  #if PHP_HTTP_HAVE_EVENT
        if (curl->timeout) {
  #endif
        curl->unfinished = 0;
  
 -      php_resource_factory_handle_dtor(h->rf, curl->handle TSRMLS_CC);
 +      php_resource_factory_handle_dtor(h->rf, curl->handle);
  
        efree(curl);
        h->ctx = NULL;
@@@ -2122,37 -2105,36 +2138,37 @@@ static void queue_dtor(php_http_client_
        php_http_client_curl_handler_dtor(handler);
  }
  
 -static php_resource_factory_t *create_rf(php_http_client_t *h, php_http_client_enqueue_t *enqueue TSRMLS_DC)
 +static php_resource_factory_t *create_rf(php_http_client_t *h, php_http_client_enqueue_t *enqueue)
  {
        php_persistent_handle_factory_t *pf = NULL;
        php_resource_factory_t *rf = NULL;
        php_http_url_t *url = enqueue->request->http.info.request.url;
  
        if (!url || (!url->host && !url->path)) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot request empty URL");
 +              php_error_docref(NULL, E_WARNING, "Cannot request empty URL");
                return NULL;
        }
  
        /* only if the client itself is setup for persistence */
        if (php_resource_factory_is_persistent(h->rf)) {
 +              zend_string *id;
                char *id_str = NULL;
                size_t id_len;
                int port = url->port ? url->port : 80;
 -              zval **zport;
 +              zval *zport;
  
 -              if (SUCCESS == zend_hash_find(enqueue->options, ZEND_STRS("port"), (void *) &zport)) {
 -                      zval *zcpy = php_http_ztyp(IS_LONG, *zport);
 +              if ((zport = zend_hash_str_find(enqueue->options, ZEND_STRL("port")))) {
 +                      zend_long lport = zval_get_long(zport);
  
 -                      if (Z_LVAL_P(zcpy)) {
 -                              port = Z_LVAL_P(zcpy);
 +                      if (lport > 0) {
 +                              port = lport;
                        }
 -                      zval_ptr_dtor(&zcpy);
                }
  
                id_len = spprintf(&id_str, 0, "%s:%d", STR_PTR(url->host), port);
 -              pf = php_persistent_handle_concede(NULL, ZEND_STRL("http\\Client\\Curl\\Request"), id_str, id_len, NULL, NULL TSRMLS_CC);
 -              efree(id_str);
 +              id = php_http_cs2zs(id_str, id_len);
 +              pf = php_persistent_handle_concede(NULL, PHP_HTTP_G->client.curl.driver.request_name, id, NULL, NULL);
 +              zend_string_release(id);
        }
  
        if (pf) {
@@@ -2171,8 -2153,9 +2187,8 @@@ static ZEND_RESULT_CODE php_http_client
        php_http_client_curl_handler_t *handler;
        php_http_client_progress_state_t *progress;
        php_resource_factory_t *rf;
 -      TSRMLS_FETCH_FROM_CTX(h->ts);
  
 -      rf = create_rf(h, enqueue TSRMLS_CC);
 +      rf = create_rf(h, enqueue);
        if (!rf) {
                return FAILURE;
        }
  
                return SUCCESS;
        } else {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not enqueue request: %s", curl_multi_strerror(rs));
 +              php_error_docref(NULL, E_WARNING, "Could not enqueue request: %s", curl_multi_strerror(rs));
                return FAILURE;
        }
  }
@@@ -2213,13 -2196,14 +2229,13 @@@ static ZEND_RESULT_CODE php_http_client
        CURLMcode rs;
        php_http_client_curl_t *curl = h->ctx;
        php_http_client_curl_handler_t *handler = enqueue->opaque;
 -      TSRMLS_FETCH_FROM_CTX(h->ts);
  
        php_http_client_curl_handler_clear(handler);
        if (CURLM_OK == (rs = curl_multi_remove_handle(curl->handle, handler->handle))) {
                zend_llist_del_element(&h->requests, handler->handle, (int (*)(void *, void *)) compare_queue);
                return SUCCESS;
        } else {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not dequeue request: %s", curl_multi_strerror(rs));
 +              php_error_docref(NULL, E_WARNING, "Could not dequeue request: %s", curl_multi_strerror(rs));
        }
  
        return FAILURE;
@@@ -2318,7 -2302,10 +2334,7 @@@ static ZEND_RESULT_CODE php_http_client
  {
  #if PHP_HTTP_HAVE_EVENT
        php_http_client_curl_t *curl = h->ctx;
 -#endif
 -      TSRMLS_FETCH_FROM_CTX(h->ts);
  
 -#if PHP_HTTP_HAVE_EVENT
        if (curl->useevents) {
                php_http_curlm_timeout_callback(CURL_SOCKET_TIMEOUT, /*EV_READ|EV_WRITE*/0, h);
                do {
  #endif
  
                        if (ev_rc < 0) {
 -                              php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error in event_base_dispatch()");
 +                              php_error_docref(NULL, E_ERROR, "Error in event_base_dispatch()");
                                return FAILURE;
                        }
                } while (curl->unfinished && !EG(exception));
                        if (SUCCESS != php_http_client_curl_wait(h, NULL)) {
  #ifdef PHP_WIN32
                                /* see http://msdn.microsoft.com/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp */
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING, "WinSock error: %d", WSAGetLastError());
 +                              php_error_docref(NULL, E_WARNING, "WinSock error: %d", WSAGetLastError());
  #else
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
 +                              php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
  #endif
                                return FAILURE;
                        }
@@@ -2379,31 -2366,34 +2395,31 @@@ static ZEND_RESULT_CODE php_http_client
        return SUCCESS;
  }
  
 -static int apply_available_options(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
 +static int apply_available_options(zval *pDest, int num_args, va_list args, zend_hash_key *hash_key)
  {
 -      php_http_option_t *opt = pDest;
 +      php_http_option_t *opt = Z_PTR_P(pDest);
        HashTable *ht;
 -      zval *entry;
 +      zval entry;
        int c;
  
        ht = va_arg(args, HashTable*);
  
 -      MAKE_STD_ZVAL(entry);
 -
        if ((c = zend_hash_num_elements(&opt->suboptions.options))) {
 -              array_init_size(entry, c);
 -              zend_hash_apply_with_arguments(&opt->suboptions.options TSRMLS_CC, apply_available_options, 1, Z_ARRVAL_P(entry));
 +              array_init_size(&entry, c);
 +              zend_hash_apply_with_arguments(&opt->suboptions.options, apply_available_options, 1, Z_ARRVAL(entry));
        } else {
                /* catch deliberate NULL options */
                if (Z_TYPE(opt->defval) == IS_STRING && !Z_STRVAL(opt->defval)) {
 -                      ZVAL_NULL(entry);
 +                      ZVAL_NULL(&entry);
                } else {
 -                      ZVAL_COPY_VALUE(entry, &opt->defval);
 -                      zval_copy_ctor(entry);
 +                      ZVAL_ZVAL(&entry, &opt->defval, 1, 0);
                }
        }
  
 -      if (hash_key->nKeyLength) {
 -              zend_hash_quick_update(ht, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &entry, sizeof(zval *), NULL);
 +      if (hash_key->key) {
 +              zend_hash_update(ht, hash_key->key, &entry);
        } else {
 -              zend_hash_index_update(ht, hash_key->h, (void *) &entry, sizeof(zval *), NULL);
 +              zend_hash_index_update(ht, hash_key->h, &entry);
        }
  
        return ZEND_HASH_APPLY_KEEP;
  static ZEND_RESULT_CODE php_http_client_curl_getopt(php_http_client_t *h, php_http_client_getopt_opt_t opt, void *arg, void **res)
  {
        php_http_client_enqueue_t *enqueue;
 -      TSRMLS_FETCH_FROM_CTX(h->ts);
  
        switch (opt) {
        case PHP_HTTP_CLIENT_OPT_PROGRESS_INFO:
                break;
  
        case PHP_HTTP_CLIENT_OPT_AVAILABLE_OPTIONS:
 -              zend_hash_apply_with_arguments(&php_http_curle_options.options TSRMLS_CC, apply_available_options, 1, *(HashTable **) res);
 +              zend_hash_apply_with_arguments(&php_http_curle_options.options, apply_available_options, 1, *(HashTable **) res);
                break;
  
        case PHP_HTTP_CLIENT_OPT_AVAILABLE_CONFIGURATION:
 -              zend_hash_apply_with_arguments(&php_http_curlm_options.options TSRMLS_CC, apply_available_options, 1, *(HashTable **) res);
 +              zend_hash_apply_with_arguments(&php_http_curlm_options.options, apply_available_options, 1, *(HashTable **) res);
                break;
  
        default:
@@@ -2470,20 -2461,19 +2486,20 @@@ php_http_client_ops_t *php_http_client_
  PHP_MINIT_FUNCTION(http_client_curl)
  {
        php_http_options_t *options;
 -      php_http_client_driver_t driver = {
 -              ZEND_STRL("curl"),
 -              &php_http_client_curl_ops
 -      };
  
 -      if (SUCCESS != php_http_client_driver_add(&driver)) {
 +      PHP_HTTP_G->client.curl.driver.driver_name = zend_string_init(ZEND_STRL("curl"), 1);
 +      PHP_HTTP_G->client.curl.driver.client_name = zend_string_init(ZEND_STRL("http\\Client\\Curl"), 1);
 +      PHP_HTTP_G->client.curl.driver.request_name = zend_string_init(ZEND_STRL("http\\Client\\Curl\\Request"), 1);
 +      PHP_HTTP_G->client.curl.driver.client_ops = &php_http_client_curl_ops;
 +
 +      if (SUCCESS != php_http_client_driver_add(&PHP_HTTP_G->client.curl.driver)) {
                return FAILURE;
        }
  
 -      if (SUCCESS != php_persistent_handle_provide(ZEND_STRL("http\\Client\\Curl"), &php_http_curlm_resource_factory_ops, NULL, NULL TSRMLS_CC)) {
 +      if (SUCCESS != php_persistent_handle_provide(PHP_HTTP_G->client.curl.driver.client_name, &php_http_curlm_resource_factory_ops, NULL, NULL)) {
                return FAILURE;
        }
 -      if (SUCCESS != php_persistent_handle_provide(ZEND_STRL("http\\Client\\Curl\\Request"), &php_http_curle_resource_factory_ops, NULL, NULL TSRMLS_CC)) {
 +      if (SUCCESS != php_persistent_handle_provide(PHP_HTTP_G->client.curl.driver.request_name, &php_http_curle_resource_factory_ops, NULL, NULL)) {
                return FAILURE;
        }
  
                options->getter = php_http_curle_get_option;
                options->setter = php_http_curle_set_option;
  
 -              php_http_curle_options_init(options TSRMLS_CC);
 +              php_http_curle_options_init(options);
        }
        if ((options = php_http_options_init(&php_http_curlm_options, 1))) {
                options->getter = php_http_option_get;
                options->setter = php_http_curlm_set_option;
  
 -              php_http_curlm_options_init(options TSRMLS_CC);
 +              php_http_curlm_options_init(options);
        }
  
        /*
  
  PHP_MSHUTDOWN_FUNCTION(http_client_curl)
  {
 -      php_persistent_handle_cleanup(ZEND_STRL("http\\Client\\Curl"), NULL, 0 TSRMLS_CC);
 -      php_persistent_handle_cleanup(ZEND_STRL("http\\Client\\Curl\\Request"), NULL, 0 TSRMLS_CC);
 +      php_persistent_handle_cleanup(PHP_HTTP_G->client.curl.driver.client_name, NULL);
 +      php_persistent_handle_cleanup(PHP_HTTP_G->client.curl.driver.request_name, NULL);
 +      zend_string_release(PHP_HTTP_G->client.curl.driver.client_name);
 +      zend_string_release(PHP_HTTP_G->client.curl.driver.request_name);
 +      zend_string_release(PHP_HTTP_G->client.curl.driver.driver_name);
  
        php_http_options_dtor(&php_http_curle_options);
        php_http_options_dtor(&php_http_curlm_options);
diff --combined php_http_env_request.c
index 5f1d130dfb0081290fc42897480f3c116bd747df,a884d2ffe432d804c145cf2685757049a914fbea..0ee68f464ade730199dc260857d70c221072bc61
  
  #include "php_http_api.h"
  
 -static int grab_file(void *zpp TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
 +static int grab_file(zval *tmp_name, int argc, va_list argv, zend_hash_key *key)
  {
 -      zval *zfiles, **name, **zname, **error, **zerror, **type, **ztype, **size, **zsize, **tmp_name = zpp;
 +      zval *zfiles, *name, *zname, *error, *zerror, *type, *ztype, *size, *zsize;
        zend_hash_key *file_key;
  
        zfiles = (zval *) va_arg(argv, zval *);
        file_key = (zend_hash_key *) va_arg(argv, zend_hash_key *);
 -      name = (zval **) va_arg(argv, zval **);
 -      size = (zval **) va_arg(argv, zval **);
 -      type = (zval **) va_arg(argv, zval **);
 -      error = (zval **) va_arg(argv, zval **);
 -
 -      if (SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(name), key->h, (void *) &zname)
 -      &&      SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(size), key->h, (void *) &zsize)
 -      &&      SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(type), key->h, (void *) &ztype)
 -      &&      SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(error), key->h, (void *) &zerror)
 +      name = (zval *) va_arg(argv, zval *);
 +      size = (zval *) va_arg(argv, zval *);
 +      type = (zval *) va_arg(argv, zval *);
 +      error = (zval *) va_arg(argv, zval *);
 +
 +      if ((zname = zend_hash_index_find(Z_ARRVAL_P(name), key->h))
 +      &&      (zsize = zend_hash_index_find(Z_ARRVAL_P(size), key->h))
 +      &&      (ztype = zend_hash_index_find(Z_ARRVAL_P(type), key->h))
 +      &&      (zerror = zend_hash_index_find(Z_ARRVAL_P(error), key->h))
        ) {
 -              zval *entry, **array;
 -
 -              MAKE_STD_ZVAL(entry);
 -              array_init(entry);
 -
 -              Z_ADDREF_PP(tmp_name);
 -              add_assoc_zval_ex(entry, ZEND_STRS("file"), *tmp_name);
 -              Z_ADDREF_PP(zname);
 -              add_assoc_zval_ex(entry, ZEND_STRS("name"), *zname);
 -              Z_ADDREF_PP(zsize);
 -              add_assoc_zval_ex(entry, ZEND_STRS("size"), *zsize);
 -              Z_ADDREF_PP(ztype);
 -              add_assoc_zval_ex(entry, ZEND_STRS("type"), *ztype);
 -              Z_ADDREF_PP(zerror);
 -              add_assoc_zval_ex(entry, ZEND_STRS("error"), *zerror);
 -
 -              if (SUCCESS == zend_hash_quick_find(Z_ARRVAL_P(zfiles), file_key->arKey, file_key->nKeyLength, file_key->h, (void *) &array)) {
 -                      add_next_index_zval(*array, entry);
 +              zval entry, *array;
 +
 +              array_init(&entry);
 +
 +              Z_TRY_ADDREF_P(tmp_name);
 +              add_assoc_zval_ex(&entry, ZEND_STRL("file"), tmp_name);
 +              Z_TRY_ADDREF_P(zname);
 +              add_assoc_zval_ex(&entry, ZEND_STRL("name"), zname);
 +              Z_TRY_ADDREF_P(zsize);
 +              add_assoc_zval_ex(&entry, ZEND_STRL("size"), zsize);
 +              Z_TRY_ADDREF_P(ztype);
 +              add_assoc_zval_ex(&entry, ZEND_STRL("type"), ztype);
 +              Z_TRY_ADDREF_P(zerror);
 +              add_assoc_zval_ex(&entry, ZEND_STRL("error"), zerror);
 +
 +              if (file_key->key && (array = zend_hash_find(Z_ARRVAL_P(zfiles), file_key->key))) {
 +                      add_next_index_zval(array, &entry);
 +              } else if (!file_key->key && (array = zend_hash_index_find(Z_ARRVAL_P(zfiles), file_key->h))) {
 +                      add_next_index_zval(array, &entry);
                } else {
 -                      zval *tmp;
 +                      zval tmp;
  
 -                      MAKE_STD_ZVAL(tmp);
 -                      array_init(tmp);
 -                      add_next_index_zval(tmp, entry);
 -                      zend_hash_quick_update(Z_ARRVAL_P(zfiles), file_key->arKey, file_key->nKeyLength, file_key->h, (void *) &tmp, sizeof(zval *), NULL);
 +                      array_init(&tmp);
 +                      add_next_index_zval(&tmp, &entry);
 +                      if (file_key->key) {
 +                              zend_hash_update(Z_ARRVAL_P(zfiles), file_key->key, &tmp);
 +                      } else {
 +                              zend_hash_index_update(Z_ARRVAL_P(zfiles), file_key->h, &tmp);
 +                      }
                }
        }
  
        return ZEND_HASH_APPLY_KEEP;
  }
  
 -static int grab_files(void *zpp TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
 +static int grab_files(zval *val, int argc, va_list argv, zend_hash_key *key)
  {
 -      zval *zfiles, **name, **tmp_name, **error, **type, **size, **val = zpp;
 +      zval *zfiles, *name, *tmp_name, *error, *type, *size;
  
        zfiles = (zval *) va_arg(argv, zval *);
  
 -      if (Z_TYPE_PP(val) == IS_ARRAY
 -      &&      SUCCESS == zend_hash_find(Z_ARRVAL_PP(val), ZEND_STRS("tmp_name"), (void *) &tmp_name)
 -      &&      SUCCESS == zend_hash_find(Z_ARRVAL_PP(val), ZEND_STRS("name"), (void *) &name)
 -      &&      SUCCESS == zend_hash_find(Z_ARRVAL_PP(val), ZEND_STRS("size"), (void *) &size)
 -      &&      SUCCESS == zend_hash_find(Z_ARRVAL_PP(val), ZEND_STRS("type"), (void *) &type)
 -      &&      SUCCESS == zend_hash_find(Z_ARRVAL_PP(val), ZEND_STRS("error"), (void *) &error)
 +      if ((Z_TYPE_P(val) == IS_ARRAY)
 +      &&      (tmp_name = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("tmp_name")))
 +      &&      (name = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("name")))
 +      &&      (size = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("size")))
 +      &&      (type = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("type")))
 +      &&      (error = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("error")))
        ) {
                int count;
  
 -              if (Z_TYPE_PP(tmp_name) == IS_ARRAY && (count = zend_hash_num_elements(Z_ARRVAL_PP(tmp_name))) > 1) {
 -                      if (count == zend_hash_num_elements(Z_ARRVAL_PP(name))
 -                      &&      count == zend_hash_num_elements(Z_ARRVAL_PP(size))
 -                      &&      count == zend_hash_num_elements(Z_ARRVAL_PP(type))
 -                      &&      count == zend_hash_num_elements(Z_ARRVAL_PP(error))
 +              if (Z_TYPE_P(tmp_name) == IS_ARRAY && (count = zend_hash_num_elements(Z_ARRVAL_P(tmp_name))) > 1) {
 +                      if (count == zend_hash_num_elements(Z_ARRVAL_P(name))
 +                      &&      count == zend_hash_num_elements(Z_ARRVAL_P(size))
 +                      &&      count == zend_hash_num_elements(Z_ARRVAL_P(type))
 +                      &&      count == zend_hash_num_elements(Z_ARRVAL_P(error))
                        ) {
 -                              zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp_name) TSRMLS_CC, grab_file, 6, zfiles, key, name, size, type, error);
 +                              zend_hash_apply_with_arguments(Z_ARRVAL_P(tmp_name), grab_file, 6, zfiles, key, name, size, type, error);
                        } else {
                                /* wat?! */
                                return ZEND_HASH_APPLY_STOP;
                        }
                } else  {
 -                      zval *cpy, **tmp;
 -
 -                      MAKE_STD_ZVAL(cpy);
 -                      MAKE_COPY_ZVAL(val, cpy);
 -                      if (SUCCESS == zend_hash_find(Z_ARRVAL_P(cpy), ZEND_STRS("tmp_name"), (void *) &tmp)) {
 -                              Z_ADDREF_PP(tmp);
 -                              add_assoc_zval_ex(cpy, ZEND_STRS("file"), *tmp);
 -                              zend_hash_del_key_or_index(Z_ARRVAL_P(cpy), ZEND_STRS("tmp_name"), 0, HASH_DEL_KEY);
 +                      zval *tmp, entry;
 +
 +                      ZVAL_DUP(&entry, val);
 +                      if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("tmp_name")))) {
 +                              Z_ADDREF_P(tmp);
 +                              add_assoc_zval_ex(&entry, ZEND_STRL("file"), tmp);
 +                              zend_hash_str_del(Z_ARRVAL(entry), ZEND_STRL("tmp_name"));
                        }
 -                      if (key->nKeyLength > 0) {
 -                              zend_hash_quick_update(Z_ARRVAL_P(zfiles), key->arKey, key->nKeyLength, key->h, (void *) &cpy, sizeof(zval *), NULL);
 +                      if (key->key) {
 +                              zend_hash_update(Z_ARRVAL_P(zfiles), key->key, &entry);
                        } else {
 -                              zend_hash_index_update(Z_ARRVAL_P(zfiles), key->h, (void *) &cpy, sizeof(zval *), NULL);
 +                              zend_hash_index_update(Z_ARRVAL_P(zfiles), key->h, &entry);
                        }
                }
        }
  #define PHP_HTTP_ENV_REQUEST_OBJECT_INIT(obj) \
        do { \
                if (!obj->message) { \
 -                      obj->message = php_http_message_init_env(NULL, PHP_HTTP_REQUEST TSRMLS_CC); \
 +                      obj->message = php_http_message_init_env(NULL, PHP_HTTP_REQUEST); \
                } \
        } while(0)
  
@@@ -123,38 -120,51 +123,38 @@@ ZEND_END_ARG_INFO()
  static PHP_METHOD(HttpEnvRequest, __construct)
  {
        php_http_message_object_t *obj;
 -      zval *zsg, *zqs;
 +      zval *zsg, zqs;
  
        php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
  
 -      obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 +      obj = PHP_HTTP_OBJ(NULL, getThis());
        obj->body = NULL;
  
 -      php_http_expect(obj->message = php_http_message_init_env(obj->message, PHP_HTTP_REQUEST TSRMLS_CC), unexpected_val, return);
 +      php_http_expect(obj->message = php_http_message_init_env(obj->message, PHP_HTTP_REQUEST), unexpected_val, return);
  
 -      zsg = php_http_env_get_superglobal(ZEND_STRL("_GET") TSRMLS_CC);
 -      MAKE_STD_ZVAL(zqs);
 -      object_init_ex(zqs, php_http_querystring_class_entry);
 -      php_http_expect(SUCCESS == php_http_querystring_ctor(zqs, zsg TSRMLS_CC), unexpected_val,
 -                      zval_ptr_dtor(&zqs);
 -                      return;
 -      );
 -      zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("query"), zqs TSRMLS_CC);
 +      zsg = php_http_env_get_superglobal(ZEND_STRL("_GET"));
 +      object_init_ex(&zqs, php_http_querystring_class_entry);
 +      php_http_expect(SUCCESS == php_http_querystring_ctor(&zqs, zsg), unexpected_val, return);
 +      zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("query"), &zqs);
        zval_ptr_dtor(&zqs);
  
 -      zsg = php_http_env_get_superglobal(ZEND_STRL("_POST") TSRMLS_CC);
 -      MAKE_STD_ZVAL(zqs);
 -      object_init_ex(zqs, php_http_querystring_class_entry);
 -      php_http_expect(SUCCESS == php_http_querystring_ctor(zqs, zsg TSRMLS_CC), unexpected_val,
 -                      zval_ptr_dtor(&zqs);
 -                      return;
 -      );
 -      zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("form"), zqs TSRMLS_CC);
 +      zsg = php_http_env_get_superglobal(ZEND_STRL("_POST"));
 +      object_init_ex(&zqs, php_http_querystring_class_entry);
 +      php_http_expect(SUCCESS == php_http_querystring_ctor(&zqs, zsg), unexpected_val, return);
 +      zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("form"), &zqs);
        zval_ptr_dtor(&zqs);
  
 -      zsg = php_http_env_get_superglobal(ZEND_STRL("_COOKIE") TSRMLS_CC);
 -      MAKE_STD_ZVAL(zqs);
 -      object_init_ex(zqs, php_http_querystring_class_entry);
 -      php_http_expect(SUCCESS == php_http_querystring_ctor(zqs, zsg TSRMLS_CC), unexpected_val,
 -                      zval_ptr_dtor(&zqs);
 -                      return;
 -      );
 -      zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("cookie"), zqs TSRMLS_CC);
 +      zsg = php_http_env_get_superglobal(ZEND_STRL("_COOKIE"));
 +      object_init_ex(&zqs, php_http_querystring_class_entry);
 +      php_http_expect(SUCCESS == php_http_querystring_ctor(&zqs, zsg), unexpected_val, return);
 +      zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("cookie"), &zqs);
        zval_ptr_dtor(&zqs);
  
 -      MAKE_STD_ZVAL(zqs);
 -      array_init(zqs);
 -      if ((zsg = php_http_env_get_superglobal(ZEND_STRL("_FILES") TSRMLS_CC))) {
 -              zend_hash_apply_with_arguments(Z_ARRVAL_P(zsg) TSRMLS_CC, grab_files, 1, zqs);
 +      array_init(&zqs);
 +      if ((zsg = php_http_env_get_superglobal(ZEND_STRL("_FILES")))) {
 +              zend_hash_apply_with_arguments(Z_ARRVAL_P(zsg), grab_files, 1, &zqs);
        }
 -      zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("files"), zqs TSRMLS_CC);
 +      zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("files"), &zqs);
        zval_ptr_dtor(&zqs);
  }
  
        do {\
                zend_fcall_info fci; \
                zend_fcall_info_cache fcc; \
 -              zval *rv = NULL, mn, ***args = ecalloc(sizeof(zval **), ZEND_NUM_ARGS()); \
 -              zval *qs = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL(prop), 0 TSRMLS_CC); \
 +              zval rv, mn, *args = ecalloc(sizeof(zval), ZEND_NUM_ARGS()); \
 +              zval *this_ptr = getThis(); \
 +              zval qs_tmp, *qs = zend_read_property(Z_OBJCE_P(this_ptr), this_ptr, ZEND_STRL(prop), 0, &qs_tmp); \
                 \
 -              INIT_PZVAL(&mn); \
++              ZVAL_NULL(&rv); \
                array_init(&mn); \
 -              Z_ADDREF_P(qs); \
 +              Z_TRY_ADDREF_P(qs); \
                add_next_index_zval(&mn, qs); \
 -              add_next_index_stringl(&mn, ZEND_STRL("get"), 1); \
 -              zend_fcall_info_init(&mn, 0, &fci, &fcc, NULL, NULL TSRMLS_CC); \
 +              add_next_index_stringl(&mn, ZEND_STRL("get")); \
 +              zend_fcall_info_init(&mn, 0, &fci, &fcc, NULL, NULL); \
                zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args); \
 -              zend_fcall_info_argp(&fci TSRMLS_CC, ZEND_NUM_ARGS(), args); \
 -              zend_fcall_info_call(&fci, &fcc, &rv, NULL TSRMLS_CC); \
 +              zend_fcall_info_argp(&fci, ZEND_NUM_ARGS(), args); \
 +              zend_fcall_info_call(&fci, &fcc, &rv, NULL); \
                zend_fcall_info_args_clear(&fci, 1); \
                efree(args); \
                zval_dtor(&mn); \
 -              if (rv) { \
 -                      RETVAL_ZVAL(rv, 0, 1); \
 -              } \
 +              RETVAL_ZVAL(&rv, 0, 1); \
        } while(0);
  
  ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnvRequest_getForm, 0, 0, 0)
@@@ -191,7 -203,7 +192,7 @@@ static PHP_METHOD(HttpEnvRequest, getFo
        if (ZEND_NUM_ARGS()) {
                call_querystring_get("form");
        } else {
 -              zval *zform = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("form"), 0 TSRMLS_CC);
 +              zval zform_tmp, *zform = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("form"), 0, &zform_tmp);
                RETURN_ZVAL(zform, 1, 0);
        }
  }
@@@ -207,7 -219,7 +208,7 @@@ static PHP_METHOD(HttpEnvRequest, getQu
        if (ZEND_NUM_ARGS()) {
                call_querystring_get("query");
        } else {
 -              zval *zquery = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("query"), 0 TSRMLS_CC);
 +              zval zquery_tmp, *zquery = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("query"), 0, &zquery_tmp);
                RETURN_ZVAL(zquery, 1, 0);
        }
  }
@@@ -223,7 -235,7 +224,7 @@@ static PHP_METHOD(HttpEnvRequest, getCo
        if (ZEND_NUM_ARGS()) {
                call_querystring_get("cookie");
        } else {
 -              zval *zcookie = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("cookie"), 0 TSRMLS_CC);
 +              zval zcookie_tmp, *zcookie = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("cookie"), 0, &zcookie_tmp);
                RETURN_ZVAL(zcookie, 1, 0);
        }
  }
@@@ -233,7 -245,7 +234,7 @@@ ZEND_END_ARG_INFO()
  static PHP_METHOD(HttpEnvRequest, getFiles)
  {
        if (SUCCESS == zend_parse_parameters_none()) {
 -              zval *zfiles = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("files"), 0 TSRMLS_CC);
 +              zval zfiles_tmp, *zfiles = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("files"), 0, &zfiles_tmp);
                RETURN_ZVAL(zfiles, 1, 0);
        }
  }
@@@ -254,12 -266,12 +255,12 @@@ PHP_MINIT_FUNCTION(http_env_request
        zend_class_entry ce = {0};
  
        INIT_NS_CLASS_ENTRY(ce, "http\\Env", "Request", php_http_env_request_methods);
 -      php_http_env_request_class_entry = zend_register_internal_class_ex(&ce, php_http_message_class_entry, NULL TSRMLS_CC);
 +      php_http_env_request_class_entry = zend_register_internal_class_ex(&ce, php_http_message_class_entry);
  
 -      zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("query"), ZEND_ACC_PROTECTED TSRMLS_CC);
 -      zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("form"), ZEND_ACC_PROTECTED TSRMLS_CC);
 -      zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("cookie"), ZEND_ACC_PROTECTED TSRMLS_CC);
 -      zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("files"), ZEND_ACC_PROTECTED TSRMLS_CC);
 +      zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("query"), ZEND_ACC_PROTECTED);
 +      zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("form"), ZEND_ACC_PROTECTED);
 +      zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("cookie"), ZEND_ACC_PROTECTED);
 +      zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("files"), ZEND_ACC_PROTECTED);
  
        return SUCCESS;
  }
diff --combined php_http_header_parser.c
index e1ebe12cf503cc284e11e0ae9bd5315c14517887,46551e21248959c67a7aa7d915885a6ec9d1e050..5dfaeddfe8c9067c2a6393d82ed1a0d20b535d28
@@@ -30,13 -30,15 +30,13 @@@ static const php_http_header_parser_sta
                {PHP_HTTP_HEADER_PARSER_STATE_DONE,                     0}
  };
  
 -php_http_header_parser_t *php_http_header_parser_init(php_http_header_parser_t *parser TSRMLS_DC)
 +php_http_header_parser_t *php_http_header_parser_init(php_http_header_parser_t *parser)
  {
        if (!parser) {
                parser = emalloc(sizeof(*parser));
        }
        memset(parser, 0, sizeof(*parser));
  
 -      TSRMLS_SET_CTX(parser->ts);
 -
        return parser;
  }
  
@@@ -95,18 -97,19 +95,18 @@@ void php_http_header_parser_free(php_ht
  }
  
  /* NOTE: 'str' has to be null terminated */
 -static void php_http_header_parser_error(size_t valid_len, char *str, size_t len, const char *eol_str TSRMLS_DC)
 +static void php_http_header_parser_error(size_t valid_len, char *str, size_t len, const char *eol_str )
  {
 -      int escaped_len;
 -      char *escaped_str;
 +      zend_string *escaped_str = zend_string_init(str, len, 0);
  
 -      escaped_str = php_addcslashes(str, len, &escaped_len, 0, ZEND_STRL("\x0..\x1F\x7F..\xFF") TSRMLS_CC);
 +      escaped_str = php_addcslashes(escaped_str, 1, ZEND_STRL("\x0..\x1F\x7F..\xFF"));
  
        if (valid_len != len && (!eol_str || (str+valid_len) != eol_str)) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse headers: unexpected character '\\%03o' at pos %zu of '%.*s'", str[valid_len], valid_len, escaped_len, escaped_str);
 +              php_error_docref(NULL, E_WARNING, "Failed to parse headers: unexpected character '\\%03o' at pos %zu of '%s'", str[valid_len], valid_len, escaped_str->val);
        } else if (eol_str) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse headers: unexpected end of line at pos %zu of '%.*s'", eol_str - str, escaped_len, escaped_str);
 +              php_error_docref(NULL, E_WARNING, "Failed to parse headers: unexpected end of line at pos %zu of '%s'", eol_str - str, escaped_str->val);
        } else {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse headers: unexpected end of input at pos %zu of '%.*s'", len, escaped_len, escaped_str);
 +              php_error_docref(NULL, E_WARNING, "Failed to parse headers: unexpected end of input at pos %zu of '%s'", len, escaped_str->val);
        }
  
        efree(escaped_str);
  
  php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg)
  {
 -      TSRMLS_FETCH_FROM_CTX(parser->ts);
 -
        while (buffer->used || !php_http_header_parser_states[php_http_header_parser_state_is(parser)].need_data) {
  #if DBG_PARSER
                const char *state[] = {"START", "KEY", "VALUE", "VALUE_EX", "HEADER_DONE", "DONE"};
  #endif
                switch (php_http_header_parser_state_pop(parser)) {
                        case PHP_HTTP_HEADER_PARSER_STATE_FAILURE:
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse headers");
 +                              php_error_docref(NULL, E_WARNING, "Failed to parse headers");
                                return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
  
                        case PHP_HTTP_HEADER_PARSER_STATE_START: {
                                const char *colon, *eol_str = NULL;
                                int eol_len = 0;
  
+                               /* fix buffer here, so eol_str pointer doesn't become obsolete afterwards */
+                               php_http_buffer_fix(buffer);
                                if (buffer->data == (eol_str = php_http_locate_bin_eol(buffer->data, buffer->used, &eol_len))) {
                                        /* end of headers */
                                        php_http_buffer_cut(buffer, 0, eol_len);
                                        php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_DONE);
-                               } else if (php_http_info_parse(&parser->info, php_http_buffer_fix(buffer)->data)) {
 -                              } else if (php_http_info_parse(&parser->info, buffer->data TSRMLS_CC)) {
++                              } else if (php_http_info_parse(&parser->info, buffer->data)) {
                                        /* new message starting with request/response line */
                                        if (callback_func) {
 -                                              callback_func(callback_arg, &headers, &parser->info TSRMLS_CC);
 +                                              callback_func(callback_arg, &headers, &parser->info);
                                        }
                                        php_http_info_dtor(&parser->info);
                                        php_http_buffer_cut(buffer, 0, eol_str + eol_len - buffer->data);
  
                                        valid_len = strspn(parser->_key.str, PHP_HTTP_HEADER_NAME_CHARS);
                                        if (valid_len != parser->_key.len) {
 -                                              php_http_header_parser_error(valid_len, parser->_key.str, parser->_key.len, eol_str TSRMLS_CC);
 +                                              php_http_header_parser_error(valid_len, parser->_key.str, parser->_key.len, eol_str);
                                                PTR_SET(parser->_key.str, NULL);
                                                return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
                                        }
                                        php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
                                } else if (eol_str || (flags & PHP_HTTP_HEADER_PARSER_CLEANUP)) {
                                        /* neither reqeust/response line nor 'header:' string, or injected new line or NUL etc. */
-                                       php_http_buffer_fix(buffer);
 -                                      php_http_header_parser_error(strspn(buffer->data, PHP_HTTP_HEADER_NAME_CHARS), buffer->data, buffer->used, eol_str TSRMLS_CC);
 +                                      php_http_header_parser_error(strspn(buffer->data, PHP_HTTP_HEADER_NAME_CHARS), buffer->data, buffer->used, eol_str);
                                        return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
                                } else {
                                        /* keep feeding */
  
                        case PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE:
                                if (parser->_key.str && parser->_val.str) {
 -                                      zval array, **exist;
 +                                      zval tmp, *exist;
                                        size_t valid_len = strlen(parser->_val.str);
  
                                        /* check for truncation */
                                        if (valid_len != parser->_val.len) {
 -                                              php_http_header_parser_error(valid_len, parser->_val.str, parser->_val.len, NULL TSRMLS_CC);
 +                                              php_http_header_parser_error(valid_len, parser->_val.str, parser->_val.len, NULL);
  
                                                PTR_SET(parser->_key.str, NULL);
                                                PTR_SET(parser->_val.str, NULL);
                                        }
  
                                        if (!headers && callback_func) {
 -                                              callback_func(callback_arg, &headers, NULL TSRMLS_CC);
 +                                              callback_func(callback_arg, &headers, NULL);
                                        }
  
 -                                      INIT_PZVAL_ARRAY(&array, headers);
                                        php_http_pretty_key(parser->_key.str, parser->_key.len, 1, 1);
 -                                      if (SUCCESS == zend_symtable_find(headers, parser->_key.str, parser->_key.len + 1, (void *) &exist)) {
 -                                              convert_to_array(*exist);
 -                                              add_next_index_stringl(*exist, parser->_val.str, parser->_val.len, 0);
 +                                      if ((exist = zend_symtable_str_find(headers, parser->_key.str, parser->_key.len))) {
 +                                              convert_to_array(exist);
 +                                              add_next_index_str(exist, php_http_cs2zs(parser->_val.str, parser->_val.len));
                                        } else {
 -                                              add_assoc_stringl_ex(&array, parser->_key.str, parser->_key.len + 1, parser->_val.str, parser->_val.len, 0);
 +                                              ZVAL_STR(&tmp, php_http_cs2zs(parser->_val.str, parser->_val.len));
 +                                              zend_symtable_str_update(headers, parser->_key.str, parser->_key.len, &tmp);
                                        }
                                        parser->_val.str = NULL;
                                }
  php_http_header_parser_state_t php_http_header_parser_parse_stream(php_http_header_parser_t *parser, php_http_buffer_t *buf, php_stream *s, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg)
  {
        php_http_header_parser_state_t state = PHP_HTTP_HEADER_PARSER_STATE_START;
 -      TSRMLS_FETCH_FROM_CTX(parser->ts);
  
        if (!buf->data) {
                php_http_buffer_resize_ex(buf, 0x1000, 1, 0);
  zend_class_entry *php_http_header_parser_class_entry;
  static zend_object_handlers php_http_header_parser_object_handlers;
  
 -zend_object_value php_http_header_parser_object_new(zend_class_entry *ce TSRMLS_DC)
 +zend_object *php_http_header_parser_object_new(zend_class_entry *ce)
  {
 -      return php_http_header_parser_object_new_ex(ce, NULL, NULL TSRMLS_CC);
 +      return &php_http_header_parser_object_new_ex(ce, NULL)->zo;
  }
  
 -zend_object_value php_http_header_parser_object_new_ex(zend_class_entry *ce, php_http_header_parser_t *parser, php_http_header_parser_object_t **ptr TSRMLS_DC)
 +php_http_header_parser_object_t *php_http_header_parser_object_new_ex(zend_class_entry *ce, php_http_header_parser_t *parser)
  {
        php_http_header_parser_object_t *o;
  
 -      o = ecalloc(1, sizeof(php_http_header_parser_object_t));
 -      zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
 -      object_properties_init((zend_object *) o, ce);
 -
 -      if (ptr) {
 -              *ptr = o;
 -      }
 +      o = ecalloc(1, sizeof(php_http_header_parser_object_t) + zend_object_properties_size(ce));
 +      zend_object_std_init(&o->zo, ce);
 +      object_properties_init(&o->zo, ce);
  
        if (parser) {
                o->parser = parser;
        } else {
 -              o->parser = php_http_header_parser_init(NULL TSRMLS_CC);
 +              o->parser = php_http_header_parser_init(NULL);
        }
        o->buffer = php_http_buffer_new();
  
 -      o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_http_header_parser_object_free, NULL TSRMLS_CC);
 -      o->zv.handlers = &php_http_header_parser_object_handlers;
 +      o->zo.handlers = &php_http_header_parser_object_handlers;
  
 -      return o->zv;
 +      return o;
  }
  
 -void php_http_header_parser_object_free(void *object TSRMLS_DC)
 +void php_http_header_parser_object_free(zend_object *object)
  {
 -      php_http_header_parser_object_t *o = (php_http_header_parser_object_t *) object;
 +      php_http_header_parser_object_t *o = PHP_HTTP_OBJ(object, NULL);
  
        if (o->parser) {
                php_http_header_parser_free(&o->parser);
        if (o->buffer) {
                php_http_buffer_free(&o->buffer);
        }
 -      zend_object_std_dtor((zend_object *) o TSRMLS_CC);
 -      efree(o);
 +      zend_object_std_dtor(object);
  }
  
  ZEND_BEGIN_ARG_INFO_EX(ai_HttpHeaderParser_getState, 0, 0, 0)
  ZEND_END_ARG_INFO();
  static PHP_METHOD(HttpHeaderParser, getState)
  {
 -      php_http_header_parser_object_t *parser_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 +      php_http_header_parser_object_t *parser_obj = PHP_HTTP_OBJ(NULL, getThis());
  
        zend_parse_parameters_none();
        /* always return the real state */
@@@ -393,17 -407,16 +395,17 @@@ static PHP_METHOD(HttpHeaderParser, par
        php_http_header_parser_object_t *parser_obj;
        zval *zmsg;
        char *data_str;
 -      int data_len;
 -      long flags;
 +      size_t data_len;
 +      zend_long flags;
  
 -      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "slz", &data_str, &data_len, &flags, &zmsg), invalid_arg, return);
 +      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "slz", &data_str, &data_len, &flags, &zmsg), invalid_arg, return);
  
 +      ZVAL_DEREF(zmsg);
        if (Z_TYPE_P(zmsg) != IS_ARRAY) {
                zval_dtor(zmsg);
                array_init(zmsg);
        }
 -      parser_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 +      parser_obj = PHP_HTTP_OBJ(NULL, getThis());
        php_http_buffer_append(parser_obj->buffer, data_str, data_len);
        RETVAL_LONG(php_http_header_parser_parse(parser_obj->parser, parser_obj->buffer, flags, Z_ARRVAL_P(zmsg), NULL, NULL));
  }
@@@ -419,20 -432,19 +421,20 @@@ static PHP_METHOD(HttpHeaderParser, str
        zend_error_handling zeh;
        zval *zmsg, *zstream;
        php_stream *s;
 -      long flags;
 +      zend_long flags;
  
 -      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &zstream, &flags, &zmsg), invalid_arg, return);
 +      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "rlz", &zstream, &flags, &zmsg), invalid_arg, return);
  
 -      zend_replace_error_handling(EH_THROW, php_http_exception_unexpected_val_class_entry, &zeh TSRMLS_CC);
 -      php_stream_from_zval(s, &zstream);
 -      zend_restore_error_handling(&zeh TSRMLS_CC);
 +      zend_replace_error_handling(EH_THROW, php_http_exception_unexpected_val_class_entry, &zeh);
 +      php_stream_from_zval(s, zstream);
 +      zend_restore_error_handling(&zeh);
  
 +      ZVAL_DEREF(zmsg);
        if (Z_TYPE_P(zmsg) != IS_ARRAY) {
                zval_dtor(zmsg);
                array_init(zmsg);
        }
 -      parser_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 +      parser_obj = PHP_HTTP_OBJ(NULL, getThis());
        RETVAL_LONG(php_http_header_parser_parse_stream(parser_obj->parser, parser_obj->buffer, s, flags, Z_ARRVAL_P(zmsg), NULL, NULL));
  }
  
@@@ -448,22 -460,20 +450,22 @@@ PHP_MINIT_FUNCTION(http_header_parser
        zend_class_entry ce;
  
        INIT_NS_CLASS_ENTRY(ce, "http\\Header", "Parser", php_http_header_parser_methods);
 -      php_http_header_parser_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 +      php_http_header_parser_class_entry = zend_register_internal_class(&ce);
        memcpy(&php_http_header_parser_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
        php_http_header_parser_class_entry->create_object = php_http_header_parser_object_new;
 +      php_http_header_parser_object_handlers.offset = XtOffsetOf(php_http_header_parser_object_t, zo);
        php_http_header_parser_object_handlers.clone_obj = NULL;
 +      php_http_header_parser_object_handlers.free_obj = php_http_header_parser_object_free;
  
 -      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("CLEANUP"), PHP_HTTP_HEADER_PARSER_CLEANUP TSRMLS_CC);
 +      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("CLEANUP"), PHP_HTTP_HEADER_PARSER_CLEANUP);
  
 -      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_FAILURE"), PHP_HTTP_HEADER_PARSER_STATE_FAILURE TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_START"), PHP_HTTP_HEADER_PARSER_STATE_START TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_KEY"), PHP_HTTP_HEADER_PARSER_STATE_KEY TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE"), PHP_HTTP_HEADER_PARSER_STATE_VALUE TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE_EX"), PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_HEADER_DONE"), PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_DONE"), PHP_HTTP_HEADER_PARSER_STATE_DONE TSRMLS_CC);
 +      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_FAILURE"), PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
 +      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_START"), PHP_HTTP_HEADER_PARSER_STATE_START);
 +      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_KEY"), PHP_HTTP_HEADER_PARSER_STATE_KEY);
 +      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE"), PHP_HTTP_HEADER_PARSER_STATE_VALUE);
 +      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE_EX"), PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
 +      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_HEADER_DONE"), PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
 +      zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_DONE"), PHP_HTTP_HEADER_PARSER_STATE_DONE);
  
        return SUCCESS;
  }
diff --combined php_http_querystring.c
index 589b01506bd3e58db1d907584a2f834ef244c6e6,d72337f80a5bc29e4c6544528127363f849c2cac..5f4eff81a9a101414d4ffed647fcc9ae6c9a4f12
  #include <ext/spl/spl_array.h>
  
  #ifdef PHP_HTTP_HAVE_ICONV
+ #     ifndef HAVE_ICONV
+ #             define HAVE_ICONV 1
+ #     endif
  #     undef PHP_ATOM_INC
  #     include <ext/iconv/php_iconv.h>
  #endif
  
  #define QS_MERGE 1
  
 -static inline void php_http_querystring_set(zval *instance, zval *params, int flags TSRMLS_DC)
 +static inline void php_http_querystring_set(zval *instance, zval *params, int flags)
  {
 -      zval *qa;
 +      zval qa;
 +
 +      array_init(&qa);
  
        if (flags & QS_MERGE) {
 -              qa = php_http_zsep(1, IS_ARRAY, zend_read_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), 0 TSRMLS_CC));
 -      } else {
 -              MAKE_STD_ZVAL(qa);
 -              array_init(qa);
 +              zval old_tmp, *old = zend_read_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), 0, &old_tmp);
 +
 +              ZVAL_DEREF(old);
 +              if (Z_TYPE_P(old) == IS_ARRAY) {
 +                      array_copy(Z_ARRVAL_P(old), Z_ARRVAL(qa));
 +              }
        }
  
 -      php_http_querystring_update(qa, params, NULL TSRMLS_CC);
 -      zend_update_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), qa TSRMLS_CC);
 +      php_http_querystring_update(&qa, params, NULL);
 +      zend_update_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), &qa);
        zval_ptr_dtor(&qa);
  }
  
 -static inline void php_http_querystring_str(zval *instance, zval *return_value TSRMLS_DC)
 +static inline void php_http_querystring_str(zval *instance, zval *return_value)
  {
 -      zval *qa = zend_read_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), 0 TSRMLS_CC);
 +      zval qa_tmp, *qa = zend_read_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), 0, &qa_tmp);
  
 +      ZVAL_DEREF(qa);
        if (Z_TYPE_P(qa) == IS_ARRAY) {
 -              php_http_querystring_update(qa, NULL, return_value TSRMLS_CC);
 +              php_http_querystring_update(qa, NULL, return_value);
        } else {
                RETURN_EMPTY_STRING();
        }
  }
  
 -static inline void php_http_querystring_get(zval *this_ptr, int type, char *name, uint name_len, zval *defval, zend_bool del, zval *return_value TSRMLS_DC)
 +static inline void php_http_querystring_get(zval *instance, int type, char *name, uint name_len, zval *defval, zend_bool del, zval *return_value)
  {
 -      zval **arrval, *qarray = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
 +      zval *arrval, qarray_tmp, *qarray = zend_read_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), 0, &qarray_tmp);
 +
 +      ZVAL_DEREF(qarray);
 +      if ((Z_TYPE_P(qarray) == IS_ARRAY) && (arrval = zend_symtable_str_find(Z_ARRVAL_P(qarray), name, name_len))) {
 +              if (type && type != Z_TYPE_P(arrval)) {
 +                      zval tmp;
  
 -      if ((Z_TYPE_P(qarray) == IS_ARRAY) && (SUCCESS == zend_symtable_find(Z_ARRVAL_P(qarray), name, name_len + 1, (void *) &arrval))) {
 -              if (type) {
 -                      zval *value = php_http_ztyp(type, *arrval);
 -                      RETVAL_ZVAL(value, 1, 1);
 +                      ZVAL_DUP(&tmp, arrval);
 +                      convert_to_explicit_type(&tmp, type);
 +                      RETVAL_ZVAL(&tmp, 0, 0);
                } else {
 -                      RETVAL_ZVAL(*arrval, 1, 0);
 +                      RETVAL_ZVAL(arrval, 1, 0);
                }
  
                if (del) {
 -                      zval *delarr;
 +                      zval delarr;
  
 -                      MAKE_STD_ZVAL(delarr);
 -                      array_init(delarr);
 -                      add_assoc_null_ex(delarr, name, name_len + 1);
 -                      php_http_querystring_set(this_ptr, delarr, QS_MERGE TSRMLS_CC);
 +                      array_init(&delarr);
 +                      add_assoc_null_ex(&delarr, name, name_len);
 +                      php_http_querystring_set(instance, &delarr, QS_MERGE);
                        zval_ptr_dtor(&delarr);
                }
        } else if(defval) {
  }
  
  #ifdef PHP_HTTP_HAVE_ICONV
 -ZEND_RESULT_CODE php_http_querystring_xlate(zval *dst, zval *src, const char *ie, const char *oe TSRMLS_DC)
 +ZEND_RESULT_CODE php_http_querystring_xlate(zval *dst, zval *src, const char *ie, const char *oe)
  {
 -      HashPosition pos;
 -      zval **entry = NULL;
 -      char *xlate_str = NULL, *xkey;
 -      size_t xlate_len = 0, xlen;
 -      php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
 +      zval *entry;
 +      zend_string *xkey, *xstr;
 +      php_http_arrkey_t key;
        
 -      FOREACH_KEYVAL(pos, src, 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)) {
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to convert '%.*s' from '%s' to '%s'", key.len-1, key.str, ie, oe);
 +      ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(src), key.h, key.key, entry)
 +      {
 +              if (key.key) {
 +                      if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(key.key->val, key.key->len, &xkey, oe, ie)) {
 +                              php_error_docref(NULL, E_WARNING, "Failed to convert '%.*s' from '%s' to '%s'", key.key->len, key.key->val, 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 (key.type == HASH_KEY_IS_STRING) {
 -                                      efree(xkey);
 +              if (Z_TYPE_P(entry) == IS_STRING) {
 +                      if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_P(entry), Z_STRLEN_P(entry), &xstr, oe, ie)) {
 +                              if (key.key) {
 +                                      zend_string_release(xkey);
                                }
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to convert '%.*s' from '%s' to '%s'", Z_STRLEN_PP(entry), Z_STRVAL_PP(entry), ie, oe);
 +                              php_error_docref(NULL, E_WARNING, "Failed to convert '%.*s' from '%s' to '%s'", Z_STRLEN_P(entry), Z_STRVAL_P(entry), ie, oe);
                                return FAILURE;
                        }
 -                      if (key.type == HASH_KEY_IS_STRING) {
 -                              add_assoc_stringl_ex(dst, xkey, xlen+1, xlate_str, xlate_len, 0);
 +                      if (key.key) {
 +                              add_assoc_str_ex(dst, xkey->val, xkey->len, xstr);
                        } else {
 -                              add_index_stringl(dst, key.num, xlate_str, xlate_len, 0);
 +                              add_index_str(dst, key.h, xstr);
                        }
 -              } else if (Z_TYPE_PP(entry) == IS_ARRAY) {
 -                      zval *subarray;
 +              } else if (Z_TYPE_P(entry) == IS_ARRAY) {
 +                      zval subarray;
                        
 -                      MAKE_STD_ZVAL(subarray);
 -                      array_init(subarray);
 -                      if (key.type == HASH_KEY_IS_STRING) {
 -                              add_assoc_zval_ex(dst, xkey, xlen+1, subarray);
 +                      array_init(&subarray);
 +                      if (key.key) {
 +                              add_assoc_zval_ex(dst, xkey->val, xkey->len, &subarray);
                        } else {
 -                              add_index_zval(dst, key.num, subarray);
 +                              add_index_zval(dst, key.h, &subarray);
                        }
 -                      if (SUCCESS != php_http_querystring_xlate(subarray, *entry, ie, oe TSRMLS_CC)) {
 -                              if (key.type == HASH_KEY_IS_STRING) {
 -                                      efree(xkey);
 +                      if (SUCCESS != php_http_querystring_xlate(&subarray, entry, ie, oe)) {
 +                              if (key.key) {
 +                                      zend_string_release(xkey);
                                }
                                return FAILURE;
                        }
                }
                
 -              if (key.type == HASH_KEY_IS_STRING) {
 -                      efree(xkey);
 +              if (key.key) {
 +                      zend_string_release(xkey);
                }
        }
 +      ZEND_HASH_FOREACH_END();
 +
        return SUCCESS;
  }
  #endif /* HAVE_ICONV */
  
 -ZEND_RESULT_CODE php_http_querystring_ctor(zval *instance, zval *params TSRMLS_DC)
 +ZEND_RESULT_CODE php_http_querystring_ctor(zval *instance, zval *params)
  {
 -      php_http_querystring_set(instance, params, 0 TSRMLS_CC);
 +      php_http_querystring_set(instance, params, 0);
        return SUCCESS;
  }
  
 -static int apply_querystring(void *pData TSRMLS_DC)
 +static int apply_querystring(zval *val)
  {
 -      zval **val = pData;
 +      if (Z_TYPE_P(val) == IS_ARRAY) {
 +              zval *zvalue;
  
 -      if (Z_TYPE_PP(val) == IS_ARRAY) {
 -              zval **zvalue;
 +              if ((zvalue = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("value")))) {
 +                      zval tmp;
  
 -              if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(val), ZEND_STRS("value"), (void *) &zvalue)) {
 -                      zval *tmp = *val;
 -
 -                      Z_ADDREF_PP(zvalue);
 -                      *val = *zvalue;
 -                      zval_dtor(tmp);
 -                      Z_TYPE_P(tmp) = IS_NULL;
 -                      zval_ptr_dtor(&tmp);
 +                      ZVAL_COPY(&tmp, zvalue);
 +                      zval_dtor(val);
 +                      ZVAL_COPY_VALUE(val, &tmp);
                }
        }
  
        return ZEND_HASH_APPLY_KEEP;
  }
  
 -ZEND_RESULT_CODE php_http_querystring_parse(HashTable *ht, const char *str, size_t len TSRMLS_DC)
 +ZEND_RESULT_CODE php_http_querystring_parse(HashTable *ht, const char *str, size_t len)
  {
        ZEND_RESULT_CODE rv = FAILURE;
        php_http_params_opts_t opts;
        opts.val = vsepp;
        opts.flags = PHP_HTTP_PARAMS_QUERY;
  
 -      if (SUCCESS == php_http_ini_entry(ZEND_STRL("arg_separator.input"), &asi_str, &asi_len, 0 TSRMLS_CC) && asi_len) {
 -              zval *arr;
 +      if (SUCCESS == php_http_ini_entry(ZEND_STRL("arg_separator.input"), &asi_str, &asi_len, 0) && asi_len) {
 +              zval arr;
  
 -              MAKE_STD_ZVAL(arr);
 -              array_init_size(arr, asi_len);
 +              array_init_size(&arr, asi_len);
  
                do {
 -                      add_next_index_stringl(arr, asi_str++, 1, 1);
 +                      add_next_index_stringl(&arr, asi_str++, 1);
                } while (*asi_str);
  
 -              opts.param = php_http_params_separator_init(arr TSRMLS_CC);
 -
 +              opts.param = php_http_params_separator_init(&arr);
                zval_ptr_dtor(&arr);
        }
  
 -      MAKE_STD_ZVAL(opts.defval);
 -      ZVAL_NULL(opts.defval);
 +      ZVAL_NULL(&opts.defval);
  
 -      if (php_http_params_parse(ht, &opts TSRMLS_CC)) {
 -              zend_hash_apply(ht, apply_querystring TSRMLS_CC);
 +      if (php_http_params_parse(ht, &opts)) {
 +              zend_hash_apply(ht, apply_querystring);
                rv = SUCCESS;
        }
  
        return rv;
  }
  
 -ZEND_RESULT_CODE php_http_querystring_update(zval *qarray, zval *params, zval *outstring TSRMLS_DC)
 +ZEND_RESULT_CODE php_http_querystring_update(zval *qarray, zval *params, zval *outstring)
  {
        /* enforce proper type */
        if (Z_TYPE_P(qarray) != IS_ARRAY) {
  
        /* modify qarray */
        if (params) {
 -              HashPosition pos;
 -              HashTable *ptr;
 -              php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
 -              zval **params_entry,  **qarray_entry;
 -              zval zv, *zv_ptr = NULL;
 +              HashTable *ht;
 +              php_http_arrkey_t key;
 +              zval zv, *params_entry, *qarray_entry;
  
 -              INIT_PZVAL(&zv);
                ZVAL_NULL(&zv);
  
                /* squeeze the hash out of the zval */
 -              if (Z_TYPE_P(params) == IS_OBJECT && instanceof_function(Z_OBJCE_P(params), php_http_querystring_class_entry TSRMLS_CC)) {
 -                      zv_ptr = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_querystring_class_entry, params, ZEND_STRL("queryArray"), 0 TSRMLS_CC));
 -                      ptr = Z_ARRVAL_P(zv_ptr);
 +              if (Z_TYPE_P(params) == IS_OBJECT && instanceof_function(Z_OBJCE_P(params), php_http_querystring_class_entry)) {
 +                      zval qa_tmp, *qa = zend_read_property(php_http_querystring_class_entry, params, ZEND_STRL("queryArray"), 0, &qa_tmp);
 +
 +                      ZVAL_DEREF(qa);
 +                      convert_to_array(qa);
 +                      ht = Z_ARRVAL_P(qa);
                } else if (Z_TYPE_P(params) == IS_OBJECT || Z_TYPE_P(params) == IS_ARRAY) {
 -                      ptr = HASH_OF(params);
 +                      ht = HASH_OF(params);
                } else {
 -                      zv_ptr = php_http_ztyp(IS_STRING, params);
 +                      zend_string *zs = zval_get_string(params);
 +
                        array_init(&zv);
 -                      php_http_querystring_parse(Z_ARRVAL(zv), Z_STRVAL_P(zv_ptr), Z_STRLEN_P(zv_ptr) TSRMLS_CC);
 -                      zval_ptr_dtor(&zv_ptr);
 -                      zv_ptr = NULL;
 -                      ptr = Z_ARRVAL(zv);
 +                      php_http_querystring_parse(Z_ARRVAL(zv), zs->val, zs->len);
 +                      zend_string_release(zs);
 +
 +                      ht = Z_ARRVAL(zv);
                }
  
 -              FOREACH_HASH_KEYVAL(pos, ptr, key, params_entry) {
 +              ZEND_HASH_FOREACH_KEY_VAL_IND(ht, key.h, key.key, params_entry)
 +              {
                        /* only public properties */
 -                      if (key.type != HASH_KEY_IS_STRING || *key.str) {
 -                              if (Z_TYPE_PP(params_entry) == IS_NULL) {
 +                      if (!key.key || *key.key->val) {
 +                              if (Z_TYPE_P(params_entry) == IS_NULL) {
                                        /*
                                         * delete
                                         */
 -                                      if (key.type == HASH_KEY_IS_STRING) {
 -                                              zend_hash_del(Z_ARRVAL_P(qarray), key.str, key.len);
 +                                      if (key.key) {
 +                                              zend_hash_del(Z_ARRVAL_P(qarray), key.key);
                                        } else {
 -                                              zend_hash_index_del(Z_ARRVAL_P(qarray), key.num);
 +                                              zend_hash_index_del(Z_ARRVAL_P(qarray), key.h);
                                        }
 -                              } else if (     ((key.type == HASH_KEY_IS_STRING) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), key.str, key.len, (void *) &qarray_entry)))
 -                                              ||      ((key.type == HASH_KEY_IS_LONG) && (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(qarray), key.num, (void *) &qarray_entry)))) {
 +                              } else if (     ((key.key) && (qarray_entry = zend_hash_find(Z_ARRVAL_P(qarray), key.key)))
 +                                              ||      ((!key.key) && (qarray_entry = zend_hash_index_find(Z_ARRVAL_P(qarray), key.h)))) {
                                        /*
                                         * update
                                         */
 -                                      zval equal, *entry = NULL;
 +                                      zval equal, tmp, *entry = &tmp;
  
 +                                      ZVAL_UNDEF(&tmp);
                                        /* recursive */
 -                                      if (Z_TYPE_PP(params_entry) == IS_ARRAY || Z_TYPE_PP(params_entry) == IS_OBJECT) {
 -                                              entry = php_http_zsep(1, IS_ARRAY, *qarray_entry);
 -                                              php_http_querystring_update(entry, *params_entry, NULL TSRMLS_CC);
 -                                      } else if ((FAILURE == is_equal_function(&equal, *qarray_entry, *params_entry TSRMLS_CC)) || !Z_BVAL(equal)) {
 -                                              Z_ADDREF_PP(params_entry);
 -                                              entry = *params_entry;
 +                                      if (Z_TYPE_P(params_entry) == IS_ARRAY || Z_TYPE_P(params_entry) == IS_OBJECT) {
 +                                              ZVAL_DUP(entry, qarray_entry);
 +                                              convert_to_array(entry);
 +                                              php_http_querystring_update(entry, params_entry, NULL);
 +                                      } else if ((FAILURE == is_equal_function(&equal, qarray_entry, params_entry)) || Z_TYPE(equal) != IS_TRUE) {
 +                                              Z_TRY_ADDREF_P(params_entry);
 +                                              entry = params_entry;
                                        }
  
                                        if (entry) {
 -                                              if (key.type == HASH_KEY_IS_STRING) {
 -                                                      zend_hash_update(Z_ARRVAL_P(qarray), key.str, key.len, (void *) &entry, sizeof(zval *), NULL);
 +                                              if (key.key) {
 +                                                      zend_hash_update(Z_ARRVAL_P(qarray), key.key, entry);
                                                } else {
 -                                                      zend_hash_index_update(Z_ARRVAL_P(qarray), key.num, (void *) &entry, sizeof(zval *), NULL);
 +                                                      zend_hash_index_update(Z_ARRVAL_P(qarray), key.h, entry);
                                                }
                                        }
                                } else {
 -                                      zval *entry;
 +                                      zval entry, *entry_ptr = &entry;
                                        /*
                                         * add
                                         */
 -                                      if (Z_TYPE_PP(params_entry) == IS_OBJECT) {
 -                                              MAKE_STD_ZVAL(entry);
 -                                              array_init(entry);
 -                                              php_http_querystring_update(entry, *params_entry, NULL TSRMLS_CC);
 +                                      if (Z_TYPE_P(params_entry) == IS_OBJECT) {
 +                                              array_init(&entry);
 +                                              php_http_querystring_update(&entry, params_entry, NULL);
                                        } else {
 -                                              Z_ADDREF_PP(params_entry);
 -                                              entry = *params_entry;
 +                                              Z_TRY_ADDREF_P(params_entry);
 +                                              entry_ptr = params_entry;
                                        }
 -                                      if (key.type == HASH_KEY_IS_STRING) {
 -                                              add_assoc_zval_ex(qarray, key.str, key.len, entry);
 +                                      if (key.key) {
 +                                              add_assoc_zval_ex(qarray, key.key->val, key.key->len, entry_ptr);
                                        } else {
 -                                              add_index_zval(qarray, key.num, entry);
 +                                              add_index_zval(qarray, key.h, entry_ptr);
                                        }
                                }
                        }
                }
 -              /* clean up */
 -              if (zv_ptr) {
 -                      zval_ptr_dtor(&zv_ptr);
 -              }
 +              ZEND_HASH_FOREACH_END();
 +
                zval_dtor(&zv);
        }
  
                char *s;
                size_t l;
  
 -              if (SUCCESS == php_http_url_encode_hash(Z_ARRVAL_P(qarray), NULL, 0, &s, &l TSRMLS_CC)) {
 +              if (SUCCESS == php_http_url_encode_hash(Z_ARRVAL_P(qarray), NULL, 0, &s, &l)) {
                        zval_dtor(outstring);
 -                      ZVAL_STRINGL(outstring, s, l, 0);
 +                      ZVAL_STR(outstring, php_http_cs2zs(s, l));
                } else {
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to encode query string");
 +                      php_error_docref(NULL, E_WARNING, "Failed to encode query string");
                        return FAILURE;
                }
        }
@@@ -329,53 -330,63 +332,53 @@@ PHP_METHOD(HttpQueryString, __construct
        zval *params = NULL;
        zend_error_handling zeh;
        
 -      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &params), invalid_arg, return);
 +      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &params), invalid_arg, return);
  
 -      zend_replace_error_handling(EH_THROW, php_http_exception_bad_querystring_class_entry, &zeh TSRMLS_CC);
 -      php_http_querystring_set(getThis(), params, 0 TSRMLS_CC);
 -      zend_restore_error_handling(&zeh TSRMLS_CC);
 +      zend_replace_error_handling(EH_THROW, php_http_exception_bad_querystring_class_entry, &zeh);
 +      php_http_querystring_set(getThis(), params, 0);
 +      zend_restore_error_handling(&zeh);
  }
  
  ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_getGlobalInstance, 0, 0, 0)
  ZEND_END_ARG_INFO();
  PHP_METHOD(HttpQueryString, getGlobalInstance)
  {
 -      zval *instance;
 +      zval *instance, *_GET;
 +      zend_string *zs;
  
        php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
  
 -      instance = *zend_std_get_static_property(php_http_querystring_class_entry, ZEND_STRL("instance"), 0 PHP_HTTP_ZEND_LITERAL_CCN TSRMLS_CC);
 -
 -      if (Z_TYPE_P(instance) != IS_OBJECT) {
 -              zval **_GET = NULL;
 -
 -              zend_is_auto_global("_GET", lenof("_GET") TSRMLS_CC);
 +      zs = zend_string_init(ZEND_STRL("instance"), 0);
 +      instance = zend_std_get_static_property(php_http_querystring_class_entry, zs, 0);
 +      zend_string_release(zs);
  
 -              if ((SUCCESS == zend_hash_find(&EG(symbol_table), "_GET", sizeof("_GET"), (void *) &_GET))
 -              &&      (Z_TYPE_PP(_GET) == IS_ARRAY)
 -              ) {
 -                      MAKE_STD_ZVAL(instance);
 -                      ZVAL_OBJVAL(instance, php_http_querystring_object_new(php_http_querystring_class_entry TSRMLS_CC), 0);
 +      if (Z_TYPE_P(instance) == IS_OBJECT) {
 +              RETVAL_ZVAL(instance, 1, 0);
 +      } else if ((_GET = php_http_env_get_superglobal(ZEND_STRL("_GET")))) {
 +              ZVAL_OBJ(return_value, php_http_querystring_object_new(php_http_querystring_class_entry));
  
 -                      SEPARATE_ZVAL_TO_MAKE_IS_REF(_GET);
 -                      convert_to_array(*_GET);
 -                      zend_update_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), *_GET TSRMLS_CC);
 +              ZVAL_MAKE_REF(_GET);
 +              zend_update_property(php_http_querystring_class_entry, return_value, ZEND_STRL("queryArray"), _GET);
  
 -                      zend_update_static_property(php_http_querystring_class_entry, ZEND_STRL("instance"), instance TSRMLS_CC);
 -                      zval_ptr_dtor(&instance);
 -              } else {
 -                      php_http_throw(unexpected_val, "Could not acquire reference to superglobal GET array", NULL);
 -              }
 +              zend_update_static_property(php_http_querystring_class_entry, ZEND_STRL("instance"), return_value);
 +      } else {
 +              php_http_throw(unexpected_val, "Could not acquire reference to superglobal GET array", NULL);
        }
  
 -      RETVAL_ZVAL(instance, 1, 0);
  }
  
  ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_getIterator, 0, 0, 0)
  ZEND_END_ARG_INFO();
  PHP_METHOD(HttpQueryString, getIterator)
  {
 -      zval *retval = NULL, *qa;
 +      zval qa_tmp, *qa;
  
        php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
  
 -      qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
 +      qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0, &qa_tmp);
  
        object_init_ex(return_value, spl_ce_RecursiveArrayIterator);
 -      zend_call_method_with_1_params(&return_value, spl_ce_RecursiveArrayIterator, NULL, "__construct", &retval, qa);
 -      if (retval) {
 -              zval_ptr_dtor(&retval);
 -      }
 +      zend_call_method_with_1_params(return_value, spl_ce_RecursiveArrayIterator, NULL, "__construct", NULL, qa);
  }
  
  ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_toString, 0, 0, 0)
@@@ -385,20 -396,20 +388,20 @@@ PHP_METHOD(HttpQueryString, toString
        if (SUCCESS != zend_parse_parameters_none()) {
                return;
        }
 -      php_http_querystring_str(getThis(), return_value TSRMLS_CC);
 +      php_http_querystring_str(getThis(), return_value);
  }
  
  ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_toArray, 0, 0, 0)
  ZEND_END_ARG_INFO();
  PHP_METHOD(HttpQueryString, toArray)
  {
 -      zval *zqa;
 +      zval zqa_tmp, *zqa;
  
        if (SUCCESS != zend_parse_parameters_none()) {
                return;
        }
  
 -      zqa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
 +      zqa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0, &zqa_tmp);
        RETURN_ZVAL(zqa, 1, 0);
  }
  
@@@ -411,12 -422,12 +414,12 @@@ ZEND_END_ARG_INFO()
  PHP_METHOD(HttpQueryString, get)
  {
        char *name_str = NULL;
 -      int name_len = 0;
 -      long type = 0;
 +      size_t name_len = 0;
 +      zend_long type = 0;
        zend_bool del = 0;
        zval *ztype = NULL, *defval = NULL;
        
 -      if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szzb", &name_str, &name_len, &ztype, &defval, &del)) {
 +      if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|szzb", &name_str, &name_len, &ztype, &defval, &del)) {
                if (name_str && name_len) {
                        if (ztype) {
                                if (Z_TYPE_P(ztype) == IS_LONG) {
                                        }
                                }
                        }
 -                      php_http_querystring_get(getThis(), type, name_str, name_len, defval, del, return_value TSRMLS_CC);
 +                      php_http_querystring_get(getThis(), type, name_str, name_len, defval, del, return_value);
                } else {
 -                      php_http_querystring_str(getThis(), return_value TSRMLS_CC);
 +                      php_http_querystring_str(getThis(), return_value);
                }
        }
  }
@@@ -456,11 -467,11 +459,11 @@@ PHP_METHOD(HttpQueryString, set
  {
        zval *params;
        
 -      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &params)) {
 +      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "z", &params)) {
                return;
        }
        
 -      php_http_querystring_set(getThis(), params, QS_MERGE TSRMLS_CC);
 +      php_http_querystring_set(getThis(), params, QS_MERGE);
        RETVAL_ZVAL(getThis(), 1, 0);
  }
  
@@@ -469,17 -480,15 +472,17 @@@ ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryStri
  ZEND_END_ARG_INFO();
  PHP_METHOD(HttpQueryString, mod)
  {
 -      zval *params;
 +      zval qa_tmp, *params, *instance = getThis();
        zend_error_handling zeh;
  
 -      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &params), invalid_arg, return);
 +      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "z", &params), invalid_arg, return);
        
 -      zend_replace_error_handling(EH_THROW, php_http_exception_bad_querystring_class_entry, &zeh TSRMLS_CC);
 -      ZVAL_OBJVAL(return_value, Z_OBJ_HT_P(getThis())->clone_obj(getThis() TSRMLS_CC), 0);
 -      php_http_querystring_set(return_value, params, QS_MERGE TSRMLS_CC);
 -      zend_restore_error_handling(&zeh TSRMLS_CC);
 +      zend_replace_error_handling(EH_THROW, php_http_exception_bad_querystring_class_entry, &zeh);
 +      ZVAL_OBJ(return_value, Z_OBJ_HT_P(instance)->clone_obj(instance));
 +      /* make sure we do not inherit the reference to _GET */
 +      SEPARATE_ZVAL(zend_read_property(Z_OBJCE_P(return_value), return_value, ZEND_STRL("queryArray"), 0, &qa_tmp));
 +      php_http_querystring_set(return_value, params, QS_MERGE);
 +      zend_restore_error_handling(&zeh);
  }
  
  ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString___getter, 0, 0, 1)
@@@ -491,14 -500,14 +494,14 @@@ ZEND_END_ARG_INFO()
  PHP_METHOD(HttpQueryString, method) \
  { \
        char *name; \
 -      int name_len; \
 +      size_t name_len; \
        zval *defval = NULL; \
        zend_bool del = 0; \
 -      if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zb", &name, &name_len, &defval, &del)) { \
 -              php_http_querystring_get(getThis(), TYPE, name, name_len, defval, del, return_value TSRMLS_CC); \
 +      if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s|zb", &name, &name_len, &defval, &del)) { \
 +              php_http_querystring_get(getThis(), TYPE, name, name_len, defval, del, return_value); \
        } \
  }
 -PHP_HTTP_QUERYSTRING_GETTER(getBool, IS_BOOL);
 +PHP_HTTP_QUERYSTRING_GETTER(getBool, _IS_BOOL);
  PHP_HTTP_QUERYSTRING_GETTER(getInt, IS_LONG);
  PHP_HTTP_QUERYSTRING_GETTER(getFloat, IS_DOUBLE);
  PHP_HTTP_QUERYSTRING_GETTER(getString, IS_STRING);
@@@ -513,25 -522,26 +516,25 @@@ ZEND_END_ARG_INFO()
  PHP_METHOD(HttpQueryString, xlate)
  {
        char *ie, *oe;
 -      int ie_len, oe_len;
 -      zval *na, *qa;
 +      size_t ie_len, oe_len;
 +      zval na, qa_tmp, *qa;
  
 -      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ie, &ie_len, &oe, &oe_len), invalid_arg, return);
 +      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &ie, &ie_len, &oe, &oe_len), invalid_arg, return);
  
 -      MAKE_STD_ZVAL(na);
 -      array_init(na);
 -      qa = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC));
 +      array_init(&na);
 +      qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0, &qa_tmp);
 +      ZVAL_DEREF(qa);
 +      convert_to_array(qa);
  
 -      php_http_expect(SUCCESS == php_http_querystring_xlate(na, qa, ie, oe TSRMLS_CC), bad_conversion,
 +      php_http_expect(SUCCESS == php_http_querystring_xlate(&na, qa, ie, oe), bad_conversion,
                        zval_ptr_dtor(&na);
 -                      zval_ptr_dtor(&qa);
                        return;
        );
  
 -      php_http_querystring_set(getThis(), na, 0 TSRMLS_CC);
 +      php_http_querystring_set(getThis(), &na, 0);
        RETVAL_ZVAL(getThis(), 1, 0);
        
        zval_ptr_dtor(&na);
 -      zval_ptr_dtor(&qa);
  }
  #endif /* HAVE_ICONV */
  
@@@ -542,7 -552,7 +545,7 @@@ PHP_METHOD(HttpQueryString, serialize
        if (SUCCESS != zend_parse_parameters_none()) {
                return;
        }
 -      php_http_querystring_str(getThis(), return_value TSRMLS_CC);
 +      php_http_querystring_str(getThis(), return_value);
  }
  
  ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_unserialize, 0, 0, 1)
@@@ -552,14 -562,14 +555,14 @@@ PHP_METHOD(HttpQueryString, unserialize
  {
        zval *serialized;
        
 -      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &serialized)) {
 +      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "z", &serialized)) {
                return;
        }
  
        if (Z_TYPE_P(serialized) == IS_STRING) {
 -              php_http_querystring_set(getThis(), serialized, 0 TSRMLS_CC);
 +              php_http_querystring_set(getThis(), serialized, 0);
        } else {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected a string as parameter");
 +              php_error_docref(NULL, E_WARNING, "Expected a string as parameter");
        }
  }
  
@@@ -568,19 -578,19 +571,19 @@@ ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryStri
  ZEND_END_ARG_INFO();
  PHP_METHOD(HttpQueryString, offsetGet)
  {
 -      char *offset_str;
 -      int offset_len;
 -      zval **value, *qa;
 +      zend_string *offset;
 +      zval *value, qa_tmp, *qa;
  
 -      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
 +      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "S", &offset)) {
                return;
        }
        
 -      qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
 +      qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0, &qa_tmp);
 +      ZVAL_DEREF(qa);
  
        if (Z_TYPE_P(qa) == IS_ARRAY) {
 -              if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(qa), offset_str, offset_len + 1, (void *) &value)) {
 -                      RETVAL_ZVAL(*value, 1, 0);
 +              if ((value = zend_symtable_find(Z_ARRVAL_P(qa), offset))) {
 +                      RETVAL_ZVAL(value, 1, 0);
                }
        }
  }
@@@ -591,22 -601,27 +594,22 @@@ ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryStri
  ZEND_END_ARG_INFO();
  PHP_METHOD(HttpQueryString, offsetSet)
  {
 -      char *offset_str;
 -      int offset_len;
 -      zval *value, *param;
 +      zend_string *offset;
 +      zval *value, param, znull;
        
 -      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &offset_str, &offset_len, &value)) {
 +      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &offset, &value)) {
                return;
        }
  
 -      param = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
 -
 -      if (Z_TYPE_P(param) == IS_ARRAY && zend_symtable_exists(Z_ARRVAL_P(param), offset_str, offset_len + 1)) {
 -              Z_ADDREF_P(value);
 -              zend_symtable_update(Z_ARRVAL_P(param), offset_str, offset_len + 1, (void *) &value, sizeof(zval *), NULL);
 -              Z_ADDREF_P(param);
 -      } else {
 -              MAKE_STD_ZVAL(param);
 -              array_init(param);
 -              Z_ADDREF_P(value);
 -              add_assoc_zval_ex(param, offset_str, offset_len + 1, value);
 -      }
 -      php_http_querystring_set(getThis(), param, QS_MERGE TSRMLS_CC);
 +      array_init_size(&param, 1);
 +      /* unset first */
 +      ZVAL_NULL(&znull);
 +      zend_symtable_update(Z_ARRVAL(param), offset, &znull);
 +      php_http_querystring_set(getThis(), &param, QS_MERGE);
 +      /* then update, else QS_MERGE would merge sub-arrrays */
 +      Z_TRY_ADDREF_P(value);
 +      zend_symtable_update(Z_ARRVAL(param), offset, value);
 +      php_http_querystring_set(getThis(), &param, QS_MERGE);
        zval_ptr_dtor(&param);
  }
  
@@@ -615,19 -630,19 +618,19 @@@ ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryStri
  ZEND_END_ARG_INFO();
  PHP_METHOD(HttpQueryString, offsetExists)
  {
 -      char *offset_str;
 -      int offset_len;
 -      zval **value, *qa;
 +      zend_string *offset;
 +      zval *value, qa_tmp, *qa;
  
 -      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
 +      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "S", &offset)) {
                return;
        }
        
 -      qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
 +      qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0, &qa_tmp);
 +      ZVAL_DEREF(qa);
  
        if (Z_TYPE_P(qa) == IS_ARRAY) {
 -              if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(qa), offset_str, offset_len + 1, (void *) &value)) {
 -                      RETURN_BOOL(Z_TYPE_PP(value) != IS_NULL);
 +              if ((value = zend_symtable_find(Z_ARRVAL_P(qa), offset))) {
 +                      RETURN_BOOL(Z_TYPE_P(value) != IS_NULL);
                }
        }
        RETURN_FALSE;
@@@ -638,17 -653,18 +641,17 @@@ ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryStri
  ZEND_END_ARG_INFO();
  PHP_METHOD(HttpQueryString, offsetUnset)
  {
 -      char *offset_str;
 -      int offset_len;
 -      zval *param;
 +      zend_string *offset;
 +      zval param, znull;
        
 -      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
 +      if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "S", &offset)) {
                return;
        }
  
 -      MAKE_STD_ZVAL(param);
 -      array_init(param);
 -      add_assoc_null_ex(param, offset_str, offset_len + 1);
 -      php_http_querystring_set(getThis(), param, QS_MERGE TSRMLS_CC);
 +      array_init(&param);
 +      ZVAL_NULL(&znull);
 +      zend_symtable_update(Z_ARRVAL(param), offset, &znull);
 +      php_http_querystring_set(getThis(), &param, QS_MERGE);
        zval_ptr_dtor(&param);
  }
  
@@@ -697,19 -713,19 +700,19 @@@ PHP_MINIT_FUNCTION(http_querystring
        zend_class_entry ce = {0};
  
        INIT_NS_CLASS_ENTRY(ce, "http", "QueryString", php_http_querystring_methods);
 -      php_http_querystring_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 +      php_http_querystring_class_entry = zend_register_internal_class(&ce);
        php_http_querystring_class_entry->create_object = php_http_querystring_object_new;
 -      zend_class_implements(php_http_querystring_class_entry TSRMLS_CC, 3, zend_ce_serializable, zend_ce_arrayaccess, zend_ce_aggregate);
 +      zend_class_implements(php_http_querystring_class_entry, 3, zend_ce_serializable, zend_ce_arrayaccess, zend_ce_aggregate);
  
 -      zend_declare_property_null(php_http_querystring_class_entry, ZEND_STRL("instance"), (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
 -      zend_declare_property_null(php_http_querystring_class_entry, ZEND_STRL("queryArray"), ZEND_ACC_PRIVATE TSRMLS_CC);
 +      zend_declare_property_null(php_http_querystring_class_entry, ZEND_STRL("instance"), (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE));
 +      zend_declare_property_null(php_http_querystring_class_entry, ZEND_STRL("queryArray"), ZEND_ACC_PRIVATE);
  
 -      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_BOOL"), PHP_HTTP_QUERYSTRING_TYPE_BOOL TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_INT"), PHP_HTTP_QUERYSTRING_TYPE_INT TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_FLOAT"), PHP_HTTP_QUERYSTRING_TYPE_FLOAT TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_STRING"), PHP_HTTP_QUERYSTRING_TYPE_STRING TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_ARRAY"), PHP_HTTP_QUERYSTRING_TYPE_ARRAY TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_OBJECT"), PHP_HTTP_QUERYSTRING_TYPE_OBJECT TSRMLS_CC);
 +      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_BOOL"), PHP_HTTP_QUERYSTRING_TYPE_BOOL);
 +      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_INT"), PHP_HTTP_QUERYSTRING_TYPE_INT);
 +      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_FLOAT"), PHP_HTTP_QUERYSTRING_TYPE_FLOAT);
 +      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_STRING"), PHP_HTTP_QUERYSTRING_TYPE_STRING);
 +      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_ARRAY"), PHP_HTTP_QUERYSTRING_TYPE_ARRAY);
 +      zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_OBJECT"), PHP_HTTP_QUERYSTRING_TYPE_OBJECT);
  
        return SUCCESS;
  }
diff --combined php_http_url.c
index 2c5d3f48f86ae719a387335c319776ec59d83803,d7829622bcaea55045bbf9cb72a27ca90528d15d..afe39bfe4511711cb5db2cff518c31e0f4e8952c
@@@ -61,7 -61,7 +61,7 @@@ static inline char *localhostname(void
  
  #define url(buf) ((php_http_url_t *) (buf).data)
  
 -static php_http_url_t *php_http_url_from_env(TSRMLS_D)
 +static php_http_url_t *php_http_url_from_env(void)
  {
        zval *https, *zhost, *zport;
        long port;
@@@ -73,7 -73,7 +73,7 @@@
  
        /* scheme */
        url(buf)->scheme = &buf.data[buf.used];
 -      https = php_http_env_get_server_var(ZEND_STRL("HTTPS"), 1 TSRMLS_CC);
 +      https = php_http_env_get_server_var(ZEND_STRL("HTTPS"), 1);
        if (https && !strcasecmp(Z_STRVAL_P(https), "ON")) {
                php_http_buffer_append(&buf, "https", sizeof("https"));
        } else {
@@@ -82,9 -82,9 +82,9 @@@
  
        /* host */
        url(buf)->host = &buf.data[buf.used];
 -      if ((((zhost = php_http_env_get_server_var(ZEND_STRL("HTTP_HOST"), 1 TSRMLS_CC)) ||
 -                      (zhost = php_http_env_get_server_var(ZEND_STRL("SERVER_NAME"), 1 TSRMLS_CC)) ||
 -                      (zhost = php_http_env_get_server_var(ZEND_STRL("SERVER_ADDR"), 1 TSRMLS_CC)))) && Z_STRLEN_P(zhost)) {
 +      if ((((zhost = php_http_env_get_server_var(ZEND_STRL("HTTP_HOST"), 1)) ||
 +                      (zhost = php_http_env_get_server_var(ZEND_STRL("SERVER_NAME"), 1)) ||
 +                      (zhost = php_http_env_get_server_var(ZEND_STRL("SERVER_ADDR"), 1)))) && Z_STRLEN_P(zhost)) {
                size_t stop_at = strspn(Z_STRVAL_P(zhost), "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-.");
  
                php_http_buffer_append(&buf, Z_STRVAL_P(zhost), stop_at);
@@@ -97,7 -97,7 +97,7 @@@
        }
  
        /* port */
 -      zport = php_http_env_get_server_var(ZEND_STRL("SERVER_PORT"), 1 TSRMLS_CC);
 +      zport = php_http_env_get_server_var(ZEND_STRL("SERVER_PORT"), 1);
        if (zport && IS_LONG == is_numeric_string(Z_STRVAL_P(zport), Z_STRLEN_P(zport), &port, NULL, 0)) {
                url(buf)->port = port;
        }
        } \
  } while (0)
  
 -php_http_url_t *php_http_url_mod(const php_http_url_t *old_url, const php_http_url_t *new_url, unsigned flags TSRMLS_DC)
 +php_http_url_t *php_http_url_mod(const php_http_url_t *old_url, const php_http_url_t *new_url, unsigned flags)
  {
        php_http_url_t *tmp_url = NULL;
        php_http_buffer_t buf;
  
        /* set from env if requested */
        if (flags & PHP_HTTP_URL_FROM_ENV) {
 -              php_http_url_t *env_url = php_http_url_from_env(TSRMLS_C);
 +              php_http_url_t *env_url = php_http_url_from_env();
  
 -              old_url = tmp_url = php_http_url_mod(env_url, old_url, flags ^ PHP_HTTP_URL_FROM_ENV TSRMLS_CC);
 +              old_url = tmp_url = php_http_url_mod(env_url, old_url, flags ^ PHP_HTTP_URL_FROM_ENV);
                php_http_url_free(&env_url);
        }
  
                if ((flags & PHP_HTTP_URL_JOIN_QUERY) && url_isset(new_url, query) && url_isset(old_url, query)) {
                        zval qarr, qstr;
                        
 -                      INIT_PZVAL(&qstr);
 -                      INIT_PZVAL(&qarr);
                        array_init(&qarr);
                        
 -                      ZVAL_STRING(&qstr, old_url->query, 0);
 -                      php_http_querystring_update(&qarr, &qstr, NULL TSRMLS_CC);
 -                      ZVAL_STRING(&qstr, new_url->query, 0);
 -                      php_http_querystring_update(&qarr, &qstr, NULL TSRMLS_CC);
 +                      ZVAL_STRING(&qstr, old_url->query);
 +                      php_http_querystring_update(&qarr, &qstr, NULL);
 +                      zval_ptr_dtor(&qstr);
 +                      ZVAL_STRING(&qstr, new_url->query);
 +                      php_http_querystring_update(&qarr, &qstr, NULL);
 +                      zval_ptr_dtor(&qstr);
                        
                        ZVAL_NULL(&qstr);
 -                      php_http_querystring_update(&qarr, NULL, &qstr TSRMLS_CC);
 +                      php_http_querystring_update(&qarr, NULL, &qstr);
  
                        url(buf)->query = &buf.data[buf.used];
                        url_append(&buf, php_http_buffer_append(&buf, Z_STRVAL(qstr), Z_STRLEN(qstr) + 1));
@@@ -422,9 -422,9 +422,9 @@@ char *php_http_url_authority_to_string(
        return buf.data;
  }
  
 -php_http_url_t *php_http_url_from_zval(zval *value, unsigned flags TSRMLS_DC)
 +php_http_url_t *php_http_url_from_zval(zval *value, unsigned flags)
  {
 -      zval *zcpy;
 +      zend_string *zs;
        php_http_url_t *purl;
  
        switch (Z_TYPE_P(value)) {
                break;
  
        default:
 -              zcpy = php_http_ztyp(IS_STRING, value);
 -              purl = php_http_url_parse(Z_STRVAL_P(zcpy), Z_STRLEN_P(zcpy), flags TSRMLS_CC);
 -              zval_ptr_dtor(&zcpy);
 +              zs = zval_get_string(value);
 +              purl = php_http_url_parse(zs->val, zs->len, flags);
 +              zend_string_release(zs);
        }
  
        return purl;
  
  php_http_url_t *php_http_url_from_struct(HashTable *ht)
  {
 -      zval **e;
 +      zval *e;
        php_http_buffer_t buf;
  
        php_http_buffer_init_ex(&buf, MAX(PHP_HTTP_BUFFER_DEFAULT_SIZE, sizeof(php_http_url_t)<<2), PHP_HTTP_BUFFER_INIT_PREALLOC);
        php_http_buffer_account(&buf, sizeof(php_http_url_t));
        memset(buf.data, 0, buf.used);
  
 -      if (SUCCESS == zend_hash_find(ht, "scheme", sizeof("scheme"), (void *) &e)) {
 -              zval *cpy = php_http_ztyp(IS_STRING, *e);
 +      if ((e = zend_hash_str_find_ind(ht, ZEND_STRL("scheme")))) {
 +              zend_string *zs = zval_get_string(e);
                url(buf)->scheme = &buf.data[buf.used];
 -              url_append(&buf, php_http_buffer_append(&buf, Z_STRVAL_P(cpy), Z_STRLEN_P(cpy) + 1));
 -              zval_ptr_dtor(&cpy);
 +              url_append(&buf, php_http_buffer_append(&buf, zs->val, zs->len + 1));
 +              zend_string_release(zs);
        }
 -      if (SUCCESS == zend_hash_find(ht, "user", sizeof("user"), (void *) &e)) {
 -              zval *cpy = php_http_ztyp(IS_STRING, *e);
 +      if ((e = zend_hash_str_find_ind(ht, ZEND_STRL("user")))) {
 +              zend_string *zs = zval_get_string(e);
                url(buf)->user = &buf.data[buf.used];
 -              url_append(&buf, php_http_buffer_append(&buf, Z_STRVAL_P(cpy), Z_STRLEN_P(cpy) + 1));
 -              zval_ptr_dtor(&cpy);
 +              url_append(&buf, php_http_buffer_append(&buf, zs->val, zs->len + 1));
 +              zend_string_release(zs);
        }
 -      if (SUCCESS == zend_hash_find(ht, "pass", sizeof("pass"), (void *) &e)) {
 -              zval *cpy = php_http_ztyp(IS_STRING, *e);
 +      if ((e = zend_hash_str_find_ind(ht, ZEND_STRL("pass")))) {
 +              zend_string *zs = zval_get_string(e);
                url(buf)->pass = &buf.data[buf.used];
 -              url_append(&buf, php_http_buffer_append(&buf, Z_STRVAL_P(cpy), Z_STRLEN_P(cpy) + 1));
 -              zval_ptr_dtor(&cpy);
 +              url_append(&buf, php_http_buffer_append(&buf, zs->val, zs->len + 1));
 +              zend_string_release(zs);
        }
 -      if (SUCCESS == zend_hash_find(ht, "host", sizeof("host"), (void *) &e)) {
 -              zval *cpy = php_http_ztyp(IS_STRING, *e);
 +      if ((e = zend_hash_str_find_ind(ht, ZEND_STRL("host")))) {
 +              zend_string *zs = zval_get_string(e);
                url(buf)->host = &buf.data[buf.used];
 -              url_append(&buf, php_http_buffer_append(&buf, Z_STRVAL_P(cpy), Z_STRLEN_P(cpy) + 1));
 -              zval_ptr_dtor(&cpy);
 +              url_append(&buf, php_http_buffer_append(&buf, zs->val, zs->len + 1));
 +              zend_string_release(zs);
        }
 -      if (SUCCESS == zend_hash_find(ht, "port", sizeof("port"), (void *) &e)) {
 -              zval *cpy = php_http_ztyp(IS_LONG, *e);
 -              url(buf)->port = (unsigned short) Z_LVAL_P(cpy);
 -              zval_ptr_dtor(&cpy);
 +      if ((e = zend_hash_str_find_ind(ht, ZEND_STRL("port")))) {
 +              url(buf)->port = (unsigned short) zval_get_long(e);
        }
 -      if (SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &e)) {
 -              zval *cpy = php_http_ztyp(IS_STRING, *e);
 +      if ((e = zend_hash_str_find_ind(ht, ZEND_STRL("path")))) {
 +              zend_string *zs = zval_get_string(e);
                url(buf)->path = &buf.data[buf.used];
 -              url_append(&buf, php_http_buffer_append(&buf, Z_STRVAL_P(cpy), Z_STRLEN_P(cpy) + 1));
 -              zval_ptr_dtor(&cpy);
 +              url_append(&buf, php_http_buffer_append(&buf, zs->val, zs->len + 1));
 +              zend_string_release(zs);
        }
 -      if (SUCCESS == zend_hash_find(ht, "query", sizeof("query"), (void *) &e)) {
 -              zval *cpy = php_http_ztyp(IS_STRING, *e);
 +      if ((e = zend_hash_str_find_ind(ht, ZEND_STRL("query")))) {
 +              zend_string *zs = zval_get_string(e);
                url(buf)->query = &buf.data[buf.used];
 -              url_append(&buf, php_http_buffer_append(&buf, Z_STRVAL_P(cpy), Z_STRLEN_P(cpy) + 1));
 -              zval_ptr_dtor(&cpy);
 +              url_append(&buf, php_http_buffer_append(&buf, zs->val, zs->len + 1));
 +              zend_string_release(zs);
        }
 -      if (SUCCESS == zend_hash_find(ht, "fragment", sizeof("fragment"), (void *) &e)) {
 -              zval *cpy = php_http_ztyp(IS_STRING, *e);
 +      if ((e = zend_hash_str_find_ind(ht, ZEND_STRL("fragment")))) {
 +              zend_string *zs = zval_get_string(e);
                url(buf)->fragment = &buf.data[buf.used];
 -              url_append(&buf, php_http_buffer_append(&buf, Z_STRVAL_P(cpy), Z_STRLEN_P(cpy) + 1));
 -              zval_ptr_dtor(&cpy);
 +              url_append(&buf, php_http_buffer_append(&buf, zs->val, zs->len + 1));
 +              zend_string_release(zs);
        }
  
        return url(buf);
  }
  
 -HashTable *php_http_url_to_struct(const php_http_url_t *url, zval *strct TSRMLS_DC)
 +HashTable *php_http_url_to_struct(const php_http_url_t *url, zval *strct)
  {
 -      zval arr;
 +      HashTable *ht;
 +      zval tmp;
  
        if (strct) {
                switch (Z_TYPE_P(strct)) {
                                /* no break */
                        case IS_ARRAY:
                        case IS_OBJECT:
 -                              INIT_PZVAL_ARRAY((&arr), HASH_OF(strct));
 +                              ht = HASH_OF(strct);
                                break;
                }
        } else {
 -              INIT_PZVAL(&arr);
 -              array_init(&arr);
 +              ALLOC_HASHTABLE(ht);
 +              zend_hash_init(ht, 8, NULL, ZVAL_PTR_DTOR, 0);
 +      }
 +
 +#define url_struct_add(part) \
 +      if (Z_TYPE_P(strct) == IS_ARRAY) { \
 +              zend_hash_str_update(Z_ARRVAL_P(strct), part, lenof(part), &tmp); \
 +      } else { \
 +              zend_update_property(Z_OBJCE_P(strct), strct, part, lenof(part), &tmp); \
 +              zval_ptr_dtor(&tmp); \
        }
  
        if (url) {
                if (url->scheme) {
 -                      add_assoc_string(&arr, "scheme", url->scheme, 1);
 +                      ZVAL_STRING(&tmp, url->scheme);
 +                      url_struct_add("scheme");
                }
                if (url->user) {
 -                      add_assoc_string(&arr, "user", url->user, 1);
 +                      ZVAL_STRING(&tmp, url->user);
 +                      url_struct_add("user");
                }
                if (url->pass) {
 -                      add_assoc_string(&arr, "pass", url->pass, 1);
 +                      ZVAL_STRING(&tmp, url->pass);
 +                      url_struct_add("pass");
                }
                if (url->host) {
 -                      add_assoc_string(&arr, "host", url->host, 1);
 +                      ZVAL_STRING(&tmp, url->host);
 +                      url_struct_add("host");
                }
                if (url->port) {
 -                      add_assoc_long(&arr, "port", (long) url->port);
 +                      ZVAL_LONG(&tmp, url->port);
 +                      url_struct_add("port");
                }
                if (url->path) {
 -                      add_assoc_string(&arr, "path", url->path, 1);
 +                      ZVAL_STRING(&tmp, url->path);
 +                      url_struct_add("path");
                }
                if (url->query) {
 -                      add_assoc_string(&arr, "query", url->query, 1);
 +                      ZVAL_STRING(&tmp, url->query);
 +                      url_struct_add("query");
                }
                if (url->fragment) {
 -                      add_assoc_string(&arr, "fragment", url->fragment, 1);
 +                      ZVAL_STRING(&tmp, url->fragment);
 +                      url_struct_add("fragment");
                }
        }
  
 -      return Z_ARRVAL(arr);
 +      return ht;
  }
  
 -ZEND_RESULT_CODE php_http_url_encode_hash(HashTable *hash, const char *pre_encoded_str, size_t pre_encoded_len, char **encoded_str, size_t *encoded_len TSRMLS_DC)
 +ZEND_RESULT_CODE php_http_url_encode_hash(HashTable *hash, const char *pre_encoded_str, size_t pre_encoded_len, char **encoded_str, size_t *encoded_len)
  {
        const char *arg_sep_str = "&";
        size_t arg_sep_len = 1;
        php_http_buffer_t *qstr = php_http_buffer_new();
  
 -      php_http_url_argsep(&arg_sep_str, &arg_sep_len TSRMLS_CC);
 +      php_http_url_argsep(&arg_sep_str, &arg_sep_len);
  
 -      if (SUCCESS != php_http_url_encode_hash_ex(hash, qstr, arg_sep_str, arg_sep_len, "=", 1, pre_encoded_str, pre_encoded_len TSRMLS_CC)) {
 +      if (SUCCESS != php_http_url_encode_hash_ex(hash, qstr, arg_sep_str, arg_sep_len, "=", 1, pre_encoded_str, pre_encoded_len)) {
                php_http_buffer_free(&qstr);
                return FAILURE;
        }
        return SUCCESS;
  }
  
 -ZEND_RESULT_CODE php_http_url_encode_hash_ex(HashTable *hash, php_http_buffer_t *qstr, const char *arg_sep_str, size_t arg_sep_len, const char *val_sep_str, size_t val_sep_len, const char *pre_encoded_str, size_t pre_encoded_len TSRMLS_DC)
 +ZEND_RESULT_CODE php_http_url_encode_hash_ex(HashTable *hash, php_http_buffer_t *qstr, const char *arg_sep_str, size_t arg_sep_len, const char *val_sep_str, size_t val_sep_len, const char *pre_encoded_str, size_t pre_encoded_len)
  {
        if (pre_encoded_len && pre_encoded_str) {
                php_http_buffer_append(qstr, pre_encoded_str, pre_encoded_len);
        }
  
 -      if (!php_http_params_to_string(qstr, hash, arg_sep_str, arg_sep_len, "", 0, val_sep_str, val_sep_len, PHP_HTTP_PARAMS_QUERY TSRMLS_CC)) {
 +      if (!php_http_params_to_string(qstr, hash, arg_sep_str, arg_sep_len, "", 0, val_sep_str, val_sep_len, PHP_HTTP_PARAMS_QUERY)) {
                return FAILURE;
        }
  
  
  struct parse_state {
        php_http_url_t url;
 -#ifdef ZTS
 -      void ***ts;
 -#endif
        const char *ptr;
        const char *end;
        size_t maxlen;
@@@ -759,12 -747,13 +759,12 @@@ static size_t parse_mb(struct parse_sta
        }
  
        if (!silent) {
 -              TSRMLS_FETCH_FROM_CTX(state->ts);
                if (consumed) {
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                      php_error_docref(NULL, E_WARNING,
                                        "Failed to parse %s; unexpected multibyte sequence 0x%x at pos %u in '%s'",
                                        parse_what[what], wchar, (unsigned) (ptr - begin), begin);
                } else {
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                      php_error_docref(NULL, E_WARNING,
                                        "Failed to parse %s; unexpected byte 0x%02x at pos %u in '%s'",
                                        parse_what[what], (unsigned char) *ptr, (unsigned) (ptr - begin), begin);
                }
@@@ -777,6 -766,7 +777,6 @@@ static ZEND_RESULT_CODE parse_userinfo(
  {
        size_t mb;
        const char *password = NULL, *end = state->ptr, *tmp = ptr;
 -      TSRMLS_FETCH_FROM_CTX(state->ts);
  
        state->url.user = &state->buffer[state->offset];
  
                switch (*ptr) {
                case ':':
                        if (password) {
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                              php_error_docref(NULL, E_WARNING,
                                                "Failed to parse password; duplicate ':' at pos %u in '%s'",
                                                (unsigned) (ptr - tmp), tmp);
                                return FAILURE;
  
                case '%':
                        if (ptr[1] != '%' && (end - ptr <= 2 || !isxdigit(*(ptr+1)) || !isxdigit(*(ptr+2)))) {
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                              php_error_docref(NULL, E_WARNING,
                                                "Failed to parse userinfo; invalid percent encoding at pos %u in '%s'",
                                                (unsigned) (ptr - tmp), tmp);
                                return FAILURE;
  
  #if defined(PHP_WIN32) || defined(HAVE_UIDNA_IDNTOASCII)
  typedef size_t (*parse_mb_func)(unsigned *wc, const char *ptr, const char *end);
 -static ZEND_RESULT_CODE to_utf16(parse_mb_func fn, const char *u8, uint16_t **u16, size_t *len TSRMLS_DC)
 +static ZEND_RESULT_CODE to_utf16(parse_mb_func fn, const char *u8, uint16_t **u16, size_t *len)
  {
        size_t offset = 0, u8_len = strlen(u8);
  
  
                if (!consumed) {
                        efree(*u16);
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse UTF-8 at pos %zu of '%s'", offset, u8);
 +                      php_error_docref(NULL, E_WARNING, "Failed to parse UTF-8 at pos %zu of '%s'", offset, u8);
                        return FAILURE;
                } else {
                        offset += consumed;
                case 0:
                default:
                        efree(*u16);
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to convert UTF-32 'U+%X' to UTF-16", wc);
 +                      php_error_docref(NULL, E_WARNING, "Failed to convert UTF-32 'U+%X' to UTF-16", wc);
                        return FAILURE;
                }
        }
@@@ -887,6 -877,7 +887,6 @@@ static ZEND_RESULT_CODE parse_idn2(stru
  {
        char *idn = NULL;
        int rv = -1;
 -      TSRMLS_FETCH_FROM_CTX(state->ts);
  
        if (state->flags & PHP_HTTP_URL_PARSE_MBUTF8) {
                rv = idn2_lookup_u8((const unsigned char *) state->url.host, (unsigned char **) &idn, IDN2_NFC_INPUT);
        }
  #     endif
        if (rv != IDN2_OK) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse IDN; %s", idn2_strerror(rv));
 +              php_error_docref(NULL, E_WARNING, "Failed to parse IDN; %s", idn2_strerror(rv));
                return FAILURE;
        } else {
                size_t idnlen = strlen(idn);
@@@ -912,6 -903,7 +912,6 @@@ static ZEND_RESULT_CODE parse_idn(struc
  {
        char *idn = NULL;
        int rv = -1;
 -      TSRMLS_FETCH_FROM_CTX(state->ts);
  
        if (state->flags & PHP_HTTP_URL_PARSE_MBUTF8) {
                rv = idna_to_ascii_8z(state->url.host, &idn, IDNA_ALLOW_UNASSIGNED|IDNA_USE_STD3_ASCII_RULES);
        }
  #     endif
        if (rv != IDNA_SUCCESS) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse IDN; %s", idna_strerror(rv));
 +              php_error_docref(NULL, E_WARNING, "Failed to parse IDN; %s", idna_strerror(rv));
                return FAILURE;
        } else {
                size_t idnlen = strlen(idn);
@@@ -948,19 -940,20 +948,19 @@@ static ZEND_RESULT_CODE parse_uidn(stru
        uint16_t *uhost_str, ahost_str[MAXHOSTNAMELEN], *ahost_ptr;
        size_t uhost_len, ahost_len;
        UErrorCode error = U_ZERO_ERROR;
 -      TSRMLS_FETCH_FROM_CTX(state->ts);
  
        if (state->flags & PHP_HTTP_URL_PARSE_MBUTF8) {
 -              if (SUCCESS != to_utf16(parse_mb_utf8, state->url.host, &uhost_str, &uhost_len TSRMLS_CC)) {
 +              if (SUCCESS != to_utf16(parse_mb_utf8, state->url.host, &uhost_str, &uhost_len)) {
                        return FAILURE;
                }
  #ifdef PHP_HTTP_HAVE_WCHAR
        } else if (state->flags & PHP_HTTP_URL_PARSE_MBLOC) {
 -              if (SUCCESS != to_utf16(parse_mb_loc, state->url.host, &uhost_str, &uhost_len TSRMLS_CC)) {
 +              if (SUCCESS != to_utf16(parse_mb_loc, state->url.host, &uhost_str, &uhost_len)) {
                        return FAILURE;
                }
  #endif
        } else {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse IDN; codepage not specified");
 +              php_error_docref(NULL, E_WARNING, "Failed to parse IDN; codepage not specified");
                return FAILURE;
        }
  
        efree(uhost_str);
  
        if (error != U_ZERO_ERROR) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse IDN; ICU error %d", error);
 +              php_error_docref(NULL, E_WARNING, "Failed to parse IDN; ICU error %d", error);
                return FAILURE;
        }
  
@@@ -989,27 -982,28 +989,27 @@@ static ZEND_RESULT_CODE parse_widn(stru
        char *host_ptr;
        uint16_t *uhost_str, ahost_str[MAXHOSTNAMELEN], *ahost_ptr;
        size_t uhost_len;
 -      TSRMLS_FETCH_FROM_CTX(state->ts);
  
        if (state->flags & PHP_HTTP_URL_PARSE_MBUTF8) {
                if (SUCCESS != to_utf16(parse_mb_utf8, state->url.host, &uhost_str, &uhost_len)) {
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse IDN");
 +                      php_error_docref(NULL, E_WARNING, "Failed to parse IDN");
                        return FAILURE;
                }
  #ifdef PHP_HTTP_HAVE_WCHAR
        } else if (state->flags & PHP_HTTP_URL_PARSE_MBLOC) {
                if (SUCCESS != to_utf16(parse_mb_loc, state->url.host, &uhost_str, &uhost_len)) {
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse IDN");
 +                      php_error_docref(NULL, E_WARNING, "Failed to parse IDN");
                        return FAILURE;
                }
  #endif
        } else {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse IDN");
 +              php_error_docref(NULL, E_WARNING, "Failed to parse IDN");
                return FAILURE;
        }
  
        if (!IdnToAscii(IDN_ALLOW_UNASSIGNED|IDN_USE_STD3_ASCII_RULES, uhost_str, uhost_len, ahost_str, MAXHOSTNAMELEN)) {
                efree(uhost_str);
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse IDN");
 +              php_error_docref(NULL, E_WARNING, "Failed to parse IDN");
                return FAILURE;
        }
  
@@@ -1030,6 -1024,7 +1030,6 @@@ static ZEND_RESULT_CODE parse_hostinfo(
  {
        size_t mb, len;
        const char *end = state->ptr, *tmp = ptr, *port = NULL;
 -      TSRMLS_FETCH_FROM_CTX(state->ts);
  
  #ifdef HAVE_INET_PTON
        if (*ptr == '[') {
                }
  
                if (error) {
 -                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse hostinfo; %s", error);
 +                      php_error_docref(NULL, E_WARNING, "Failed to parse hostinfo; %s", error);
                        return FAILURE;
                }
        }
                switch (*ptr) {
                case ':':
                        if (port) {
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                              php_error_docref(NULL, E_WARNING,
                                                "Failed to parse port; unexpected ':' at pos %u in '%s'",
                                                (unsigned) (ptr - tmp), tmp);
                                return FAILURE;
  
                case '%':
                        if (ptr[1] != '%' && (end - ptr <= 2 || !isxdigit(*(ptr+1)) || !isxdigit(*(ptr+2)))) {
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                              php_error_docref(NULL, E_WARNING,
                                                "Failed to parse hostinfo; invalid percent encoding at pos %u in '%s'",
                                                (unsigned) (ptr - tmp), tmp);
                                return FAILURE;
                case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
                case 'v': case 'w': case 'x': case 'y': case 'z':
                        if (port) {
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                              php_error_docref(NULL, E_WARNING,
                                                "Failed to parse port; unexpected char '%c' at pos %u in '%s'",
                                                (unsigned char) *ptr, (unsigned) (ptr - tmp), tmp);
                                return FAILURE;
                        if (ptr == end) {
                                break;
                        } else if (port) {
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                              php_error_docref(NULL, E_WARNING,
                                                "Failed to parse port; unexpected byte 0x%02x at pos %u in '%s'",
                                                (unsigned char) *ptr, (unsigned) (ptr - tmp), tmp);
                                return FAILURE;
@@@ -1164,7 -1159,8 +1164,7 @@@ static const char *parse_authority(stru
                case '@':
                        /* userinfo delimiter */
                        if (host) {
 -                              TSRMLS_FETCH_FROM_CTX(state->ts);
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                              php_error_docref(NULL, E_WARNING,
                                                "Failed to parse userinfo; unexpected '@'");
                                return NULL;
                        }
@@@ -1196,6 -1192,7 +1196,6 @@@ static const char *parse_path(struct pa
  {
        size_t mb;
        const char *tmp;
 -      TSRMLS_FETCH_FROM_CTX(state->ts);
  
        /* is there actually a path to parse? */
        if (!*state->ptr) {
  
                case '%':
                        if (state->ptr[1] != '%' && (state->end - state->ptr <= 2 || !isxdigit(*(state->ptr+1)) || !isxdigit(*(state->ptr+2)))) {
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                              php_error_docref(NULL, E_WARNING,
                                                "Failed to parse path; invalid percent encoding at pos %u in '%s'",
                                                (unsigned) (state->ptr - tmp), tmp);
                                return NULL;
@@@ -1263,6 -1260,7 +1263,6 @@@ static const char *parse_query(struct p
  {
        size_t mb;
        const char *tmp = state->ptr + !!*state->ptr;
 -      TSRMLS_FETCH_FROM_CTX(state->ts);
  
        /* is there actually a query to parse? */
        if (*state->ptr != '?') {
  
                case '%':
                        if (state->ptr[1] != '%' && (state->end - state->ptr <= 2 || !isxdigit(*(state->ptr+1)) || !isxdigit(*(state->ptr+2)))) {
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                              php_error_docref(NULL, E_WARNING,
                                                "Failed to parse query; invalid percent encoding at pos %u in '%s'",
                                                (unsigned) (state->ptr - tmp), tmp);
                                return NULL;
                        state->buffer[state->offset++] = *state->ptr;
                        break;
  
-               case ']':
-               case '[':
+               /* RFC1738 unsafe */
+               case '{': case '}':
+               case '<': case '>':
+               case '[': case ']':
+               case '|': case '\\': case '^': case '`': case '"': case ' ':
                        if (state->flags & PHP_HTTP_URL_PARSE_TOPCT) {
                                state->buffer[state->offset++] = '%';
                                state->buffer[state->offset++] = parse_xdigits[((unsigned char) *state->ptr) >> 4];
@@@ -1338,6 -1339,7 +1341,6 @@@ static const char *parse_fragment(struc
  {
        size_t mb;
        const char *tmp;
 -      TSRMLS_FETCH_FROM_CTX(state->ts);
  
        /* is there actually a fragment to parse? */
        if (*state->ptr != '#') {
                switch (*state->ptr) {
                case '%':
                        if (state->ptr[1] != '%' && (state->end - state->ptr <= 2 || !isxdigit(*(state->ptr+1)) || !isxdigit(*(state->ptr+2)))) {
 -                              php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +                              php_error_docref(NULL, E_WARNING,
                                                "Failed to parse fragment; invalid percent encoding at pos %u in '%s'",
                                                (unsigned) (state->ptr - tmp), tmp);
                                return NULL;
                        state->buffer[state->offset++] = *state->ptr;
                        break;
  
+               /* RFC1738 unsafe */
+               case '{': case '}':
+               case '<': case '>':
+               case '[': case ']':
+               case '|': case '\\': case '^': case '`': case '"': case ' ':
+                       if (state->flags & PHP_HTTP_URL_PARSE_TOPCT) {
+                               state->buffer[state->offset++] = '%';
+                               state->buffer[state->offset++] = parse_xdigits[((unsigned char) *state->ptr) >> 4];
+                               state->buffer[state->offset++] = parse_xdigits[((unsigned char) *state->ptr) & 0xf];
+                               break;
+                       }
+                       /* no break */
                case '?': case '/':
                case '!': case '$': case '&': case '\'': case '(': case ')': case '*':
                case '+': case ',': case ';': case '=': /* sub-delims */
@@@ -1452,7 -1467,7 +1468,7 @@@ static const char *parse_scheme(struct 
        return state->ptr = tmp;
  }
  
 -php_http_url_t *php_http_url_parse(const char *str, size_t len, unsigned flags TSRMLS_DC)
 +php_http_url_t *php_http_url_parse(const char *str, size_t len, unsigned flags)
  {
        size_t maxlen = 3 * len;
        struct parse_state *state = ecalloc(1, sizeof(*state) + maxlen);
        state->ptr = str;
        state->flags = flags;
        state->maxlen = maxlen;
 -      TSRMLS_SET_CTX(state->ts);
  
        if (!parse_scheme(state)) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse URL scheme: '%s'", state->ptr);
 +              php_error_docref(NULL, E_WARNING, "Failed to parse URL scheme: '%s'", state->ptr);
                efree(state);
                return NULL;
        }
        }
  
        if (!parse_query(state)) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse URL query: '%s'", state->ptr);
 +              php_error_docref(NULL, E_WARNING, "Failed to parse URL query: '%s'", state->ptr);
                efree(state);
                return NULL;
        }
  
        if (!parse_fragment(state)) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse URL fragment: '%s'", state->ptr);
 +              php_error_docref(NULL, E_WARNING, "Failed to parse URL fragment: '%s'", state->ptr);
                efree(state);
                return NULL;
        }
        return (php_http_url_t *) state;
  }
  
 -php_http_url_t *php_http_url_parse_authority(const char *str, size_t len, unsigned flags TSRMLS_DC)
 +php_http_url_t *php_http_url_parse_authority(const char *str, size_t len, unsigned flags)
  {
        size_t maxlen = 3 * len;
        struct parse_state *state = ecalloc(1, sizeof(*state) + maxlen);
        state->ptr = str;
        state->flags = flags;
        state->maxlen = maxlen;
 -      TSRMLS_SET_CTX(state->ts);
  
        if (!(state->ptr = parse_authority(state))) {
                efree(state);
        }
  
        if (state->ptr != state->end) {
 -              php_error_docref(NULL TSRMLS_CC, E_WARNING,
 +              php_error_docref(NULL, E_WARNING,
                                "Failed to parse URL authority, unexpected character at pos %u in '%s'",
                                (unsigned) (state->ptr - str), str);
                efree(state);
@@@ -1522,35 -1539,35 +1538,35 @@@ ZEND_END_ARG_INFO()
  PHP_METHOD(HttpUrl, __construct)
  {
        zval *new_url = NULL, *old_url = NULL;
 -      long flags = PHP_HTTP_URL_FROM_ENV;
 +      zend_long flags = PHP_HTTP_URL_FROM_ENV;
        zend_error_handling zeh;
  
 -      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!z!l", &old_url, &new_url, &flags), invalid_arg, return);
 +      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|z!z!l", &old_url, &new_url, &flags), invalid_arg, return);
  
 -      zend_replace_error_handling(EH_THROW, php_http_exception_bad_url_class_entry, &zeh TSRMLS_CC);
 +      zend_replace_error_handling(EH_THROW, php_http_exception_bad_url_class_entry, &zeh);
        {
                php_http_url_t *res_purl, *new_purl = NULL, *old_purl = NULL;
  
                if (new_url) {
 -                      new_purl = php_http_url_from_zval(new_url, flags TSRMLS_CC);
 +                      new_purl = php_http_url_from_zval(new_url, flags);
                        if (!new_purl) {
 -                              zend_restore_error_handling(&zeh TSRMLS_CC);
 +                              zend_restore_error_handling(&zeh);
                                return;
                        }
                }
                if (old_url) {
 -                      old_purl = php_http_url_from_zval(old_url, flags TSRMLS_CC);
 +                      old_purl = php_http_url_from_zval(old_url, flags);
                        if (!old_purl) {
                                if (new_purl) {
                                        php_http_url_free(&new_purl);
                                }
 -                              zend_restore_error_handling(&zeh TSRMLS_CC);
 +                              zend_restore_error_handling(&zeh);
                                return;
                        }
                }
  
 -              res_purl = php_http_url_mod(old_purl, new_purl, flags TSRMLS_CC);
 -              php_http_url_to_struct(res_purl, getThis() TSRMLS_CC);
 +              res_purl = php_http_url_mod(old_purl, new_purl, flags);
 +              php_http_url_to_struct(res_purl, getThis());
  
                php_http_url_free(&res_purl);
                if (old_purl) {
                        php_http_url_free(&new_purl);
                }
        }
 -      zend_restore_error_handling(&zeh TSRMLS_CC);
 +      zend_restore_error_handling(&zeh);
  }
  
  ZEND_BEGIN_ARG_INFO_EX(ai_HttpUrl_mod, 0, 0, 1)
@@@ -1570,19 -1587,19 +1586,19 @@@ ZEND_END_ARG_INFO()
  PHP_METHOD(HttpUrl, mod)
  {
        zval *new_url = NULL;
 -      long flags = PHP_HTTP_URL_JOIN_PATH | PHP_HTTP_URL_JOIN_QUERY | PHP_HTTP_URL_SANITIZE_PATH;
 +      zend_long flags = PHP_HTTP_URL_JOIN_PATH | PHP_HTTP_URL_JOIN_QUERY | PHP_HTTP_URL_SANITIZE_PATH;
        zend_error_handling zeh;
  
 -      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!|l", &new_url, &flags), invalid_arg, return);
 +      php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "z!|l", &new_url, &flags), invalid_arg, return);
  
 -      zend_replace_error_handling(EH_THROW, php_http_exception_bad_url_class_entry, &zeh TSRMLS_CC);
 +      zend_replace_error_handling(EH_THROW, php_http_exception_bad_url_class_entry, &zeh);
        {
                php_http_url_t *new_purl = NULL, *old_purl = NULL;
  
                if (new_url) {
 -                      new_purl = php_http_url_from_zval(new_url, flags TSRMLS_CC);
 +                      new_purl = php_http_url_from_zval(new_url, flags);
                        if (!new_purl) {
 -                              zend_restore_error_handling(&zeh TSRMLS_CC);
 +                              zend_restore_error_handling(&zeh);
                                return;
                        }
                }
                if ((old_purl = php_http_url_from_struct(HASH_OF(getThis())))) {
                        php_http_url_t *res_purl;
  
 -                      ZVAL_OBJVAL(return_value, zend_objects_clone_obj(getThis() TSRMLS_CC), 0);
 +                      ZVAL_OBJ(return_value, zend_objects_clone_obj(getThis()));
  
 -                      res_purl = php_http_url_mod(old_purl, new_purl, flags TSRMLS_CC);
 -                      php_http_url_to_struct(res_purl, return_value TSRMLS_CC);
 +                      res_purl = php_http_url_mod(old_purl, new_purl, flags);
 +                      php_http_url_to_struct(res_purl, return_value);
  
                        php_http_url_free(&res_purl);
                        php_http_url_free(&old_purl);
                        php_http_url_free(&new_purl);
                }
        }
 -      zend_restore_error_handling(&zeh TSRMLS_CC);
 +      zend_restore_error_handling(&zeh);
  }
  
  ZEND_BEGIN_ARG_INFO_EX(ai_HttpUrl_toString, 0, 0, 0)
@@@ -1618,7 -1635,7 +1634,7 @@@ PHP_METHOD(HttpUrl, toString
  
                        php_http_url_to_string(purl, &str, &len, 0);
                        php_http_url_free(&purl);
 -                      RETURN_STRINGL(str, len, 0);
 +                      RETURN_STR(php_http_cs2zs(str, len));
                }
        }
        RETURN_EMPTY_STRING();
@@@ -1636,7 -1653,7 +1652,7 @@@ PHP_METHOD(HttpUrl, toArray
  
        /* strip any non-URL properties */
        purl = php_http_url_from_struct(HASH_OF(getThis()));
 -      php_http_url_to_struct(purl, return_value TSRMLS_CC);
 +      php_http_url_to_struct(purl, return_value);
        php_http_url_free(&purl);
  }
  
@@@ -1656,39 -1673,39 +1672,39 @@@ PHP_MINIT_FUNCTION(http_url
        zend_class_entry ce = {0};
  
        INIT_NS_CLASS_ENTRY(ce, "http", "Url", php_http_url_methods);
 -      php_http_url_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 -
 -      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("scheme"), ZEND_ACC_PUBLIC TSRMLS_CC);
 -      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("user"), ZEND_ACC_PUBLIC TSRMLS_CC);
 -      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("pass"), ZEND_ACC_PUBLIC TSRMLS_CC);
 -      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("host"), ZEND_ACC_PUBLIC TSRMLS_CC);
 -      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("port"), ZEND_ACC_PUBLIC TSRMLS_CC);
 -      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("path"), ZEND_ACC_PUBLIC TSRMLS_CC);
 -      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("query"), ZEND_ACC_PUBLIC TSRMLS_CC);
 -      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("fragment"), ZEND_ACC_PUBLIC TSRMLS_CC);
 -
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("REPLACE"), PHP_HTTP_URL_REPLACE TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("JOIN_PATH"), PHP_HTTP_URL_JOIN_PATH TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("JOIN_QUERY"), PHP_HTTP_URL_JOIN_QUERY TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_USER"), PHP_HTTP_URL_STRIP_USER TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_PASS"), PHP_HTTP_URL_STRIP_PASS TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_AUTH"), PHP_HTTP_URL_STRIP_AUTH TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_PORT"), PHP_HTTP_URL_STRIP_PORT TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_PATH"), PHP_HTTP_URL_STRIP_PATH TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_QUERY"), PHP_HTTP_URL_STRIP_QUERY TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_FRAGMENT"), PHP_HTTP_URL_STRIP_FRAGMENT TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_ALL"), PHP_HTTP_URL_STRIP_ALL TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("FROM_ENV"), PHP_HTTP_URL_FROM_ENV TSRMLS_CC);
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("SANITIZE_PATH"), PHP_HTTP_URL_SANITIZE_PATH TSRMLS_CC);
 +      php_http_url_class_entry = zend_register_internal_class(&ce);
 +
 +      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("scheme"), ZEND_ACC_PUBLIC);
 +      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("user"), ZEND_ACC_PUBLIC);
 +      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("pass"), ZEND_ACC_PUBLIC);
 +      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("host"), ZEND_ACC_PUBLIC);
 +      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("port"), ZEND_ACC_PUBLIC);
 +      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("path"), ZEND_ACC_PUBLIC);
 +      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("query"), ZEND_ACC_PUBLIC);
 +      zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("fragment"), ZEND_ACC_PUBLIC);
 +
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("REPLACE"), PHP_HTTP_URL_REPLACE);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("JOIN_PATH"), PHP_HTTP_URL_JOIN_PATH);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("JOIN_QUERY"), PHP_HTTP_URL_JOIN_QUERY);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_USER"), PHP_HTTP_URL_STRIP_USER);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_PASS"), PHP_HTTP_URL_STRIP_PASS);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_AUTH"), PHP_HTTP_URL_STRIP_AUTH);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_PORT"), PHP_HTTP_URL_STRIP_PORT);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_PATH"), PHP_HTTP_URL_STRIP_PATH);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_QUERY"), PHP_HTTP_URL_STRIP_QUERY);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_FRAGMENT"), PHP_HTTP_URL_STRIP_FRAGMENT);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STRIP_ALL"), PHP_HTTP_URL_STRIP_ALL);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("FROM_ENV"), PHP_HTTP_URL_FROM_ENV);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("SANITIZE_PATH"), PHP_HTTP_URL_SANITIZE_PATH);
  
  #ifdef PHP_HTTP_HAVE_WCHAR
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("PARSE_MBLOC"), PHP_HTTP_URL_PARSE_MBLOC TSRMLS_CC);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("PARSE_MBLOC"), PHP_HTTP_URL_PARSE_MBLOC);
  #endif
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("PARSE_MBUTF8"), PHP_HTTP_URL_PARSE_MBUTF8 TSRMLS_CC);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("PARSE_MBUTF8"), PHP_HTTP_URL_PARSE_MBUTF8);
  #if defined(PHP_HTTP_HAVE_IDN2) || defined(PHP_HTTP_HAVE_IDN) || defined(HAVE_UIDNA_IDNTOASCII)
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("PARSE_TOIDN"), PHP_HTTP_URL_PARSE_TOIDN TSRMLS_CC);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("PARSE_TOIDN"), PHP_HTTP_URL_PARSE_TOIDN);
  #endif
 -      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("PARSE_TOPCT"), PHP_HTTP_URL_PARSE_TOPCT TSRMLS_CC);
 +      zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("PARSE_TOPCT"), PHP_HTTP_URL_PARSE_TOPCT);
  
        return SUCCESS;
  }
diff --combined tests/helper/server.inc
index a13dc12027d89204d1d49192b0ea77bde57f4d23,029cd46e55359262f4288f6c2336e877db13706f..091ff5cd483834d5c88d7e6304b42270bad9fe91
@@@ -1,5 -1,19 +1,19 @@@
  <?php
  
+ ini_set("log_errors", true);
+ ini_set("error_log", __DIR__."/server.log");
+ function logger() {
+       if (!ini_get("date.timezone")) {
+               date_default_timezone_set(@date_default_timezone_get());
+       }
+       error_log(sprintf("%s(%s): %s", 
+               basename(getenv("SCRIPT_FILENAME"), ".php"), 
+               basename(current(get_included_files()), ".inc"), 
+               call_user_func_array("sprintf", func_get_args())
+       ));
+ }
  $php = getenv('TEST_PHP_EXECUTABLE');
  if ($php) {
        define('PHP_BIN', $php);
        define("PHP_BIN", PHP_BINDIR.DIRECTORY_SEPARATOR."php");
  }
  
 +foreach (array("raphf", "propro", "http") as $ext) {
 +      if (!extension_loaded($ext)) {
 +              switch (PHP_SHLIB_SUFFIX) {
 +                      case "dll":
 +                              dl("php_$ext.dll"); 
 +                              break;
 +                      default:
 +                              dl($ext .".". PHP_SHLIB_SUFFIX);
 +              }
 +      }
 +}
 +
  function serve($cb) {
        /* stream_socket_server() automatically sets SO_REUSEADDR, 
         * which is, well, bad if the tests are run in parallel
         */
        $offset = rand(0,2000);
        foreach (range(8000+$offset, 9000+$offset) as $port) {
+               logger("serve: Trying port %d", $port);
                if (($server = @stream_socket_server("tcp://localhost:$port"))) {
                        fprintf(STDERR, "%s\n", $port);
+                       logger("serve: Using port %d", $port);
                        do {
                                $R = array($server); $W = array(); $E = array();
-                               $select = stream_select($R, $E, $E, 0, 10000);
+                               $select = stream_select($R, $E, $E, 10, 0);
                                if ($select && ($client = stream_socket_accept($server, 1))) {
+                                       logger("serve: Accept client %d", (int) $client);
                                        if (getenv("PHP_HTTP_TEST_SSL")) {
                                                stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_SSLv23_SERVER);
                                        }
                                        try {
                                                while (!feof($client)) {
+                                                       logger("serve: Handle client %d", (int) $client);
                                                        $cb($client);
                                                }
+                                               logger("serve: EOF on client %d", (int) $client);
                                        } catch (Exception $ex) {
+                                               logger("serve: Exception on client %d: %s", (int) $client, $ex->getMessage());
                                                /* ignore disconnect */
                                                if ($ex->getMessage() !== "Empty message received from stream") {
                                                        fprintf(STDERR, "%s\n", $ex);
@@@ -49,7 -57,7 +69,7 @@@
                                                break;
                                        }
                                }
-                       } while ($select !== false);
+                       } while ($select);
                        return;
                }
        }
@@@ -123,4 -131,4 +143,4 @@@ function proc($bin, $args, $cb) 
                fpassthru($stderr);
                fpassthru($stdout);
        }
- }
+ }