* flush *
authorMichael Wallner <mike@php.net>
Sun, 22 May 2005 17:24:15 +0000 (17:24 +0000)
committerMichael Wallner <mike@php.net>
Sun, 22 May 2005 17:24:15 +0000 (17:24 +0000)
- added PHP_FUNCTIONS:
  http_throttle, http_request_method_(register|unregister|exists|name)
- added PHP_METHODS:
  HttpResponse::(set|get)ThrottleDelay, HttpResponse::(set|get)SendBuffersize
- http_globals cleanup
- added request methods to MINFO
- register error code constants
- added provisory http_message_dup() for the HttpMessage clone handler
- added some missing functions in missing.c
# gcc fixes follow

25 files changed:
config.w32
http.c
http_api.c
http_cache_api.c
http_exception_object.c
http_functions.c
http_message_api.c
http_message_object.c
http_methods.c
http_request_api.c
http_response_object.c
http_send_api.c
missing.c [new file with mode: 0644]
missing.h [new file with mode: 0644]
package.xml
php_http.h
php_http_exception_object.h
php_http_message_api.h
php_http_message_object.h
php_http_request_api.h
php_http_request_object.h
php_http_response_object.h
php_http_send_api.h
php_http_std_defs.h
php_http_util_object.h

index 76adf5f..f539b40 100644 (file)
@@ -2,10 +2,11 @@
 // $Id$
 
 ARG_ENABLE("http", "whether to enable extended HTTP support", "no");
+ARG_WITH("http-curl-zend-mm", "wheter ext/http's curl should use zend mm");
 
 if (PHP_HTTP != "no") {
        EXTENSION("http",
-               "http.c http_functions.c http_methods.c http_exception_object.c "+
+               "missing.c http.c http_functions.c http_methods.c http_exception_object.c "+
                "http_util_object.c http_message_object.c "+
                "http_request_object.c http_response_object.c "+
                "http_api.c http_auth_api.c http_cache_api.c "+
@@ -22,7 +23,10 @@ if (PHP_HTTP != "no") {
             CHECK_LIB("zlib.lib", "http", PHP_HTTP) &&
             CHECK_LIB("winmm.lib", "http", PHP_HTTP)) {
         AC_DEFINE("HTTP_HAVE_CURL", 1, "Have CURL library");
+               if (PHP_HTTP_CURL_ZEND_MM == "yes") {
+                       AC_DEFINE("HTTP_CURL_USE_ZEND_MM", 1, "CURL library shall use Zend MM");
+               }
     } else {
         WARNING("curl convenience functions not enabled; libraries and headers not found");
     }
-}
+}
\ No newline at end of file
diff --git a/http.c b/http.c
index b214c4c..7b90bd0 100644 (file)
--- a/http.c
+++ b/http.c
@@ -98,6 +98,7 @@ function_entry http_functions[] = {
        PHP_FE(http_negotiate_language, NULL)
        PHP_FE(http_negotiate_charset, NULL)
        PHP_FE(http_redirect, NULL)
+       PHP_FE(http_throttle, NULL)
        PHP_FE(http_send_status, NULL)
        PHP_FE(http_send_last_modified, NULL)
        PHP_FE(http_send_content_type, NULL)
@@ -120,6 +121,10 @@ function_entry http_functions[] = {
        PHP_FE(http_post_fields, http_request_info_ref_5)
        PHP_FE(http_put_file, http_request_info_ref_4)
        PHP_FE(http_put_stream, http_request_info_ref_4)
+       PHP_FE(http_request_method_register, NULL)
+       PHP_FE(http_request_method_unregister, NULL)
+       PHP_FE(http_request_method_exists, NULL)
+       PHP_FE(http_request_method_name, NULL)
 #endif
        PHP_FE(http_auth_basic, NULL)
        PHP_FE(http_auth_basic_cb, NULL)
@@ -150,54 +155,32 @@ zend_module_entry http_module_entry = {
 };
 /* }}} */
 
+#ifdef HTTP_HAVE_CURL
+#      ifdef HTTP_CURL_USE_ZEND_MM
+static void http_curl_free(void *p)                                    { efree(p); }
+static char *http_curl_strdup(const char *p)           { return estrdup(p); }
+static void *http_curl_malloc(size_t s)                                { return emalloc(s); }
+static void *http_curl_realloc(void *p, size_t s)      { return erealloc(p, s); }
+static void *http_curl_calloc(size_t n, size_t s)      { return ecalloc(n, s); }
+#      endif /* HTTP_CURL_USE_ZEND_MM */
+static void http_curl_freestr(void *s)                         { efree(*(char **)s); }
+#endif /* HTTP_HAVE_CURL */
 
-static void free_to_free(void *s)
-{
-       efree(*(char **)s);
-}
-
-/* {{{ void http_globals_ctor(zend_http_globals *) */
-#define http_globals_ctor _http_globals_ctor
-static inline void _http_globals_ctor(zend_http_globals *http_globals)
+/* {{{ http_globals */
+static inline void http_globals_init(zend_http_globals *G)
 {
-       http_globals->etag_started = 0;
-       http_globals->ctype = NULL;
-       http_globals->etag  = NULL;
-       http_globals->lmod  = 0;
+       memset(G, 0, sizeof(zend_http_globals));
+       G->send.buffer_size = HTTP_SENDBUF_SIZE;
+       zend_hash_init(&G->request.methods.custom, 0, NULL, ZVAL_PTR_DTOR, 0);
 #ifdef HTTP_HAVE_CURL
-#      if LIBCURL_VERSION_NUM < 0x070c00
-       memset(&http_globals->curlerr, 0, sizeof(http_globals->curlerr));
-#      endif
-       zend_llist_init(&http_globals->to_free, sizeof(char *), free_to_free, 0);
+       zend_llist_init(&G->request.curl.copies, sizeof(char *), http_curl_freestr, 0);
 #endif
-       http_globals->allowed_methods = NULL;
-       http_globals->cache_log = NULL;
 }
-/* }}} */
-
-/* {{{ void http_globals_dtor() */
-#define http_globals_dtor() _http_globals_dtor(TSRMLS_C)
-static inline void _http_globals_dtor(TSRMLS_D)
+static inline void http_globals_free(zend_http_globals *G)
 {
-       HTTP_G(etag_started) = 0;
-       HTTP_G(lmod) = 0;
-
-       if (HTTP_G(etag)) {
-               efree(HTTP_G(etag));
-               HTTP_G(etag) = NULL;
-       }
-
-       if (HTTP_G(ctype)) {
-               efree(HTTP_G(ctype));
-               HTTP_G(ctype) = NULL;
-       }
-
-#ifdef HTTP_HAVE_CURL
-#      if LIBCURL_VERSION_NUM < 0x070c00
-       memset(&HTTP_G(curlerr), 0, sizeof(HTTP_G(curlerr)));
-#      endif
-#endif
-
+       STR_FREE(G->send.content_type);
+       STR_FREE(G->send.unquoted_etag);
+       zend_hash_destroy(&G->request.methods.custom);
 }
 /* }}} */
 
@@ -222,28 +205,17 @@ PHP_INI_MH(http_update_allowed_methods)
        return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
 }
 
-#define http_update_cache_log OnUpdateString
-
 PHP_INI_BEGIN()
-       HTTP_INI_ENTRY("http.allowed_methods", HTTP_KNOWN_METHODS, PHP_INI_ALL, allowed_methods)
-       HTTP_INI_ENTRY("http.cache_log", NULL, PHP_INI_ALL, cache_log)
+       HTTP_PHP_INI_ENTRY("http.allowed_methods", NULL, PHP_INI_ALL, http_update_allowed_methods, request.methods.allowed)
+       HTTP_PHP_INI_ENTRY("http.cache_log", NULL, PHP_INI_ALL, OnUpdateString, log.cache)
 PHP_INI_END()
 /* }}} */
 
-/* {{{ HTTP_CURL_USE_ZEND_MM */
-#if defined(HTTP_HAVE_CURL) && defined(HTTP_CURL_USE_ZEND_MM)
-static void http_curl_free(void *p)                                    { efree(p); }
-static char *http_curl_strdup(const char *p)           { return estrdup(p); }
-static void *http_curl_malloc(size_t s)                                { return emalloc(s); }
-static void *http_curl_realloc(void *p, size_t s)      { return erealloc(p, s); }
-static void *http_curl_calloc(size_t n, size_t s)      { return ecalloc(n, s); }
-#endif /* HTTP_HAVE_CURL && HTTP_CURL_USE_ZEND_MM */
-/* }}} */
 
 /* {{{ PHP_MINIT_FUNCTION */
 PHP_MINIT_FUNCTION(http)
 {
-       ZEND_INIT_MODULE_GLOBALS(http, http_globals_ctor, NULL);
+       ZEND_INIT_MODULE_GLOBALS(http, NULL, NULL);
        REGISTER_INI_ENTRIES();
 
 #ifdef HTTP_HAVE_CURL
@@ -260,13 +232,13 @@ PHP_MINIT_FUNCTION(http)
 #endif /* HTTP_HAVE_CURL */
 
 #ifdef ZEND_ENGINE_2
-       http_util_object_init(INIT_FUNC_ARGS_PASSTHRU);
-       http_message_object_init(INIT_FUNC_ARGS_PASSTHRU);
-       http_response_object_init(INIT_FUNC_ARGS_PASSTHRU);
+       http_util_object_init();
+       http_message_object_init();
+       http_response_object_init();
 #      ifdef HTTP_HAVE_CURL
-       http_request_object_init(INIT_FUNC_ARGS_PASSTHRU);
+       http_request_object_init();
 #      endif /* HTTP_HAVE_CURL */
-       http_exception_object_init(INIT_FUNC_ARGS_PASSTHRU);
+       http_exception_object_init();
 #endif /* ZEND_ENGINE_2 */
 
        return SUCCESS;
@@ -287,8 +259,13 @@ PHP_MSHUTDOWN_FUNCTION(http)
 /* {{{ PHP_RINIT_FUNCTION */
 PHP_RINIT_FUNCTION(http)
 {
-       char *allowed_methods = INI_STR("http.allowed_methods");
-       http_check_allowed_methods(allowed_methods, strlen(allowed_methods));
+       char *m;
+
+       if (m = INI_STR("http.allowed_methods")) {
+               http_check_allowed_methods(m, strlen(m));
+       }
+
+       http_globals_init(HTTP_GLOBALS);
        return SUCCESS;
 }
 /* }}} */
@@ -296,7 +273,7 @@ PHP_RINIT_FUNCTION(http)
 /* {{{ PHP_RSHUTDOWN_FUNCTION */
 PHP_RSHUTDOWN_FUNCTION(http)
 {
-       http_globals_dtor();
+       http_globals_free(HTTP_GLOBALS);
        return SUCCESS;
 }
 /* }}} */
@@ -322,19 +299,54 @@ PHP_MINFO_FUNCTION(http)
 #      define HTTP_CURL_AVAIL(CLASS) "libcurl not available"
 #endif
 
-       char full_version_string[1024] = {0};
-       snprintf(full_version_string, 1023, "%s (%s)", HTTP_PEXT_VERSION, HTTP_CURL_VERSION);
+#include "php_http_request_api.h"
 
        php_info_print_table_start();
-       php_info_print_table_row(2, "Extended HTTP support", "enabled");
-       php_info_print_table_row(2, "Extension Version:", full_version_string);
+       {
+               char full_version_string[1024] = {0};
+               snprintf(full_version_string, 1023, "%s (%s)", HTTP_PEXT_VERSION, HTTP_CURL_VERSION);
+
+               php_info_print_table_row(2, "Extended HTTP support:", "enabled");
+               php_info_print_table_row(2, "Extension Version:", full_version_string);
+       }
        php_info_print_table_end();
 
        php_info_print_table_start();
-       php_info_print_table_header(2, "Functionality",            "Availability");
-       php_info_print_table_row(2,    "Miscellaneous Utilities:", HTTP_FUNC_AVAIL("HttpUtil, HttpMessage"));
-       php_info_print_table_row(2,    "Extended HTTP Responses:", HTTP_FUNC_AVAIL("HttpResponse"));
-       php_info_print_table_row(2,    "Extended HTTP Requests:",  HTTP_CURL_AVAIL("HttpRequest"));
+       {
+               unsigned i;
+               zval **custom_method;
+               phpstr *known_request_methods = phpstr_new();
+               phpstr *custom_request_methods = phpstr_new();
+
+               for (i = HTTP_NO_REQUEST_METHOD+1; i < HTTP_MAX_REQUEST_METHOD; ++i) {
+                       phpstr_appendl(known_request_methods, http_request_method_name(i));
+                       phpstr_appends(known_request_methods, ", ");
+               }
+               FOREACH_HASH_VAL(&HTTP_G(request).methods.custom, custom_method) {
+                       phpstr_append(custom_request_methods, Z_STRVAL_PP(custom_method), Z_STRLEN_PP(custom_method));
+                       phpstr_appends(custom_request_methods, ", ");
+               }
+
+               phpstr_append(known_request_methods, PHPSTR_VAL(custom_request_methods), PHPSTR_LEN(custom_request_methods));
+               phpstr_fix(known_request_methods);
+               phpstr_fix(custom_request_methods);
+
+               php_info_print_table_row(2, "Known Request Methods:", PHPSTR_VAL(known_request_methods));
+               php_info_print_table_row(2, "Custom Request Methods:",
+                       PHPSTR_LEN(custom_request_methods) ? PHPSTR_VAL(custom_request_methods) : "none registered");
+
+               phpstr_free(known_request_methods);
+               phpstr_free(custom_request_methods);
+       }
+       php_info_print_table_end();
+
+       php_info_print_table_start();
+       {
+               php_info_print_table_header(2, "Functionality",            "Availability");
+               php_info_print_table_row(2,    "Miscellaneous Utilities:", HTTP_FUNC_AVAIL("HttpUtil, HttpMessage"));
+               php_info_print_table_row(2,    "Extended HTTP Responses:", HTTP_FUNC_AVAIL("HttpResponse"));
+               php_info_print_table_row(2,    "Extended HTTP Requests:",  HTTP_CURL_AVAIL("HttpRequest"));
+       }
        php_info_print_table_end();
 
        DISPLAY_INI_ENTRIES();
index fb43d99..079e451 100644 (file)
@@ -70,7 +70,7 @@ void _http_error_ex(long type, long code, const char *format, ...)
 #ifdef ZEND_ENGINE_2
                char *message;
                vspprintf(&message, 0, format, args);
-               zend_throw_exception(http_exception_get_default(), message, code TSRMLS_CC);
+               zend_throw_exception(http_exception_get_for_code(code), message, code TSRMLS_CC);
 #else
                type = E_WARNING;
 #endif
@@ -146,9 +146,9 @@ PHP_HTTP_API const char *_http_chunked_decode(const char *encoded, size_t encode
        while (((e_ptr - encoded) - encoded_len) > 0) {
                char *n_ptr;
                size_t chunk_len = 0;
-               
+
                chunk_len = strtol(e_ptr, &n_ptr, 16);
-               
+
                if (n_ptr == e_ptr) {
                        /* don't fail on apperently not encoded data */
                        if (e_ptr == encoded) {
index c75b6dc..a70feb0 100644 (file)
@@ -38,8 +38,8 @@ ZEND_EXTERN_MODULE_GLOBALS(http);
 /* {{{ STATUS http_cache_exit(char *, zend_bool) */
 STATUS _http_cache_exit_ex(char *cache_token, zend_bool etag, zend_bool free_token TSRMLS_DC)
 {
-       if (HTTP_G(cache_log) && strlen(HTTP_G(cache_log))) {
-               php_stream *log = php_stream_open_wrapper(HTTP_G(cache_log), "ab", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
+       if (HTTP_G(log).cache && strlen(HTTP_G(log).cache)) {
+               php_stream *log = php_stream_open_wrapper(HTTP_G(log).cache, "ab", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
 
                if (log) {
                        time_t now;
@@ -76,17 +76,15 @@ PHP_HTTP_API char *_http_etag(const void *data_ptr, size_t data_len, http_send_m
                break;
 
                case SEND_RSRC:
-                       if (!HTTP_G(ssb).sb.st_ino) {
-                               if (php_stream_stat((php_stream *) data_ptr, &HTTP_G(ssb))) {
-                                       return NULL;
-                               }
-                       }
-                       snprintf(ssb_buf, 127, "%ld=%ld=%ld",
-                               HTTP_G(ssb).sb.st_mtime,
-                               HTTP_G(ssb).sb.st_ino,
-                               HTTP_G(ssb).sb.st_size
-                       );
+               {
+                       php_stream_statbuf ssb;
+
+            if (php_stream_stat((php_stream *) data_ptr, &ssb)) {
+                return NULL;
+            }
+                       snprintf(ssb_buf, 127, "%ld=%ld=%ld", ssb.sb.st_mtime, ssb.sb.st_ino, ssb.sb.st_size);
                        PHP_MD5Update(&ctx, ssb_buf, strlen(ssb_buf));
+               }
                break;
 
                default:
@@ -105,24 +103,13 @@ PHP_HTTP_API char *_http_etag(const void *data_ptr, size_t data_len, http_send_m
 /* {{{ time_t http_last_modified(void *, http_send_mode) */
 PHP_HTTP_API time_t _http_last_modified(const void *data_ptr, http_send_mode data_mode TSRMLS_DC)
 {
+       php_stream_statbuf ssb;
+
        switch (data_mode)
        {
-               case SEND_DATA:
-               {
-                       return time(NULL);
-               }
-
-               case SEND_RSRC:
-               {
-                       php_stream_stat((php_stream *) data_ptr, &HTTP_G(ssb));
-                       return HTTP_G(ssb).sb.st_mtime;
-               }
-
-               default:
-               {
-                       php_stream_stat_path(Z_STRVAL_P((zval *) data_ptr), &HTTP_G(ssb));
-                       return HTTP_G(ssb).sb.st_mtime;
-               }
+               case SEND_DATA: return time(NULL);
+               case SEND_RSRC: return php_stream_stat((php_stream *) data_ptr, &ssb) ? 0 : ssb.sb.st_mtime;
+               default:                return php_stream_stat_path(Z_STRVAL_P((zval *) data_ptr), &ssb) ? 0 : ssb.sb.st_mtime;
        }
 }
 /* }}} */
@@ -211,16 +198,15 @@ PHP_HTTP_API STATUS _http_cache_etag(const char *etag, size_t etag_len,
        }
 
        /* if no etag is given and we didn't already start ob_etaghandler -- start it */
-       if (HTTP_G(etag_started)) {
+       if (HTTP_G(etag).started) {
                return SUCCESS;
        }
 
-       if (HTTP_G(etag_started) = (SUCCESS == php_start_ob_buffer_named("ob_etaghandler", HTTP_SENDBUF_SIZE, 1 TSRMLS_CC))) {
+       if (HTTP_G(etag).started = (SUCCESS == php_start_ob_buffer_named("ob_etaghandler", HTTP_SENDBUF_SIZE, 1 TSRMLS_CC))) {
                return SUCCESS;
        } else {
                return FAILURE;
        }
-
 }
 /* }}} */
 
@@ -232,17 +218,17 @@ PHP_HTTP_API void _http_ob_etaghandler(char *output, uint output_len,
        unsigned char digest[16];
 
        if (mode & PHP_OUTPUT_HANDLER_START) {
-               HTTP_G(etag_started) = 1;
-               PHP_MD5Init(&HTTP_G(etag_md5));
+               HTTP_G(etag).started = 1;
+               PHP_MD5Init(&HTTP_G(etag).md5ctx);
        }
 
-       PHP_MD5Update(&HTTP_G(etag_md5), output, output_len);
+       PHP_MD5Update(&HTTP_G(etag).md5ctx, output, output_len);
 
        if (mode & PHP_OUTPUT_HANDLER_END) {
-               PHP_MD5Final(digest, &HTTP_G(etag_md5));
+               PHP_MD5Final(digest, &HTTP_G(etag).md5ctx);
 
                /* just do that if desired */
-               if (HTTP_G(etag_started)) {
+               if (HTTP_G(etag).started) {
                        make_digest(etag, digest);
                        http_send_header("Cache-Control: " HTTP_DEFAULT_CACHECONTROL);
                        http_send_etag(etag, 32);
index 44c5c2a..7ea4af5 100644 (file)
 #include "zend_exceptions.h"
 
 zend_class_entry *http_exception_object_ce;
-zend_function_entry http_exception_object_fe[] = {
-       {NULL, NULL, NULL}
-};
+zend_function_entry http_exception_object_fe[] = {{NULL, NULL, NULL}};
 
 void _http_exception_object_init(INIT_FUNC_ARGS)
 {
        HTTP_REGISTER_CLASS(HttpException, http_exception_object, zend_exception_get_default(), 0);
+       
+       HTTP_LONG_CONSTANT("HTTP_E_UNKNOWN", HTTP_E_UNKOWN);
+       HTTP_LONG_CONSTANT("HTTP_E_PARSE", HTTP_E_PARSE);
+       HTTP_LONG_CONSTANT("HTTP_E_HEADER", HTTP_E_HEADER);
+       HTTP_LONG_CONSTANT("HTTP_E_OBUFFER", HTTP_E_OBUFFER);
+       HTTP_LONG_CONSTANT("HTTP_E_CURL", HTTP_E_CURL);
+       HTTP_LONG_CONSTANT("HTTP_E_ENCODE", HTTP_E_ENCODE);
+       HTTP_LONG_CONSTANT("HTTP_E_PARAM", HTTP_E_PARAM);
+       HTTP_LONG_CONSTANT("HTTP_E_URL", HTTP_E_URL);
+       HTTP_LONG_CONSTANT("HTTP_E_MSG", HTTP_E_MSG);
 }
 
 zend_class_entry *_http_exception_get_default()
@@ -45,6 +53,11 @@ zend_class_entry *_http_exception_get_default()
        return http_exception_object_ce;
 }
 
+zend_class_entry *_http_exception_get_for_code(long code)
+{
+       return http_exception_object_ce;
+}
+
 #endif
 
 /*
index afe6f85..4b611e0 100644 (file)
@@ -411,6 +411,35 @@ PHP_FUNCTION(ob_etaghandler)
 }
 /* }}} */
 
+/* {{{ proto void http_throttle(double sec[, long bytes = 2097152])
+ *
+ * Use with http_send() API.
+ *
+ * Example:
+ * <code>
+ * <?php
+ * // ~ 20 kbyte/s
+ * # http_throttle(1, 20000);
+ * # http_throttle(0.5, 10000);
+ * # http_throttle(0.1, 2000);
+ * http_send_file('document.pdf');
+ * ?>
+ * </code>
+ */
+PHP_FUNCTION(http_throttle)
+{
+       long chunk_size;
+       double interval;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dl", &interval, &chunk_size)) {
+               return;
+       }
+
+       HTTP_G(send).throttle_delay = interval;
+       HTTP_G(send).buffer_size = chunk_size;
+}
+/* }}} */
+
 /* {{{ proto void http_redirect([string url[, array params[, bool session,[ bool permanent]]]])
  *
  * Redirect to a given url.
@@ -893,25 +922,25 @@ PHP_FUNCTION(http_put_stream)
        php_stream *stream;
        php_stream_statbuf ssb;
        http_request_body body;
-       
+
        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sr|a/!z", &URL, &URL_len, &resource, &options, &info)) {
                RETURN_FALSE;
        }
-       
+
        php_stream_from_zval(stream, &resource);
        if (php_stream_stat(stream, &ssb)) {
                RETURN_FALSE;
        }
-       
+
        if (info) {
                zval_dtor(info);
                array_init(info);
        }
-       
+
        body.type = HTTP_REQUEST_BODY_UPLOADFILE;
        body.data = stream;
        body.size = ssb.sb.st_size;
-       
+
        phpstr_init_ex(&response, HTTP_CURLBUF_SIZE, 0);
        if (SUCCESS == http_put(URL, &body, options ? Z_ARRVAL_P(options) : NULL, info ? Z_ARRVAL_P(info) : NULL, &response)) {
                RETURN_PHPSTR_VAL(response);
@@ -921,6 +950,114 @@ PHP_FUNCTION(http_put_stream)
 }
 /* }}} */
 
+/* {{{ proto bool http_request()
+ */
+/* }}} */
+
+/* {{{ proto long http_request_method_register(string method)
+ *
+ */
+PHP_FUNCTION(http_request_method_register)
+{
+       char *method;
+       int *method_len;
+       unsigned long existing;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
+               RETURN_FALSE;
+       }
+       if (existing = http_request_method_exists(1, 0, method)) {
+               RETURN_LONG((long) existing);
+       }
+
+       RETVAL_LONG((long) http_request_method_register(method));
+}
+/* }}} */
+
+/* {{{ proto bool http_request_method_unregister(mixed method)
+ *
+ */
+PHP_FUNCTION(http_request_method_unregister)
+{
+       zval *method;
+       zend_bool numeric;
+       unsigned long existing;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) {
+               RETURN_FALSE;
+       }
+
+       switch (Z_TYPE_P(method))
+       {
+               case IS_OBJECT:
+                       convert_to_string(method);
+               case IS_STRING:
+#include "zend_operators.h"
+                       if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) {
+                               convert_to_long(method);
+                       } else {
+                               unsigned long mn;
+                               if (!(mn = http_request_method_exists(1, 0, Z_STRVAL_P(method)))) {
+                                       RETURN_FALSE;
+                               }
+                               zval_dtor(method);
+                               ZVAL_LONG(method, (long)mn);
+                       }
+               case IS_LONG:
+                       RETURN_SUCCESS(http_request_method_unregister(Z_LVAL_P(method)));
+               default:
+                       RETURN_FALSE;
+       }
+}
+/* }}} */
+
+/* {{{ proto long http_request_method_exists(mixed method)
+ *
+ */
+PHP_FUNCTION(http_request_method_exists)
+{
+       IF_RETVAL_USED {
+               zval *method;
+
+               if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) {
+                       RETURN_FALSE;
+               }
+
+               switch (Z_TYPE_P(method))
+               {
+                       case IS_OBJECT:
+                               convert_to_string(method);
+                       case IS_STRING:
+                               if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) {
+                                       convert_to_long(method);
+                               } else {
+                                       RETURN_LONG((long) http_request_method_exists(1, 0, Z_STRVAL_P(method)));
+                               }
+                       case IS_LONG:
+                               RETURN_LONG((long) http_request_method_exists(0, Z_LVAL_P(method), NULL));
+                       default:
+                               RETURN_FALSE;
+               }
+       }
+}
+/* }}} */
+
+/* {{{ proto string http_request_method_name(long method)
+ *
+ */
+PHP_FUNCTION(http_request_method_name)
+{
+       IF_RETVAL_USED {
+               long method;
+
+               if ((SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method)) || (method < 0)) {
+                       RETURN_FALSE;
+               }
+
+               RETURN_STRING(estrdup(http_request_method_name((unsigned long) method)), 0);
+       }
+}
+/* }}} */
 #endif
 /* }}} HAVE_CURL */
 
index a0f5e59..47cd1dd 100644 (file)
@@ -412,6 +412,21 @@ PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC)
        return rs;
 }
 
+PHP_HTTP_API http_message *_http_message_dup(http_message *msg TSRMLS_DC)
+{
+       /*
+        * TODO: unroll
+        */
+       http_message *new;
+       char *serialized_data;
+       size_t serialized_length;
+
+       http_message_serialize(msg, &serialized_data, &serialized_length);
+       new = http_message_parse(serialized_data, serialized_length);
+       efree(serialized_data);
+       return new;
+}
+
 PHP_HTTP_API void _http_message_dtor(http_message *message)
 {
        if (message) {
index f1a6705..e934f8b 100644 (file)
@@ -38,6 +38,8 @@ static zval *_http_message_object_read_prop(zval *object, zval *member, int type
 static void _http_message_object_write_prop(zval *object, zval *member, zval *value TSRMLS_DC);
 #define http_message_object_get_props _http_message_object_get_props
 static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC);
+#define http_message_object_clone_obj _http_message_object_clone_obj
+static inline zend_object_value _http_message_object_clone_obj(zval *object TSRMLS_DC);
 
 zend_class_entry *http_message_object_ce;
 zend_function_entry http_message_object_fe[] = {
@@ -75,6 +77,7 @@ void _http_message_object_init(INIT_FUNC_ARGS)
        HTTP_LONG_CONSTANT("HTTP_MSG_REQUEST", HTTP_MSG_REQUEST);
        HTTP_LONG_CONSTANT("HTTP_MSG_RESPONSE", HTTP_MSG_RESPONSE);
 
+       http_message_object_handlers.clone_obj = http_message_object_clone_obj;
        http_message_object_handlers.read_property = http_message_object_read_prop;
        http_message_object_handlers.write_property = http_message_object_write_prop;
        http_message_object_handlers.get_properties = http_message_object_get_props;
@@ -112,6 +115,11 @@ zend_object_value _http_message_object_new_ex(zend_class_entry *ce, http_message
        return ov;
 }
 
+zend_object_value _http_message_object_clone(zval *this_ptr TSRMLS_DC)
+{
+       return http_message_object_clone_obj(this_ptr TSRMLS_CC);
+}
+
 static inline void _http_message_object_declare_default_properties(TSRMLS_D)
 {
        zend_class_entry *ce = http_message_object_ce;
@@ -141,6 +149,12 @@ void _http_message_object_free(zend_object *object TSRMLS_DC)
        efree(o);
 }
 
+static inline zend_object_value _http_message_object_clone_obj(zval *this_ptr TSRMLS_DC)
+{
+       getObject(http_message_object, obj);
+       return http_message_object_from_msg(http_message_dup(obj->message));
+}
+
 static zval *_http_message_object_read_prop(zval *object, zval *member, int type TSRMLS_DC)
 {
        getObjectEx(http_message_object, obj, object);
index 4588718..4d7518a 100644 (file)
@@ -40,6 +40,8 @@
 
 #ifdef ZEND_ENGINE_2
 
+ZEND_EXTERN_MODULE_GLOBALS(http)
+
 /* {{{ HttpResponse */
 
 /* {{{ proto void HttpResponse::__construct(bool cache, bool gzip)
@@ -94,13 +96,15 @@ PHP_METHOD(HttpResponse, setCache)
  */
 PHP_METHOD(HttpResponse, getCache)
 {
-       zval *do_cache = NULL;
-       getObject(http_response_object, obj);
-
        NO_ARGS;
 
-       do_cache = GET_PROP(obj, cache);
-       RETURN_BOOL(Z_LVAL_P(do_cache));
+       IF_RETVAL_USED {
+               zval *do_cache = NULL;
+               getObject(http_response_object, obj);
+
+               do_cache = GET_PROP(obj, cache);
+               RETURN_BOOL(Z_LVAL_P(do_cache));
+       }
 }
 /* }}}*/
 
@@ -128,13 +132,15 @@ PHP_METHOD(HttpResponse, setGzip)
  */
 PHP_METHOD(HttpResponse, getGzip)
 {
-       zval *do_gzip = NULL;
-       getObject(http_response_object, obj);
-
        NO_ARGS;
 
-       do_gzip = GET_PROP(obj, gzip);
-       RETURN_BOOL(Z_LVAL_P(do_gzip));
+       IF_RETVAL_USED {
+               zval *do_gzip;
+               getObject(http_response_object, obj);
+
+               do_gzip = GET_PROP(obj, gzip);
+               RETURN_BOOL(Z_LVAL_P(do_gzip));
+       }
 }
 /* }}} */
 
@@ -171,13 +177,15 @@ PHP_METHOD(HttpResponse, setCacheControl)
  */
 PHP_METHOD(HttpResponse, getCacheControl)
 {
-       zval *ccontrol;
-       getObject(http_response_object, obj);
-
        NO_ARGS;
 
-       ccontrol = GET_PROP(obj, cacheControl);
-       RETURN_STRINGL(Z_STRVAL_P(ccontrol), Z_STRLEN_P(ccontrol), 1);
+       IF_RETVAL_USED {
+               zval *ccontrol;
+               getObject(http_response_object, obj);
+
+               ccontrol = GET_PROP(obj, cacheControl);
+               RETURN_STRINGL(Z_STRVAL_P(ccontrol), Z_STRLEN_P(ccontrol), 1);
+       }
 }
 /* }}} */
 
@@ -212,13 +220,15 @@ PHP_METHOD(HttpResponse, setContentType)
  */
 PHP_METHOD(HttpResponse, getContentType)
 {
-       zval *ctype;
-       getObject(http_response_object, obj);
-
        NO_ARGS;
 
-       ctype = GET_PROP(obj, contentType);
-       RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
+       IF_RETVAL_USED {
+               zval *ctype;
+               getObject(http_response_object, obj);
+
+               ctype = GET_PROP(obj, contentType);
+               RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
+       }
 }
 /* }}} */
 
@@ -258,20 +268,19 @@ PHP_METHOD(HttpResponse, setContentDisposition)
  */
 PHP_METHOD(HttpResponse, getContentDisposition)
 {
-       zval *file;
-       zval *is_inline;
-       getObject(http_response_object, obj);
+       NO_ARGS;
 
-       if (ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
-       }
+       IF_RETVAL_USED {
+               zval *file, *is_inline;
+               getObject(http_response_object, obj);
 
-       file = GET_PROP(obj, dispoFile);
-       is_inline = GET_PROP(obj, dispoInline);
+               file = GET_PROP(obj, dispoFile);
+               is_inline = GET_PROP(obj, dispoInline);
 
-       array_init(return_value);
-       add_assoc_stringl(return_value, "filename", Z_STRVAL_P(file), Z_STRLEN_P(file), 1);
-       add_assoc_bool(return_value, "inline", Z_LVAL_P(is_inline));
+               array_init(return_value);
+               add_assoc_stringl(return_value, "filename", Z_STRVAL_P(file), Z_STRLEN_P(file), 1);
+               add_assoc_bool(return_value, "inline", Z_LVAL_P(is_inline));
+       }
 }
 /* }}} */
 
@@ -300,13 +309,79 @@ PHP_METHOD(HttpResponse, setETag)
  */
 PHP_METHOD(HttpResponse, getETag)
 {
-       zval *etag;
-       getObject(http_response_object, obj);
+       NO_ARGS;
+
+       IF_RETVAL_USED {
+               zval *etag;
+               getObject(http_response_object, obj);
+
+               etag = GET_PROP(obj, eTag);
+               RETURN_STRINGL(Z_STRVAL_P(etag), Z_STRLEN_P(etag), 1);
+       }
+}
+/* }}} */
+
+/* {{{ proto void HttpResponse::setThrottleDelay(double seconds)
+ *
+ */
+PHP_METHOD(HttpResponse, setThrottleDelay)
+{
+       double seconds;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &seconds)) {
+               getObject(http_response_object, obj);
+
+               UPD_PROP(obj, double, throttleDelay, seconds);
+       }
+}
+/* }}} */
+
+/* {{{ proto double HttpResponse::getThrottleDelay()
+ *
+ */
+PHP_METHOD(HttpResponse, getThrottleDelay)
+{
+       NO_ARGS;
+
+       IF_RETVAL_USED {
+               zval *seconds;
+               getObject(http_response_object, obj);
+
+               seconds = GET_PROP(obj, throttleDelay);
+               RETURN_DOUBLE(Z_DVAL_P(seconds));
+       }
+}
+/* }}} */
+
+/* {{{ proto void HttpResponse::setSendBuffersize(long bytes)
+ *
+ */
+PHP_METHOD(HttpResponse, setSendBuffersize)
+{
+       long bytes;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bytes)) {
+               getObject(http_response_object, obj);
 
+               UPD_PROP(obj, long, sendBuffersize, bytes);
+       }
+}
+/* }}} */
+
+/* {{{ proto long HttpResponse::getSendBuffersize()
+ *
+ */
+PHP_METHOD(HttpResponse, getSendBuffersize)
+{
        NO_ARGS;
 
-       etag = GET_PROP(obj, eTag);
-       RETURN_STRINGL(Z_STRVAL_P(etag), Z_STRLEN_P(etag), 1);
+       IF_RETVAL_USED {
+               zval *bytes;
+               getObject(http_response_object, obj);
+
+               bytes = GET_PROP(obj, sendBuffersize);
+               RETURN_LONG(Z_LVAL_P(bytes));
+       }
 }
 /* }}} */
 
@@ -337,13 +412,15 @@ PHP_METHOD(HttpResponse, setData)
  */
 PHP_METHOD(HttpResponse, getData)
 {
-       zval *the_data;
-       getObject(http_response_object, obj);
-
        NO_ARGS;
 
-       the_data = GET_PROP(obj, data);
-       RETURN_STRINGL(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), 1);
+       IF_RETVAL_USED {
+               zval *the_data;
+               getObject(http_response_object, obj);
+
+               the_data = GET_PROP(obj, data);
+               RETURN_STRINGL(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), 1);
+       }
 }
 /* }}} */
 
@@ -376,13 +453,15 @@ PHP_METHOD(HttpResponse, setStream)
  */
 PHP_METHOD(HttpResponse, getStream)
 {
-       zval *the_stream;
-       getObject(http_response_object, obj);
-
        NO_ARGS;
 
-       the_stream = GET_PROP(obj, stream);
-       RETURN_RESOURCE(Z_LVAL_P(the_stream));
+       IF_RETVAL_USED {
+               zval *the_stream;
+               getObject(http_response_object, obj);
+
+               the_stream = GET_PROP(obj, stream);
+               RETURN_RESOURCE(Z_LVAL_P(the_stream));
+       }
 }
 /* }}} */
 
@@ -414,13 +493,15 @@ PHP_METHOD(HttpResponse, setFile)
  */
 PHP_METHOD(HttpResponse, getFile)
 {
-       zval *the_file;
-       getObject(http_response_object, obj);
-
        NO_ARGS;
 
-       the_file = GET_PROP(obj, file);
-       RETURN_STRINGL(Z_STRVAL_P(the_file), Z_STRLEN_P(the_file), 1);
+       IF_RETVAL_USED {
+               zval *the_file;
+               getObject(http_response_object, obj);
+
+               the_file = GET_PROP(obj, file);
+               RETURN_STRINGL(Z_STRVAL_P(the_file), Z_STRLEN_P(the_file), 1);
+       }
 }
 /* }}} */
 
@@ -456,6 +537,8 @@ PHP_METHOD(HttpResponse, send)
 
        /* caching */
        if (Z_LVAL_P(do_cache)) {
+               char *cc_hdr;
+               int cc_len;
                zval *cctrl, *etag, *lmod, *ccraw;
 
                etag  = GET_PROP(obj, eTag);
@@ -464,14 +547,17 @@ PHP_METHOD(HttpResponse, send)
                ccraw = GET_PROP(obj, raw_cache_header);
 
                if (Z_LVAL_P(ccraw)) {
-                       http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), Z_STRVAL_P(cctrl), Z_STRLEN_P(cctrl));
-                       http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), Z_STRVAL_P(cctrl), Z_STRLEN_P(cctrl));
+                       cc_hdr = Z_STRVAL_P(cctrl);
+                       cc_len = Z_STRLEN_P(cctrl);
                } else {
                        char cc_header[42] = {0};
                        sprintf(cc_header, "%s, must-revalidate, max-age=0", Z_STRVAL_P(cctrl));
-                       http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), cc_header, strlen(cc_header));
-                       http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), cc_header, strlen(cc_header));
+                       cc_hdr = cc_header;
+                       cc_len = Z_STRLEN_P(cctrl) + lenof(", must-revalidate, max-age=0");
                }
+
+               http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), cc_hdr, cc_len);
+               http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), cc_hdr, cc_len);
        }
 
        /* content type */
@@ -480,7 +566,7 @@ PHP_METHOD(HttpResponse, send)
                if (Z_STRLEN_P(ctype)) {
                        http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
                } else {
-                       http_send_content_type("application/x-octetstream", sizeof("application/x-octetstream") - 1);
+                       http_send_content_type("application/x-octetstream", lenof("application/x-octetstream"));
                }
        }
 
@@ -493,6 +579,15 @@ PHP_METHOD(HttpResponse, send)
                }
        }
 
+       /* throttling */
+       {
+               zval *send_buffersize, *throttle_delay;
+               send_buffersize = GET_PROP(obj, sendBuffersize);
+               throttle_delay  = GET_PROP(obj, throttleDelay);
+               HTTP_G(send).buffer_size    = Z_LVAL_P(send_buffersize);
+               HTTP_G(send).throttle_delay = Z_DVAL_P(throttle_delay);
+       }
+
        /* send */
        {
                zval *send_mode = GET_PROP(obj, send_mode);
@@ -579,12 +674,12 @@ PHP_METHOD(HttpMessage, __construct)
  */
 PHP_METHOD(HttpMessage, getBody)
 {
-       zval *body;
-       getObject(http_message_object, obj);
-
        NO_ARGS;
 
-       RETURN_PHPSTR(&obj->message->body, PHPSTR_FREE_NOT, 1);
+       IF_RETVAL_USED {
+               getObject(http_message_object, obj);
+               RETURN_PHPSTR(&obj->message->body, PHPSTR_FREE_NOT, 1);
+       }
 }
 /* }}} */
 
@@ -594,14 +689,16 @@ PHP_METHOD(HttpMessage, getBody)
  */
 PHP_METHOD(HttpMessage, getHeaders)
 {
-       zval headers;
-       getObject(http_message_object, obj);
-
        NO_ARGS;
 
-       Z_ARRVAL(headers) = &obj->message->hdrs;
-       array_init(return_value);
-       array_copy(&headers, return_value);
+       IF_RETVAL_USED {
+               zval headers;
+               getObject(http_message_object, obj);
+
+               Z_ARRVAL(headers) = &obj->message->hdrs;
+               array_init(return_value);
+               array_copy(&headers, return_value);
+       }
 }
 /* }}} */
 
@@ -653,11 +750,12 @@ PHP_METHOD(HttpMessage, addHeaders)
  */
 PHP_METHOD(HttpMessage, getType)
 {
-       getObject(http_message_object, obj);
-
        NO_ARGS;
 
-       RETURN_LONG(obj->message->type);
+       IF_RETVAL_USED {
+               getObject(http_message_object, obj);
+               RETURN_LONG(obj->message->type);
+       }
 }
 /* }}} */
 
@@ -683,16 +781,18 @@ PHP_METHOD(HttpMessage, setType)
  */
 PHP_METHOD(HttpMessage, getResponseCode)
 {
-       getObject(http_message_object, obj);
-
        NO_ARGS;
 
-       if (!HTTP_MSG_TYPE(RESPONSE, obj->message)) {
-               http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_RESPONSE");
-               RETURN_NULL();
-       }
+       IF_RETVAL_USED {
+               getObject(http_message_object, obj);
+
+               if (!HTTP_MSG_TYPE(RESPONSE, obj->message)) {
+                       http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_RESPONSE");
+                       RETURN_NULL();
+               }
 
-       RETURN_LONG(obj->message->info.response.code);
+               RETURN_LONG(obj->message->info.response.code);
+       }
 }
 /* }}} */
 
@@ -707,7 +807,7 @@ PHP_METHOD(HttpMessage, setResponseCode)
        long code;
        getObject(http_message_object, obj);
 
-       if (obj->message->type != HTTP_MSG_RESPONSE) {
+       if (!HTTP_MSG_TYPE(RESPONSE, obj->message)) {
                http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_RESPONSE");
                RETURN_FALSE;
        }
@@ -732,16 +832,18 @@ PHP_METHOD(HttpMessage, setResponseCode)
  */
 PHP_METHOD(HttpMessage, getRequestMethod)
 {
-       getObject(http_message_object, obj);
-
        NO_ARGS;
 
-       if (obj->message->type != HTTP_MSG_REQUEST) {
-               http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
-               RETURN_NULL();
-       }
+       IF_RETVAL_USED {
+               getObject(http_message_object, obj);
 
-       RETURN_STRING(obj->message->info.request.method, 1);
+               if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
+                       http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
+                       RETURN_NULL();
+               }
+
+               RETURN_STRING(obj->message->info.request.method, 1);
+       }
 }
 /* }}} */
 
@@ -756,7 +858,7 @@ PHP_METHOD(HttpMessage, setRequestMethod)
        int method_len;
        getObject(http_message_object, obj);
 
-       if (obj->message->type != HTTP_MSG_REQUEST) {
+       if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
                http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
                RETURN_FALSE;
        }
@@ -773,10 +875,7 @@ PHP_METHOD(HttpMessage, setRequestMethod)
                RETURN_FALSE;
        }
 
-       if (obj->message->info.request.method) {
-               efree(obj->message->info.request.method);
-       }
-       obj->message->info.request.method = estrndup(method, method_len);
+       STR_SET(obj->message->info.request.method, estrndup(method, method_len));
        RETURN_TRUE;
 }
 /* }}} */
@@ -787,17 +886,19 @@ PHP_METHOD(HttpMessage, setRequestMethod)
  */
 PHP_METHOD(HttpMessage, getRequestUri)
 {
-       zval *uri;
-       getObject(http_message_object, obj);
-
        NO_ARGS;
 
-       if (obj->message->type != HTTP_MSG_REQUEST) {
-               http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
-               RETURN_NULL();
-       }
+       IF_RETVAL_USED {
+               zval *uri;
+               getObject(http_message_object, obj);
 
-       RETURN_STRING(obj->message->info.request.URI, 1);
+               if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
+                       http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
+                       RETURN_NULL();
+               }
+
+               RETURN_STRING(obj->message->info.request.URI, 1);
+       }
 }
 /* }}} */
 
@@ -813,7 +914,7 @@ PHP_METHOD(HttpMessage, setRequestUri)
        int URIlen;
        getObject(http_message_object, obj);
 
-       if (obj->message->type != HTTP_MSG_REQUEST) {
+       if (!HTTP_MSG_TYPE(REQUEST, obj->message)) {
                http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
                RETURN_FALSE;
        }
@@ -825,10 +926,7 @@ PHP_METHOD(HttpMessage, setRequestUri)
                RETURN_FALSE;
        }
 
-       if (obj->message->info.request.URI) {
-               efree(obj->message->info.request.URI);
-       }
-       obj->message->info.request.URI = estrndup(URI, URIlen);
+       STR_SET(obj->message->info.request.URI, estrndup(URI, URIlen));
        RETURN_TRUE;
 }
 /* }}} */
@@ -839,28 +937,30 @@ PHP_METHOD(HttpMessage, setRequestUri)
  */
 PHP_METHOD(HttpMessage, getHttpVersion)
 {
-       char ver[4] = {0};
-       float version;
-       getObject(http_message_object, obj);
-
        NO_ARGS;
 
-       switch (obj->message->type)
-       {
-               case HTTP_MSG_RESPONSE:
-                       version = obj->message->info.response.http_version;
-               break;
+       IF_RETVAL_USED {
+               char ver[4] = {0};
+               float version;
+               getObject(http_message_object, obj);
 
-               case HTTP_MSG_REQUEST:
-                       version = obj->message->info.request.http_version;
-               break;
+               switch (obj->message->type)
+               {
+                       case HTTP_MSG_RESPONSE:
+                               version = obj->message->info.response.http_version;
+                       break;
 
-               case HTTP_MSG_NONE:
-               default:
-                       RETURN_NULL();
+                       case HTTP_MSG_REQUEST:
+                               version = obj->message->info.request.http_version;
+                       break;
+
+                       case HTTP_MSG_NONE:
+                       default:
+                               RETURN_NULL();
+               }
+               sprintf(ver, "%1.1f", version);
+               RETURN_STRINGL(ver, 3, 1);
        }
-       sprintf(ver, "%1.1f", version);
-       RETURN_STRINGL(ver, 3, 1);
 }
 /* }}} */
 
@@ -879,19 +979,19 @@ PHP_METHOD(HttpMessage, setHttpVersion)
                return;
        }
 
-       if (obj->message->type == HTTP_MSG_NONE) {
+       if (HTTP_MSG_TYPE(NONE, obj->message)) {
                http_error(E_WARNING, HTTP_E_MSG, "Message is neither of type HTTP_MSG_RESPONSE nor HTTP_MSG_REQUEST");
                RETURN_FALSE;
        }
 
-       convert_to_double_ex(&zv);
+       convert_to_double(zv);
        sprintf(v, "%1.1f", Z_DVAL_P(zv));
        if (strcmp(v, "1.0") && strcmp(v, "1.1")) {
                http_error_ex(E_WARNING, HTTP_E_PARAM, "Invalid HTTP protocol version (1.0 or 1.1): %s", v);
                RETURN_FALSE;
        }
 
-       if (obj->message->type == HTTP_MSG_RESPONSE) {
+       if (HTTP_MSG_TYPE(RESPONSE, obj->message)) {
                obj->message->info.response.http_version = (float) Z_DVAL_P(zv);
        } else {
                obj->message->info.request.http_version = (float) Z_DVAL_P(zv);
@@ -906,14 +1006,16 @@ PHP_METHOD(HttpMessage, setHttpVersion)
  */
 PHP_METHOD(HttpMessage, getParentMessage)
 {
-       getObject(http_message_object, obj);
-
        NO_ARGS;
 
-       if (obj->message->parent) {
-               RETVAL_OBJVAL(obj->parent);
-       } else {
-               RETVAL_NULL();
+       IF_RETVAL_USED {
+               getObject(http_message_object, obj);
+
+               if (obj->message->parent) {
+                       RETVAL_OBJVAL(obj->parent);
+               } else {
+                       RETVAL_NULL();
+               }
        }
 }
 /* }}} */
@@ -938,21 +1040,23 @@ PHP_METHOD(HttpMessage, send)
  */
 PHP_METHOD(HttpMessage, toString)
 {
-       char *string;
-       size_t length;
-       zend_bool include_parent = 1;
-       getObject(http_message_object, obj);
+       IF_RETVAL_USED {
+               char *string;
+               size_t length;
+               zend_bool include_parent = 1;
+               getObject(http_message_object, obj);
 
-       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &include_parent)) {
-               RETURN_FALSE;
-       }
+               if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &include_parent)) {
+                       RETURN_FALSE;
+               }
 
-       if (include_parent) {
-               http_message_serialize(obj->message, &string, &length);
-       } else {
-               http_message_tostring(obj->message, &string, &length);
+               if (include_parent) {
+                       http_message_serialize(obj->message, &string, &length);
+               } else {
+                       http_message_tostring(obj->message, &string, &length);
+               }
+               RETURN_STRINGL(string, length, 0);
        }
-       RETURN_STRINGL(string, length, 0);
 }
 /* }}} */
 
@@ -1061,14 +1165,16 @@ PHP_METHOD(HttpRequest, setOptions)
  */
 PHP_METHOD(HttpRequest, getOptions)
 {
-       zval *opts;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       opts = GET_PROP(obj, options);
-       array_init(return_value);
-       array_copy(opts, return_value);
+       IF_RETVAL_USED {
+               zval *opts;
+               getObject(http_request_object, obj);
+
+               opts = GET_PROP(obj, options);
+               array_init(return_value);
+               array_copy(opts, return_value);
+       }
 }
 /* }}} */
 
@@ -1119,17 +1225,19 @@ PHP_METHOD(HttpRequest, setSslOptions)
  */
 PHP_METHOD(HttpRequest, getSslOptions)
 {
-       zval *opts, **ssl_options;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       opts = GET_PROP(obj, options);
+       IF_RETVAL_USED {
+               zval *opts, **ssl_options;
+               getObject(http_request_object, obj);
 
-       array_init(return_value);
+               opts = GET_PROP(obj, options);
 
-       if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "ssl", sizeof("ssl"), (void **) &ssl_options)) {
-               array_copy(*ssl_options, return_value);
+               array_init(return_value);
+
+               if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "ssl", sizeof("ssl"), (void **) &ssl_options)) {
+                       array_copy(*ssl_options, return_value);
+               }
        }
 }
 /* }}} */
@@ -1182,17 +1290,19 @@ PHP_METHOD(HttpRequest, addHeaders)
  */
 PHP_METHOD(HttpRequest, getHeaders)
 {
-       zval *opts, **headers;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       opts = GET_PROP(obj, options);
+       IF_RETVAL_USED {
+               zval *opts, **headers;
+               getObject(http_request_object, obj);
 
-       array_init(return_value);
+               opts = GET_PROP(obj, options);
 
-       if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "headers", sizeof("headers"), (void **) &headers)) {
-               array_copy(*headers, return_value);
+               array_init(return_value);
+
+               if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "headers", sizeof("headers"), (void **) &headers)) {
+                       array_copy(*headers, return_value);
+               }
        }
 }
 /* }}} */
@@ -1245,17 +1355,19 @@ PHP_METHOD(HttpRequest, addCookies)
  */
 PHP_METHOD(HttpRequest, getCookies)
 {
-       zval *opts, **cookies;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       opts = GET_PROP(obj, options);
+       IF_RETVAL_USED {
+               zval *opts, **cookies;
+               getObject(http_request_object, obj);
 
-       array_init(return_value);
+               opts = GET_PROP(obj, options);
 
-       if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
-               array_copy(*cookies, return_value);
+               array_init(return_value);
+
+               if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
+                       array_copy(*cookies, return_value);
+               }
        }
 }
 /* }}} */
@@ -1300,13 +1412,15 @@ PHP_METHOD(HttpRequest, setURL)
  */
 PHP_METHOD(HttpRequest, getURL)
 {
-       zval *URL;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       URL = GET_PROP(obj, url);
-       RETURN_STRINGL(Z_STRVAL_P(URL), Z_STRLEN_P(URL), 1);
+       IF_RETVAL_USED {
+               zval *URL;
+               getObject(http_request_object, obj);
+
+               URL = GET_PROP(obj, url);
+               RETURN_STRINGL(Z_STRVAL_P(URL), Z_STRLEN_P(URL), 1);
+       }
 }
 /* }}} */
 
@@ -1335,13 +1449,15 @@ PHP_METHOD(HttpRequest, setMethod)
  */
 PHP_METHOD(HttpRequest, getMethod)
 {
-       zval *meth;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       meth = GET_PROP(obj, method);
-       RETURN_LONG(Z_LVAL_P(meth));
+       IF_RETVAL_USED {
+               zval *meth;
+               getObject(http_request_object, obj);
+
+               meth = GET_PROP(obj, method);
+               RETURN_LONG(Z_LVAL_P(meth));
+       }
 }
 /* }}} */
 
@@ -1376,13 +1492,15 @@ PHP_METHOD(HttpRequest, setContentType)
  */
 PHP_METHOD(HttpRequest, getContentType)
 {
-       zval *ctype;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       ctype = GET_PROP(obj, contentType);
-       RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
+       IF_RETVAL_USED {
+               zval *ctype;
+               getObject(http_request_object, obj);
+
+               ctype = GET_PROP(obj, contentType);
+               RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
+       }
 }
 /* }}} */
 
@@ -1423,13 +1541,15 @@ PHP_METHOD(HttpRequest, setQueryData)
  */
 PHP_METHOD(HttpRequest, getQueryData)
 {
-       zval *qdata;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       qdata = GET_PROP(obj, queryData);
-       RETURN_STRINGL(Z_STRVAL_P(qdata), Z_STRLEN_P(qdata), 1);
+       IF_RETVAL_USED {
+               zval *qdata;
+               getObject(http_request_object, obj);
+
+               qdata = GET_PROP(obj, queryData);
+               RETURN_STRINGL(Z_STRVAL_P(qdata), Z_STRLEN_P(qdata), 1);
+       }
 }
 /* }}} */
 
@@ -1526,14 +1646,16 @@ PHP_METHOD(HttpRequest, setPostFields)
  */
 PHP_METHOD(HttpRequest, getPostFields)
 {
-       zval *post_data;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       post_data = GET_PROP(obj, postFields);
-       array_init(return_value);
-       array_copy(post_data, return_value);
+       IF_RETVAL_USED {
+               zval *post_data;
+               getObject(http_request_object, obj);
+
+               post_data = GET_PROP(obj, postFields);
+               array_init(return_value);
+               array_copy(post_data, return_value);
+       }
 }
 /* }}} */
 
@@ -1600,15 +1722,17 @@ PHP_METHOD(HttpRequest, addPostFile)
  */
 PHP_METHOD(HttpRequest, getPostFiles)
 {
-       zval *files;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       files = GET_PROP(obj, postFiles);
+       IF_RETVAL_USED {
+               zval *files;
+               getObject(http_request_object, obj);
+
+               files = GET_PROP(obj, postFiles);
 
-       array_init(return_value);
-       array_copy(files, return_value);
+               array_init(return_value);
+               array_copy(files, return_value);
+       }
 }
 /* }}} */
 
@@ -1635,14 +1759,16 @@ PHP_METHOD(HttpRequest, unsetPostFiles)
  */
 PHP_METHOD(HttpRequest, getResponseData)
 {
-       zval *data;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       data = GET_PROP(obj, responseData);
-       array_init(return_value);
-       array_copy(data, return_value);
+       IF_RETVAL_USED {
+               zval *data;
+               getObject(http_request_object, obj);
+
+               data = GET_PROP(obj, responseData);
+               array_init(return_value);
+               array_copy(data, return_value);
+       }
 }
 /* }}} */
 
@@ -1652,27 +1778,29 @@ PHP_METHOD(HttpRequest, getResponseData)
  */
 PHP_METHOD(HttpRequest, getResponseHeader)
 {
-       zval *data, **headers, **header;
-       char *header_name = NULL;
-       int header_len = 0;
-       getObject(http_response_object, obj);
+       IF_RETVAL_USED {
+               zval *data, **headers, **header;
+               char *header_name = NULL;
+               int header_len = 0;
+               getObject(http_response_object, obj);
 
-       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &header_name, &header_len)) {
-               RETURN_FALSE;
-       }
+               if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &header_name, &header_len)) {
+                       RETURN_FALSE;
+               }
 
-       data = GET_PROP(obj, responseData);
-       if (SUCCESS != zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
-               RETURN_FALSE;
-       }
+               data = GET_PROP(obj, responseData);
+               if (SUCCESS != zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
+                       RETURN_FALSE;
+               }
 
-       if (!header_len || !header_name) {
-               array_init(return_value);
-               array_copy(*headers, return_value);
-       } else if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(headers), pretty_key(header_name, header_len, 1, 1), header_len + 1, (void **) &header)) {
-               RETURN_STRINGL(Z_STRVAL_PP(header), Z_STRLEN_PP(header), 1);
-       } else {
-               RETURN_FALSE;
+               if (!header_len || !header_name) {
+                       array_init(return_value);
+                       array_copy(*headers, return_value);
+               } else if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(headers), pretty_key(header_name, header_len, 1, 1), header_len + 1, (void **) &header)) {
+                       RETURN_STRINGL(Z_STRVAL_PP(header), Z_STRLEN_PP(header), 1);
+               } else {
+                       RETURN_FALSE;
+               }
        }
 }
 /* }}} */
@@ -1683,35 +1811,61 @@ PHP_METHOD(HttpRequest, getResponseHeader)
  */
 PHP_METHOD(HttpRequest, getResponseCookie)
 {
-       zval *data, **headers;
-       char *cookie_name = NULL;
-       int cookie_len = 0;
-       getObject(http_request_object, obj);
+       IF_RETVAL_USED {
+               zval *data, **headers;
+               char *cookie_name = NULL;
+               int cookie_len = 0;
+               getObject(http_request_object, obj);
 
-       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cookie_name, &cookie_len)) {
-               RETURN_FALSE;
-       }
-
-       array_init(return_value);
-
-       data = GET_PROP(obj, responseData);
-       if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
-               ulong idx = 0;
-               char *key = NULL;
-               zval **header = NULL;
+               if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cookie_name, &cookie_len)) {
+                       RETURN_FALSE;
+               }
 
-               FOREACH_HASH_KEYVAL(Z_ARRVAL_PP(headers), key, idx, header) {
-                       if (key && !strcasecmp(key, "Set-Cookie")) {
-                               /* several cookies? */
-                               if (Z_TYPE_PP(header) == IS_ARRAY) {
-                                       zval **cookie;
+               array_init(return_value);
 
-                                       FOREACH_HASH_VAL(Z_ARRVAL_PP(header), cookie) {
+               data = GET_PROP(obj, responseData);
+               if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
+                       ulong idx = 0;
+                       char *key = NULL;
+                       zval **header = NULL;
+
+                       FOREACH_HASH_KEYVAL(Z_ARRVAL_PP(headers), key, idx, header) {
+                               if (key && !strcasecmp(key, "Set-Cookie")) {
+                                       /* several cookies? */
+                                       if (Z_TYPE_PP(header) == IS_ARRAY) {
+                                               zval **cookie;
+
+                                               FOREACH_HASH_VAL(Z_ARRVAL_PP(header), cookie) {
+                                                       zval *cookie_hash;
+                                                       MAKE_STD_ZVAL(cookie_hash);
+                                                       array_init(cookie_hash);
+
+                                                       if (SUCCESS == http_parse_cookie(Z_STRVAL_PP(cookie), Z_ARRVAL_P(cookie_hash))) {
+                                                               if (!cookie_len) {
+                                                                       add_next_index_zval(return_value, cookie_hash);
+                                                               } else {
+                                                                       zval **name;
+
+                                                                       if (    (SUCCESS == zend_hash_find(Z_ARRVAL_P(cookie_hash), "name", sizeof("name"), (void **) &name)) &&
+                                                                                       (!strcmp(Z_STRVAL_PP(name), cookie_name))) {
+                                                                               add_next_index_zval(return_value, cookie_hash);
+                                                                               return; /* <<< FOUND >>> */
+                                                                       } else {
+                                                                               zval_dtor(cookie_hash);
+                                                                               efree(cookie_hash);
+                                                                       }
+                                                               }
+                                                       } else {
+                                                               zval_dtor(cookie_hash);
+                                                               efree(cookie_hash);
+                                                       }
+                                               }
+                                       } else {
                                                zval *cookie_hash;
                                                MAKE_STD_ZVAL(cookie_hash);
                                                array_init(cookie_hash);
 
-                                               if (SUCCESS == http_parse_cookie(Z_STRVAL_PP(cookie), Z_ARRVAL_P(cookie_hash))) {
+                                               if (SUCCESS == http_parse_cookie(Z_STRVAL_PP(header), Z_ARRVAL_P(cookie_hash))) {
                                                        if (!cookie_len) {
                                                                add_next_index_zval(return_value, cookie_hash);
                                                        } else {
@@ -1720,7 +1874,6 @@ PHP_METHOD(HttpRequest, getResponseCookie)
                                                                if (    (SUCCESS == zend_hash_find(Z_ARRVAL_P(cookie_hash), "name", sizeof("name"), (void **) &name)) &&
                                                                                (!strcmp(Z_STRVAL_PP(name), cookie_name))) {
                                                                        add_next_index_zval(return_value, cookie_hash);
-                                                                       return; /* <<< FOUND >>> */
                                                                } else {
                                                                        zval_dtor(cookie_hash);
                                                                        efree(cookie_hash);
@@ -1731,34 +1884,11 @@ PHP_METHOD(HttpRequest, getResponseCookie)
                                                        efree(cookie_hash);
                                                }
                                        }
-                               } else {
-                                       zval *cookie_hash;
-                                       MAKE_STD_ZVAL(cookie_hash);
-                                       array_init(cookie_hash);
-
-                                       if (SUCCESS == http_parse_cookie(Z_STRVAL_PP(header), Z_ARRVAL_P(cookie_hash))) {
-                                               if (!cookie_len) {
-                                                       add_next_index_zval(return_value, cookie_hash);
-                                               } else {
-                                                       zval **name;
-
-                                                       if (    (SUCCESS == zend_hash_find(Z_ARRVAL_P(cookie_hash), "name", sizeof("name"), (void **) &name)) &&
-                                                                       (!strcmp(Z_STRVAL_PP(name), cookie_name))) {
-                                                               add_next_index_zval(return_value, cookie_hash);
-                                                       } else {
-                                                               zval_dtor(cookie_hash);
-                                                               efree(cookie_hash);
-                                                       }
-                                               }
-                                       } else {
-                                               zval_dtor(cookie_hash);
-                                               efree(cookie_hash);
-                                       }
+                                       break;
                                }
-                               break;
+                               /* reset key */
+                               key = NULL;
                        }
-                       /* reset key */
-                       key = NULL;
                }
        }
 }
@@ -1770,16 +1900,18 @@ PHP_METHOD(HttpRequest, getResponseCookie)
  */
 PHP_METHOD(HttpRequest, getResponseBody)
 {
-       zval *data, **body;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       data = GET_PROP(obj, responseData);
-       if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body)) {
-               RETURN_STRINGL(Z_STRVAL_PP(body), Z_STRLEN_PP(body), 1);
-       } else {
-               RETURN_FALSE;
+       IF_RETVAL_USED {
+               zval *data, **body;
+               getObject(http_request_object, obj);
+
+               data = GET_PROP(obj, responseData);
+               if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body)) {
+                       RETURN_STRINGL(Z_STRVAL_PP(body), Z_STRLEN_PP(body), 1);
+               } else {
+                       RETURN_FALSE;
+               }
        }
 }
 /* }}} */
@@ -1790,13 +1922,15 @@ PHP_METHOD(HttpRequest, getResponseBody)
  */
 PHP_METHOD(HttpRequest, getResponseCode)
 {
-       zval *code;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       code = GET_PROP(obj, responseCode);
-       RETURN_LONG(Z_LVAL_P(code));
+       IF_RETVAL_USED {
+               zval *code;
+               getObject(http_request_object, obj);
+
+               code = GET_PROP(obj, responseCode);
+               RETURN_LONG(Z_LVAL_P(code));
+       }
 }
 /* }}} */
 
@@ -1807,27 +1941,29 @@ PHP_METHOD(HttpRequest, getResponseCode)
  */
 PHP_METHOD(HttpRequest, getResponseInfo)
 {
-       zval *info, **infop;
-       char *info_name = NULL;
-       int info_len = 0;
-       getObject(http_request_object, obj);
+       IF_RETVAL_USED {
+               zval *info, **infop;
+               char *info_name = NULL;
+               int info_len = 0;
+               getObject(http_request_object, obj);
 
-       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &info_name, &info_len)) {
-               RETURN_FALSE;
-       }
+               if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &info_name, &info_len)) {
+                       RETURN_FALSE;
+               }
 
-       info = GET_PROP(obj, responseInfo);
+               info = GET_PROP(obj, responseInfo);
 
-       if (info_len && info_name) {
-               if (SUCCESS == zend_hash_find(Z_ARRVAL_P(info), pretty_key(info_name, info_len, 0, 0), info_len + 1, (void **) &infop)) {
-                       RETURN_ZVAL(*infop, 1, ZVAL_PTR_DTOR);
+               if (info_len && info_name) {
+                       if (SUCCESS == zend_hash_find(Z_ARRVAL_P(info), pretty_key(info_name, info_len, 0, 0), info_len + 1, (void **) &infop)) {
+                               RETURN_ZVAL(*infop, 1, ZVAL_PTR_DTOR);
+                       } else {
+                               http_error_ex(E_NOTICE, HTTP_E_PARAM, "Could not find response info named %s", info_name);
+                               RETURN_FALSE;
+                       }
                } else {
-                       http_error_ex(E_NOTICE, HTTP_E_PARAM, "Could not find response info named %s", info_name);
-                       RETURN_FALSE;
+                       array_init(return_value);
+                       array_copy(info, return_value);
                }
-       } else {
-               array_init(return_value);
-               array_copy(info, return_value);
        }
 }
 /* }}}*/
@@ -1838,16 +1974,18 @@ PHP_METHOD(HttpRequest, getResponseInfo)
  */
 PHP_METHOD(HttpRequest, getResponseMessage)
 {
-       zval *message;
-       getObject(http_request_object, obj);
-
        NO_ARGS;
 
-       message = GET_PROP(obj, responseMessage);
-       Z_TYPE_P(return_value) = IS_OBJECT;
-       return_value->is_ref = 1;
-       return_value->value.obj = message->value.obj;
-       zval_add_ref(&return_value);
+       IF_RETVAL_USED {
+               zval *message;
+               getObject(http_request_object, obj);
+
+               message = GET_PROP(obj, responseMessage);
+               Z_TYPE_P(return_value) = IS_OBJECT;
+               return_value->is_ref = 1;
+               return_value->value.obj = message->value.obj;
+               zval_add_ref(&return_value);
+       }
 }
 
 /* {{{ proto bool HttpRequest::send()
@@ -1908,7 +2046,9 @@ PHP_METHOD(HttpRequest, send)
        resp  = GET_PROP(obj, responseData);
 
        // HTTP_URI_MAXLEN+1 long char *
-       request_uri = http_absolute_uri_ex(Z_STRVAL_P(URL), Z_STRLEN_P(URL), NULL, 0, NULL, 0, 0);
+       if (!(request_uri = http_absolute_uri_ex(Z_STRVAL_P(URL), Z_STRLEN_P(URL), NULL, 0, NULL, 0, 0))) {
+               RETURN_FALSE;
+       }
 
        if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) {
                if (!strchr(request_uri, '?')) {
@@ -1933,7 +2073,7 @@ PHP_METHOD(HttpRequest, send)
                        php_stream_statbuf ssb;
                        zval *file = GET_PROP(obj, putFile);
 
-                       if (    (stream = php_stream_open_wrapper(Z_STRVAL_P(file), , "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL)) && 
+                       if (    (stream = php_stream_open_wrapper(Z_STRVAL_P(file), , "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL)) &&
                                        !php_stream_stat(stream, &ssb)) {
                                body.type = HTTP_REQUEST_BODY_UPLOADFILE;
                                body.data = stream;
@@ -1963,11 +2103,11 @@ PHP_METHOD(HttpRequest, send)
                {
                        http_request_body body;
                        zval *post = GET_PROP(obj, postData);
-                       
+
                        body.type = HTTP_REQUEST_BODY_CSTRING;
                        body.data = Z_STRVAL_P(post);
                        body.size = Z_STRLEN_P(post);
-                       
+
                        status = http_request_ex(obj->ch, Z_LVAL_P(meth), request_uri, &body, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response);
                }
                break;
index 19f25fa..0b71ef7 100644 (file)
@@ -37,7 +37,7 @@
 ZEND_EXTERN_MODULE_GLOBALS(http)
 
 #if LIBCURL_VERSION_NUM < 0x070c00
-#      define curl_easy_strerror(code) HTTP_G(curlerr)
+#      define curl_easy_strerror(code) HTTP_G(request).curl.error
 #endif
 
 #define HTTP_CURL_INFO(I) HTTP_CURL_INFO_EX(I, I)
@@ -156,6 +156,8 @@ PHP_HTTP_API STATUS _http_request_body_fill(http_request_body *body, HashTable *
                                        curl_formfree(http_post_data[0]);
                                        return FAILURE;
                                }
+                       } else {
+                               http_error(E_NOTICE, HTTP_E_PARAM, "Post file array entry misses either 'name', 'type' or 'file' entry");
                        }
                }
 
@@ -244,7 +246,7 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c
        HTTP_CURL_OPT(NOSIGNAL, 1);
 #endif
 #if LIBCURL_VERSION_NUM < 0x070c00
-       HTTP_CURL_OPT(ERRORBUFFER, HTTP_G(curlerr));
+       HTTP_CURL_OPT(ERRORBUFFER, HTTP_G(request).curl.error);
 #endif
 
        /* progress callback */
@@ -331,14 +333,13 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c
        if (zoption = http_curl_getopt(options, "useragent", IS_STRING)) {
                HTTP_CURL_OPT(USERAGENT, http_curl_copystr(Z_STRVAL_P(zoption)));
        } else {
-               HTTP_CURL_OPT(USERAGENT,
-                       "PECL::HTTP/" HTTP_PEXT_VERSION " (PHP/" PHP_VERSION ")");
+               HTTP_CURL_OPT(USERAGENT, "PECL::HTTP/" HTTP_PEXT_VERSION " (PHP/" PHP_VERSION ")");
        }
 
        /* additional headers, array('name' => 'value') */
        if (zoption = http_curl_getopt(options, "headers", IS_ARRAY)) {
                char *header_key;
-               long header_idx;
+               ulong header_idx;
                struct curl_slist *headers = NULL;
 
                FOREACH_KEY(zoption, header_key, header_idx) {
@@ -363,7 +364,7 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c
        /* cookies, array('name' => 'value') */
        if (zoption = http_curl_getopt(options, "cookies", IS_ARRAY)) {
                char *cookie_key = NULL;
-               long cookie_idx = 0;
+               ulong cookie_idx = 0;
                phpstr *qstr = phpstr_new();
 
                FOREACH_KEY(zoption, cookie_key, cookie_idx) {
@@ -427,7 +428,7 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c
                zval **param;
 
                FOREACH_KEYVAL(zoption, key, idx, param) {
-                       if (key) {fprintf(stderr, "%s\n", key);
+                       if (key) {
                                HTTP_CURL_OPT_SSL_STRING(CERT);
 #if LIBCURL_VERSION_NUM >= 0x070903
                                HTTP_CURL_OPT_SSL_STRING(CERTTYPE);
@@ -483,8 +484,8 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c
                break;
 
                default:
-                       if ((meth > HTTP_NO_REQUEST_METHOD) && (meth < HTTP_MAX_REQUEST_METHOD)) {
-                               curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, http_request_methods[meth]);
+                       if (http_request_method_exists(0, meth, NULL)) {
+                               curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, http_request_method_name(meth));
                        } else {
                                http_error_ex(E_WARNING, HTTP_E_CURL, "Unsupported request method: %d", meth);
                                status = FAILURE;
@@ -580,7 +581,7 @@ PHP_HTTP_API STATUS _http_request_ex(CURL *ch, http_request_method meth, const c
 
 http_request_end:
        /* free strings copied with http_curl_copystr() */
-       zend_llist_clean(&HTTP_G(to_free));
+       zend_llist_clean(&HTTP_G(request).curl.copies);
 
        /* clean curl handle if acquired */
        if (clean_curl) {
@@ -597,16 +598,71 @@ http_request_end:
 }
 /* }}} */
 
-/* {{{ char *http_request_method_string(http_request_method) */
-PHP_HTTP_API const char *_http_request_method_string(http_request_method m)
+/* {{{ char *http_request_method_name(http_request_method) */
+PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC)
 {
-       if ((m > HTTP_NO_REQUEST_METHOD) && (m < HTTP_MAX_REQUEST_METHOD)) {
+       zval **meth;
+
+       if (HTTP_STD_REQUEST_METHOD(m)) {
                return http_request_methods[m];
        }
+
+       if (SUCCESS == zend_hash_index_find(&HTTP_G(request).methods.custom, HTTP_CUSTOM_REQUEST_METHOD(m), (void **) &meth)) {
+               return Z_STRVAL_PP(meth);
+       }
+
        return http_request_methods[0];
 }
 /* }}} */
 
+/* {{{ unsigned long http_request_method_exists(zend_bool, unsigned long, char *) */
+PHP_HTTP_API unsigned long _http_request_method_exists(zend_bool by_name, unsigned long id, const char *name TSRMLS_DC)
+{
+       if (by_name) {
+               unsigned i;
+
+               for (i = HTTP_NO_REQUEST_METHOD + 1; i < HTTP_MAX_REQUEST_METHOD; ++i) {
+                       if (!strcmp(name, http_request_methods[i])) {
+                               return i;
+                       }
+               }
+               {
+                       zval **data;
+                       char *key;
+                       ulong idx;
+
+                       FOREACH_HASH_KEYVAL(&HTTP_G(request).methods.custom, key, idx, data) {
+                               if (!strcmp(name, Z_STRVAL_PP(data))) {
+                                       return idx + HTTP_MAX_REQUEST_METHOD;
+                               }
+                       }
+               }
+               return 0;
+       } else {
+               return HTTP_STD_REQUEST_METHOD(id) || zend_hash_index_exists(&HTTP_G(request).methods.custom, HTTP_CUSTOM_REQUEST_METHOD(id)) ? id : 0;
+       }
+}
+/* }}} */
+
+/* {{{ unsigned long http_request_method_register(char *) */
+PHP_HTTP_API unsigned long _http_request_method_register(const char *method TSRMLS_DC)
+{
+       zval array;
+       unsigned long meth_num = HTTP_G(request).methods.custom.nNextFreeElement + HTTP_MAX_REQUEST_METHOD;
+
+       Z_ARRVAL(array) = &HTTP_G(request).methods.custom;
+       add_next_index_string(&array, estrdup(method), 0);
+       return meth_num;
+}
+/* }}} */
+
+/* {{{ STATUS http_request_method_unregister(usngigned long) */
+PHP_HTTP_API STATUS _http_request_method_unregister(unsigned long method TSRMLS_DC)
+{
+       return zend_hash_index_del(&HTTP_G(request).methods.custom, HTTP_CUSTOM_REQUEST_METHOD(method));
+}
+/* }}} */
+
 /* {{{ char *http_request_methods[] */
 static const char *const http_request_methods[] = {
        "UNKOWN",
@@ -649,7 +705,7 @@ static const char *const http_request_methods[] = {
 static inline char *_http_curl_copystr(const char *str TSRMLS_DC)
 {
        char *new_str = estrdup(str);
-       zend_llist_add_element(&HTTP_G(to_free), &new_str);
+       zend_llist_add_element(&HTTP_G(request).curl.copies, &new_str);
        return new_str;
 }
 /* }}} */
index aaa51f5..480479d 100644 (file)
@@ -52,6 +52,12 @@ zend_function_entry http_response_object_fe[] = {
        PHP_ME(HttpResponse, setGzip, NULL, ZEND_ACC_PUBLIC)
        PHP_ME(HttpResponse, getGzip, NULL, ZEND_ACC_PUBLIC)
 
+       PHP_ME(HttpResponse, setThrottleDelay, NULL, ZEND_ACC_PUBLIC)
+       PHP_ME(HttpResponse, getThrottleDelay, NULL, ZEND_ACC_PUBLIC)
+
+       PHP_ME(HttpResponse, setSendBuffersize, NULL, ZEND_ACC_PUBLIC)
+       PHP_ME(HttpResponse, getSendBuffersize, NULL, ZEND_ACC_PUBLIC)
+
        PHP_ME(HttpResponse, setData, NULL, ZEND_ACC_PUBLIC)
        PHP_ME(HttpResponse, getData, NULL, ZEND_ACC_PUBLIC)
 
@@ -105,6 +111,8 @@ static inline void _http_response_object_declare_default_properties(TSRMLS_D)
        DCL_PROP(PROTECTED, long, dispoInline, 0);
        DCL_PROP(PROTECTED, long, cache, 0);
        DCL_PROP(PROTECTED, long, gzip, 0);
+       DCL_PROP(PROTECTED, long, sendBuffersize, HTTP_SENDBUF_SIZE);
+       DCL_PROP(PROTECTED, double, throttleDelay, 0.0);
 
        DCL_PROP(PRIVATE, long, raw_cache_header, 0);
        DCL_PROP(PRIVATE, long, send_mode, -1);
index 41ba305..4caf6ee 100644 (file)
 
 ZEND_EXTERN_MODULE_GLOBALS(http);
 
+#define http_flush() _http_flush(TSRMLS_C)
+/* {{{ static inline void http_flush() */
+static inline void _http_flush(TSRMLS_D)
+{
+       php_end_ob_buffer(1, 1 TSRMLS_CC);
+       sapi_flush(TSRMLS_C);
+}
+/* }}} */
+
+#define http_sleep() _http_sleep(TSRMLS_C)
+/* {{{ static inline void http_sleep() */
+static inline void _http_sleep(TSRMLS_D)
+{
+       if (HTTP_G(send).throttle_delay >= 0.001) {
+#if defined(PHP_WIN32)
+               Sleep((DWORD) (HTTP_G(send).throttle_delay * 1000));
+#elif defined(HAVE_USLEEP)
+               usleep(HTTP_G(send).throttle_delay * 1000000);
+#elif defined(HAVE_NANOSLEEP)
+               struct timespec req, rem;
+
+               req.tv_sec = (time_t) HTTP_G(send).throttle_delay;
+               req.tv_nsec = (HTTP_G(send).throttle_delay * 1000000000) % 1000000000;
+
+               while (nanosleep(&req, &rem) && (errno == EINTR) && (rem.tv_nsec > 1000000)) {
+                       req.tv_sec = rem.tv_sec;
+                       req.tv_nsec = rem.tv_nsec;
+               }
+#endif
+       }
+}
+/* }}} */
+
+#define HTTP_CHUNK_AVAIL(len) ((len -= HTTP_G(send).buffer_size) >= 0)
+#define HTTP_CHUNK_WRITE(data, l, dofree, dosleep) \
+       { \
+               long size = (long) l; \
+ \
+               if ((1 > size) || (size - PHPWRITE(data, size))) { \
+                       if (dofree) { \
+                               efree(data); \
+                       } \
+                       return FAILURE; \
+               } \
+ \
+               http_flush(); \
+               if (dosleep) { \
+                       http_sleep(); \
+               } \
+       }
+
 #define http_send_chunk(d, b, e, m) _http_send_chunk((d), (b), (e), (m) TSRMLS_CC)
 /* {{{ static STATUS http_send_chunk(const void *, size_t, size_t, http_send_mode) */
 static STATUS _http_send_chunk(const void *data, size_t begin, size_t end, http_send_mode mode TSRMLS_DC)
@@ -46,44 +97,23 @@ static STATUS _http_send_chunk(const void *data, size_t begin, size_t end, http_
                case SEND_RSRC:
                {
                        char *buf;
-                       size_t read = 0;
                        php_stream *s = (php_stream *) data;
 
                        if (php_stream_seek(s, begin, SEEK_SET)) {
                                return FAILURE;
                        }
 
-                       buf = (char *) ecalloc(1, HTTP_SENDBUF_SIZE);
-                       /* read into buf and write out */
-                       while ((len -= HTTP_SENDBUF_SIZE) >= 0) {
-                               if (!(read = php_stream_read(s, buf, HTTP_SENDBUF_SIZE))) {
-                                       efree(buf);
-                                       return FAILURE;
-                               }
-                               if (read - php_body_write(buf, read TSRMLS_CC)) {
-                                       efree(buf);
-                                       return FAILURE;
-                               }
-                               /* ob_flush() && flush() */
-                               php_end_ob_buffer(1, 1 TSRMLS_CC);
-                               sapi_flush(TSRMLS_C);
+                       buf = emalloc(HTTP_G(send).buffer_size);
+
+                       while (HTTP_CHUNK_AVAIL(len)) {
+                               HTTP_CHUNK_WRITE(buf, php_stream_read(s, buf, HTTP_G(send).buffer_size), 1, 1);
                        }
 
                        /* read & write left over */
                        if (len) {
-                               if (read = php_stream_read(s, buf, HTTP_SENDBUF_SIZE + len)) {
-                                       if (read - php_body_write(buf, read TSRMLS_CC)) {
-                                               efree(buf);
-                                               return FAILURE;
-                                       }
-                               } else {
-                                       efree(buf);
-                                       return FAILURE;
-                               }
-                               /* ob_flush() & flush() */
-                               php_end_ob_buffer(1, 1 TSRMLS_CC);
-                               sapi_flush(TSRMLS_C);
+                               HTTP_CHUNK_WRITE(buf, php_stream_read(s, buf, HTTP_G(send).buffer_size + len), 1, 0);
                        }
+
                        efree(buf);
                        return SUCCESS;
                }
@@ -92,25 +122,16 @@ static STATUS _http_send_chunk(const void *data, size_t begin, size_t end, http_
                {
                        char *s = (char *) data + begin;
 
-                       while ((len -= HTTP_SENDBUF_SIZE) >= 0) {
-                               if (HTTP_SENDBUF_SIZE - php_body_write(s, HTTP_SENDBUF_SIZE TSRMLS_CC)) {
-                                       return FAILURE;
-                               }
-                               s += HTTP_SENDBUF_SIZE;
-                               /* ob_flush() & flush() */
-                               php_end_ob_buffer(1, 1 TSRMLS_CC);
-                               sapi_flush(TSRMLS_C);
+                       while (HTTP_CHUNK_AVAIL(len)) {
+                               HTTP_CHUNK_WRITE(s, HTTP_G(send).buffer_size, 0, 1);
+                               s += HTTP_G(send).buffer_size;
                        }
 
                        /* write left over */
                        if (len) {
-                               if (HTTP_SENDBUF_SIZE + len - php_body_write(s, HTTP_SENDBUF_SIZE + len TSRMLS_CC)) {
-                                               return FAILURE;
-                               }
-                               /* ob_flush() & flush() */
-                               php_end_ob_buffer(1, 1 TSRMLS_CC);
-                               sapi_flush(TSRMLS_C);
+                               HTTP_CHUNK_WRITE(s, HTTP_G(send).buffer_size + len, 0, 0);
                        }
+
                        return SUCCESS;
                }
 
@@ -123,11 +144,11 @@ static STATUS _http_send_chunk(const void *data, size_t begin, size_t end, http_
 
 
 /* {{{ STATUS http_send_status_header(int, char *) */
-PHP_HTTP_API STATUS _http_send_status_header(int status, const char *header TSRMLS_DC)
+PHP_HTTP_API STATUS _http_send_status_header_ex(int status, const char *header, zend_bool replace TSRMLS_DC)
 {
        STATUS ret;
        sapi_header_line h = {(char *) header, header ? strlen(header) : 0, status};
-       if (SUCCESS != (ret = sapi_header_op(SAPI_HEADER_REPLACE, &h TSRMLS_CC))) {
+       if (SUCCESS != (ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, &h TSRMLS_CC))) {
                http_error_ex(E_WARNING, HTTP_E_HEADER, "Could not send header: %s (%d)", header, status);
        }
        return ret;
@@ -144,7 +165,7 @@ PHP_HTTP_API STATUS _http_send_last_modified(time_t t TSRMLS_DC)
                efree(date);
 
                /* remember */
-               HTTP_G(lmod) = t;
+               HTTP_G(send).last_modified = t;
 
                return http_send_header(modified);
        }
@@ -159,15 +180,13 @@ PHP_HTTP_API STATUS _http_send_etag(const char *etag, size_t etag_len TSRMLS_DC)
        char *etag_header;
 
        if (!etag_len){
-               http_error_ex(E_WARNING, HTTP_E_HEADER, "Attempt to send empty ETag (previous: %s)\n", HTTP_G(etag));
+               http_error_ex(E_WARNING, HTTP_E_HEADER, "Attempt to send empty ETag (previous: %s)\n", HTTP_G(send).unquoted_etag);
                return FAILURE;
        }
 
        /* remember */
-       if (HTTP_G(etag)) {
-               efree(HTTP_G(etag));
-       }
-       HTTP_G(etag) = estrdup(etag);
+       STR_FREE(HTTP_G(send).unquoted_etag);
+       HTTP_G(send).unquoted_etag = estrdup(etag);
 
        etag_header = ecalloc(1, sizeof("ETag: \"\"") + etag_len);
        sprintf(etag_header, "ETag: \"%s\"", etag);
@@ -202,10 +221,8 @@ PHP_HTTP_API STATUS _http_send_content_type(const char *content_type, size_t ct_
        }
 
        /* remember for multiple ranges */
-       if (HTTP_G(ctype)) {
-               efree(HTTP_G(ctype));
-       }
-       HTTP_G(ctype) = estrndup(content_type, ct_len);
+       STR_FREE(HTTP_G(send).content_type);
+       HTTP_G(send).content_type = estrndup(content_type, ct_len);
 
        ct_header = ecalloc(1, sizeof("Content-Type: ") + ct_len);
        sprintf(ct_header, "Content-Type: %s", content_type);
@@ -248,6 +265,7 @@ PHP_HTTP_API STATUS _http_send_ranges(HashTable *ranges, const void *data, size_
                if (SUCCESS != zend_hash_index_find(ranges, 0, (void **) &zrange) ||
                        SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(zrange), 0, (void **) &begin) ||
                        SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(zrange), 1, (void **) &end)) {
+                       http_send_status(500);
                        return FAILURE;
                }
 
@@ -290,20 +308,20 @@ PHP_HTTP_API STATUS _http_send_ranges(HashTable *ranges, const void *data, size_
                                HTTP_CRLF,
 
                                bound,
-                               HTTP_G(ctype) ? HTTP_G(ctype) : "application/x-octetstream",
+                               HTTP_G(send).content_type ? HTTP_G(send).content_type : "application/x-octetstream",
                                **begin,
                                **end,
                                size
                        );
 
-                       php_body_write(preface, strlen(preface) TSRMLS_CC);
+                       PHPWRITE(preface, strlen(preface));
                        http_send_chunk(data, **begin, **end + 1, mode);
                }
 
                /* write boundary once more */
-               php_body_write(HTTP_CRLF, sizeof(HTTP_CRLF) - 1 TSRMLS_CC);
-               php_body_write(bound, strlen(bound) TSRMLS_CC);
-               php_body_write("--", 2 TSRMLS_CC);
+               PHPWRITE(HTTP_CRLF, lenof(HTTP_CRLF));
+               PHPWRITE(bound, strlen(bound));
+               PHPWRITE("--", lenof("--"));
 
                return SUCCESS;
        }
@@ -325,9 +343,9 @@ PHP_HTTP_API STATUS _http_send(const void *data_ptr, size_t data_size, http_send
        }
 
        /* stop on-the-fly etag generation */
-       if (cache_etag = HTTP_G(etag_started)) {
+       if (cache_etag = HTTP_G(etag).started) {
                /* interrupt ob_etaghandler */
-               HTTP_G(etag_started) = 0;
+               HTTP_G(etag).started = 0;
        }
 
        /* enable partial dl and resume */
@@ -344,8 +362,8 @@ PHP_HTTP_API STATUS _http_send(const void *data_ptr, size_t data_size, http_send
 
        /* Range Request - only send ranges if entity hasn't changed */
        if (    range_status == RANGE_OK &&
-                       http_match_etag_ex("HTTP_IF_MATCH", HTTP_G(etag), 0) &&
-                       http_match_last_modified_ex("HTTP_IF_UNMODIFIED_SINCE", HTTP_G(lmod), 0)) {
+                       http_match_etag_ex("HTTP_IF_MATCH", HTTP_G(send).unquoted_etag, 0) &&
+                       http_match_last_modified_ex("HTTP_IF_UNMODIFIED_SINCE", HTTP_G(send).last_modified, 0)) {
                STATUS result = http_send_ranges(&ranges, data_ptr, data_size, data_mode);
                zend_hash_destroy(&ranges);
                return result;
@@ -353,26 +371,24 @@ PHP_HTTP_API STATUS _http_send(const void *data_ptr, size_t data_size, http_send
 
        zend_hash_destroy(&ranges);
 
-       /* send 304 Not Modified if etag matches */
+       /* send 304 Not Modified if etag matches - DON'T return on ETag generation failure */
        if (cache_etag) {
                char *etag = NULL;
 
                if (!(etag = http_etag(data_ptr, data_size, data_mode))) {
-                       return FAILURE;
-               }
-               if (SUCCESS != http_send_etag(etag, 32)) {
+                       http_error(E_NOTICE, HTTP_E_PARAM, "Failed to generate ETag for data source");
+               } else {
+                       http_send_etag(etag, 32);
+                       if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
+                               return http_cache_exit_ex(etag, 1, 1);
+                       }
                        efree(etag);
-                       return FAILURE;
-               }
-               if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
-                       return http_cache_exit_ex(etag, 1, 1);
                }
-               efree(etag);
        }
 
        /* send 304 Not Modified if last modified matches */
-       if (http_match_last_modified("HTTP_IF_MODIFIED_SINCE", HTTP_G(lmod))) {
-               return http_cache_exit_ex(http_date(HTTP_G(lmod)), 0, 1);
+       if (http_match_last_modified("HTTP_IF_MODIFIED_SINCE", HTTP_G(send).last_modified)) {
+               return http_cache_exit_ex(http_date(HTTP_G(send).last_modified), 0, 1);
        }
 
        /* send full entity */
@@ -384,12 +400,13 @@ PHP_HTTP_API STATUS _http_send(const void *data_ptr, size_t data_size, http_send
 PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *file, zend_bool close_stream TSRMLS_DC)
 {
        STATUS status;
+       php_stream_statbuf ssb;
 
-       if ((!file) || php_stream_stat(file, &HTTP_G(ssb))) {
+       if ((!file) || php_stream_stat(file, &ssb)) {
                return FAILURE;
        }
 
-       status = http_send(file, HTTP_G(ssb).sb.st_size, SEND_RSRC);
+       status = http_send(file, ssb.sb.st_size, SEND_RSRC);
 
        if (close_stream) {
                php_stream_close(file);
@@ -399,7 +416,6 @@ PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *file, zend_bool close_strea
 }
 /* }}} */
 
-
 /*
  * Local variables:
  * tab-width: 4
diff --git a/missing.c b/missing.c
new file mode 100644 (file)
index 0000000..bbc4b3a
--- /dev/null
+++ b/missing.c
@@ -0,0 +1,38 @@
+
+#include "php.h"
+#include "missing.h"
+
+int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC)
+{
+       zval *property;
+
+       if (ce->type & ZEND_INTERNAL_CLASS) {
+               property = malloc(sizeof(zval));
+       } else {
+               ALLOC_ZVAL(property);
+       }
+       INIT_PZVAL(property);
+       ZVAL_DOUBLE(property, value);
+       return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
+}
+
+void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC)
+{
+       zval *tmp;
+
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_DOUBLE(tmp, value);
+       zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
+
diff --git a/missing.h b/missing.h
new file mode 100644 (file)
index 0000000..b5f822e
--- /dev/null
+++ b/missing.h
@@ -0,0 +1,18 @@
+
+#ifndef PHP_HTTP_MISSING
+#define PHP_HTTP_MISSING
+
+extern int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC);
+extern void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC);
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
+
index 5e8ebd1..6791580 100644 (file)
@@ -1,95 +1,96 @@
-<?xml version="1.0" encoding="iso-8859-1"?>\r
-<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">\r
-<package version="1.0">\r
-  <name>pecl_http</name>\r
-  <summary>Extended HTTP support</summary>\r
-  <description>\r
-<![CDATA[\r
-* Building absolute URIs\r
-* RFC compliant HTTP redirects\r
-* RFC compliant HTTP date handling\r
-* Parsing of HTTP headers and messages\r
-* Caching by "Last-Modified" and/or ETag\r
-  (with 'on the fly' option for ETag generation from buffered output)\r
-* Sending data/files/streams with (multiple) ranges support\r
-* Negotiating user preferred language/charset\r
-* Convenient request functions to HEAD/GET/POST if libcurl is available\r
-* HTTP auth hooks (Basic)\r
-]]>\r
-  </description>\r
-  <license>PHP License 3.0</license>\r
-\r
-  <maintainers>\r
-    <maintainer>\r
-      <user>mike</user>\r
-      <name>Michael Wallner</name>\r
-      <email>mike@php.net</email>\r
-      <role>lead</role>\r
-    </maintainer>\r
-  </maintainers>\r
-\r
-  <release>\r
-    <version>0.8.0dev</version>\r
-    <date>2005-05-00</date>\r
-    <state>beta</state>\r
-    <notes><![CDATA[\r
-* renamed ob_httpetaghandler to ob_etaghandler\r
-* added HttpMessage class and HttpException (PHP5 only)\r
-* added http.cache_log INI directive\r
-* http_chunked_decode() now silently passes through apparently not encoded data\r
-]]>\r
-    </notes>\r
-  </release>\r
-\r
-  <filelist>\r
-    <dir name="/">\r
-      <file role="doc">CREDITS</file>\r
-      <file role="doc">EXPERIMENTAL</file>\r
-      <file role="doc">docs/functions.html</file>\r
-      \r
-      <file role="src" platform="windows">http.dsp</file>\r
-      <file role="src" platform="windows">config.w32</file>\r
-      <file role="src">config.m4</file>\r
-      \r
-      <file role="src">phpstr/phpstr.h</file>\r
-      <file role="src">phpstr/phpstr.c</file>\r
-      \r
-      <file role="src">php_http.h</file>\r
-      <file role="src">php_http_std_defs.h</file>\r
-      <file role="src">php_http_api.h</file>\r
-      <file role="src">php_http_auth_api.h</file>\r
-      <file role="src">php_http_cache_api.h</file>\r
-      <file role="src">php_http_date_api.h</file>\r
-      <file role="src">php_http_headers_api.h</file>\r
-      <file role="src">php_http_message_api.h</file>\r
-      <file role="src">php_http_request_api.h</file>\r
-      <file role="src">php_http_send_api.h</file>\r
-      <file role="src">php_http_url_api.h</file>\r
-      <file role="src">php_http_util_object.h</file>\r
-      <file role="src">php_http_message_object.h</file>\r
-      <file role="src">php_http_request_object.h</file>\r
-      <file role="src">php_http_response_object.h</file>\r
-      <file role="src">php_http_exception_object.h</file>\r
-      \r
-      <file role="src">http.c</file>\r
-      <file role="src">http_functions.c</file>\r
-      <file role="src">http_methods.c</file>\r
-      <file role="src">http_api.c</file>\r
-      <file role="src">http_auth_api.c</file>\r
-      <file role="src">http_cache_api.c</file>\r
-      <file role="src">http_date_api.c</file>\r
-      <file role="src">http_headers_api.c</file>\r
-      <file role="src">http_message_api.c</file>\r
-      <file role="src">http_request_api.c</file>\r
-      <file role="src">http_send_api.c</file>\r
-      <file role="src">http_url_api.c</file>\r
-      <file role="src">http_util_object.c</file>\r
-      <file role="src">http_message_object.c</file>\r
-      <file role="src">http_request_object.c</file>\r
-      <file role="src">http_response_object.c</file>\r
-      <file role="src">http_exception_object.c</file>\r
-      \r
-    </dir>\r
-  </filelist>\r
-</package>\r
-\r
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
+<package version="1.0">
+  <name>pecl_http</name>
+  <summary>Extended HTTP support</summary>
+  <description>
+<![CDATA[
+* Building absolute URIs
+* RFC compliant HTTP redirects
+* RFC compliant HTTP date handling
+* Parsing of HTTP headers and messages
+* Caching by "Last-Modified" and/or ETag
+  (with 'on the fly' option for ETag generation from buffered output)
+* Sending data/files/streams with (multiple) ranges support
+* Negotiating user preferred language/charset
+* Convenient request functions to HEAD/GET/POST if libcurl is available
+* HTTP auth hooks (Basic)
+]]>
+  </description>
+  <license>PHP License 3.0</license>
+
+  <maintainers>
+    <maintainer>
+      <user>mike</user>
+      <name>Michael Wallner</name>
+      <email>mike@php.net</email>
+      <role>lead</role>
+    </maintainer>
+  </maintainers>
+
+  <release>
+    <version>0.8.0dev</version>
+    <date>2005-05-00</date>
+    <state>beta</state>
+    <notes><![CDATA[
+* renamed ob_httpetaghandler to ob_etaghandler
+* added HttpMessage class and HttpException (PHP5 only)
+* added http.cache_log INI directive
+* http_chunked_decode() now silently passes through apparently not encoded data
+* added throttling capability to http_send()/HttpResponse
+]]>
+    </notes>
+  </release>
+
+  <filelist>
+    <dir name="/">
+      <file role="doc">CREDITS</file>
+      <file role="doc">EXPERIMENTAL</file>
+      <file role="doc">docs/functions.html</file>
+      
+      <file role="src" platform="windows">http.dsp</file>
+      <file role="src" platform="windows">config.w32</file>
+      <file role="src">config.m4</file>
+      
+      <file role="src">phpstr/phpstr.h</file>
+      <file role="src">phpstr/phpstr.c</file>
+      
+      <file role="src">php_http.h</file>
+      <file role="src">php_http_std_defs.h</file>
+      <file role="src">php_http_api.h</file>
+      <file role="src">php_http_auth_api.h</file>
+      <file role="src">php_http_cache_api.h</file>
+      <file role="src">php_http_date_api.h</file>
+      <file role="src">php_http_headers_api.h</file>
+      <file role="src">php_http_message_api.h</file>
+      <file role="src">php_http_request_api.h</file>
+      <file role="src">php_http_send_api.h</file>
+      <file role="src">php_http_url_api.h</file>
+      <file role="src">php_http_util_object.h</file>
+      <file role="src">php_http_message_object.h</file>
+      <file role="src">php_http_request_object.h</file>
+      <file role="src">php_http_response_object.h</file>
+      <file role="src">php_http_exception_object.h</file>
+      
+      <file role="src">http.c</file>
+      <file role="src">http_functions.c</file>
+      <file role="src">http_methods.c</file>
+      <file role="src">http_api.c</file>
+      <file role="src">http_auth_api.c</file>
+      <file role="src">http_cache_api.c</file>
+      <file role="src">http_date_api.c</file>
+      <file role="src">http_headers_api.c</file>
+      <file role="src">http_message_api.c</file>
+      <file role="src">http_request_api.c</file>
+      <file role="src">http_send_api.c</file>
+      <file role="src">http_url_api.c</file>
+      <file role="src">http_util_object.c</file>
+      <file role="src">http_message_object.c</file>
+      <file role="src">http_request_object.c</file>
+      <file role="src">http_response_object.c</file>
+      <file role="src">http_exception_object.c</file>
+      
+    </dir>
+  </filelist>
+</package>
+
index 952639c..9b9b1e7 100644 (file)
@@ -34,29 +34,51 @@ extern zend_module_entry http_module_entry;
 #define phpext_http_ptr &http_module_entry
 
 ZEND_BEGIN_MODULE_GLOBALS(http)
-       zend_bool etag_started;
-       PHP_MD5_CTX etag_md5;
-       php_stream_statbuf ssb;
-       char *ctype;
-       char *etag;
-       time_t lmod;
-       char *allowed_methods;
-       char *cache_log;
+
+       struct _http_globals_etag {
+               zend_bool started;
+               PHP_MD5_CTX md5ctx;
+       } etag;
+
+       struct _http_globals_log {
+               char *cache;
+       } log;
+
+       struct _http_globals_send {
+               double throttle_delay;
+               size_t buffer_size;
+               char *content_type;
+               char *unquoted_etag;
+               time_t last_modified;
+       } send;
+
+       struct _http_globals_request {
+               struct _http_globals_request_methods {
+                       char *allowed;
+                       HashTable custom;
+               } methods;
 
 #ifdef HTTP_HAVE_CURL
+               struct _http_globals_request_curl {
+                       zend_llist copies;
 #      if LIBCURL_VERSION_NUM < 0x070c00
-       char curlerr[CURL_ERROR_SIZE + 1];
+                       char error[CURL_ERROR_SIZE + 1];
 #      endif
-       zend_llist to_free;
+               } curl;
 #endif /* HTTP_HAVE_CURL */
+       } request;
+
 ZEND_END_MODULE_GLOBALS(http)
 
 #ifdef ZTS
 #      include "TSRM.h"
 #      define HTTP_G(v) TSRMG(http_globals_id, zend_http_globals *, v)
+#      define HTTP_GLOBALS ((zend_http_globals *) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(http_globals_id)])
 #else
 #      define HTTP_G(v) (http_globals.v)
+#      define HTTP_GLOBALS http_globals
 #endif
+#define getGlobals(G) zend_http_globals *G = HTTP_GLOBALS;
 
 PHP_FUNCTION(http_test);
 PHP_FUNCTION(http_date);
@@ -64,6 +86,7 @@ PHP_FUNCTION(http_absolute_uri);
 PHP_FUNCTION(http_negotiate_language);
 PHP_FUNCTION(http_negotiate_charset);
 PHP_FUNCTION(http_redirect);
+PHP_FUNCTION(http_throttle);
 PHP_FUNCTION(http_send_status);
 PHP_FUNCTION(http_send_last_modified);
 PHP_FUNCTION(http_send_content_type);
@@ -86,6 +109,11 @@ PHP_FUNCTION(http_post_data);
 PHP_FUNCTION(http_post_fields);
 PHP_FUNCTION(http_put_file);
 PHP_FUNCTION(http_put_stream);
+/*PHP_FUNCTION(http_request)*/
+PHP_FUNCTION(http_request_method_register);
+PHP_FUNCTION(http_request_method_unregister);
+PHP_FUNCTION(http_request_method_exists);
+PHP_FUNCTION(http_request_method_name);
 #endif /* HTTP_HAVE_CURL */
 PHP_FUNCTION(http_auth_basic);
 PHP_FUNCTION(http_auth_basic_cb);
index e89c576..f309035 100644 (file)
 extern zend_class_entry *http_exception_object_ce;
 extern zend_function_entry http_exception_object_fe[];
 
-#define http_exception_object_init _http_exception_object_init
+#define http_exception_object_init() _http_exception_object_init(INIT_FUNC_ARGS_PASSTHRU)
 extern void _http_exception_object_init(INIT_FUNC_ARGS);
 
 #define http_exception_get_default _http_exception_get_default
 extern zend_class_entry *_http_exception_get_default();
 
+#define http_exception_get_for_code(c) _http_exception_get_for_code(c)
+extern zend_class_entry *_http_exception_get_for_code(long code);
+
 #endif
 #endif
 
index d529a0a..731e170 100644 (file)
@@ -77,6 +77,9 @@ PHP_HTTP_API void _http_message_serialize(http_message *message, char **string,
 #define http_message_send(m) _http_message_send((m) TSRMLS_CC)
 PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC);
 
+#define http_message_dup(m) _http_message_dup((m) TSRMLS_CC)
+PHP_HTTP_API http_message *_http_message_dup(http_message *msg TSRMLS_DC);
+
 #define http_message_dtor(m) _http_message_dtor((m))
 PHP_HTTP_API void _http_message_dtor(http_message *message);
 
index fb7a5bc..b3d4c14 100644 (file)
@@ -30,13 +30,15 @@ typedef struct {
 extern zend_class_entry *http_message_object_ce;
 extern zend_function_entry http_message_object_fe[];
 
-#define http_message_object_init _http_message_object_init
+#define http_message_object_init() _http_message_object_init(INIT_FUNC_ARGS_PASSTHRU)
 extern void _http_message_object_init(INIT_FUNC_ARGS);
 #define http_message_object_new _http_message_object_new
 extern zend_object_value _http_message_object_new(zend_class_entry *ce TSRMLS_DC);
 #define http_message_object_new_ex(ce, msg) _http_message_object_new_ex(ce, msg TSRMLS_CC)
 #define http_message_object_from_msg(msg) _http_message_object_new_ex(http_message_object_ce, msg TSRMLS_CC)
 extern zend_object_value _http_message_object_new_ex(zend_class_entry *ce, http_message *msg TSRMLS_DC);
+#define http_message_object_clone(zobj) _http_message_object_clone(zobj TSRMLS_CC)
+extern zend_object_value _http_message_object_clone(zval *object TSRMLS_DC);
 #define http_message_object_free _http_message_object_free
 extern void _http_message_object_free(zend_object *object TSRMLS_DC);
 
index 269ef7b..bee4e70 100644 (file)
@@ -63,6 +63,9 @@ typedef enum {
        HTTP_MAX_REQUEST_METHOD = 28
 } http_request_method;
 
+#define HTTP_STD_REQUEST_METHOD(m) ((m > HTTP_NO_REQUEST_METHOD) && (m < HTTP_MAX_REQUEST_METHOD))
+#define HTTP_CUSTOM_REQUEST_METHOD(m) (m - HTTP_MAX_REQUEST_METHOD)
+
 #define HTTP_REQUEST_BODY_CSTRING              0
 #define HTTP_REQUEST_BODY_CURLPOST             1
 #define HTTP_REQUEST_BODY_UPLOADFILE   2
@@ -73,8 +76,17 @@ typedef struct {
        size_t size;
 } http_request_body;
 
-#define http_request_method_string(m) _http_request_method((m))
-PHP_HTTP_API const char *_http_request_method_string(http_request_method m);
+#define http_request_method_name(m) _http_request_method_name((m) TSRMLS_CC)
+PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC);
+
+#define http_request_method_exists(u, l, c) _http_request_method_exists((u), (l), (c) TSRMLS_CC)
+PHP_HTTP_API unsigned long _http_request_method_exists(zend_bool by_name, unsigned long id, const char *name TSRMLS_DC);
+
+#define http_request_method_register(m) _http_request_method_register((m) TSRMLS_CC)
+PHP_HTTP_API unsigned long _http_request_method_register(const char *method TSRMLS_DC);
+
+#define http_request_method_unregister(mn) _http_request_method_unregister((mn) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_request_method_unregister(unsigned long method TSRMLS_DC);
 
 #define http_request_body_fill(b, fields, files) _http_request_body_fill((b), (fields), (files) TSRMLS_CC)
 PHP_HTTP_API STATUS _http_request_body_fill(http_request_body *body, HashTable *fields, HashTable *files TSRMLS_DC);
index 3f87a17..6755669 100644 (file)
@@ -37,7 +37,7 @@ typedef struct {
 extern zend_class_entry *http_request_object_ce;
 extern zend_function_entry http_request_object_fe[];
 
-#define http_request_object_init _http_request_object_init
+#define http_request_object_init() _http_request_object_init(INIT_FUNC_ARGS_PASSTHRU)
 extern void _http_request_object_init(INIT_FUNC_ARGS);
 #define http_request_object_new _http_request_object_new
 extern zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC);
index 9767b5a..6484ac9 100644 (file)
@@ -26,7 +26,7 @@ typedef struct {
 extern zend_class_entry *http_response_object_ce;
 extern zend_function_entry http_response_object_fe[];
 
-#define http_response_object_init _http_response_object_init
+#define http_response_object_init() _http_response_object_init(INIT_FUNC_ARGS_PASSTHRU)
 extern void _http_response_object_init(INIT_FUNC_ARGS);
 #define http_response_object_new _http_response_object_new
 extern zend_object_value _http_response_object_new(zend_class_entry *ce TSRMLS_DC);
@@ -46,6 +46,10 @@ PHP_METHOD(HttpResponse, setCacheControl);
 PHP_METHOD(HttpResponse, getCacheControl);
 PHP_METHOD(HttpResponse, setGzip);
 PHP_METHOD(HttpResponse, getGzip);
+PHP_METHOD(HttpResponse, setThrottleDelay);
+PHP_METHOD(HttpResponse, getThrottleDelay);
+PHP_METHOD(HttpResponse, setSendBuffersize);
+PHP_METHOD(HttpResponse, getSendBuffersize);
 PHP_METHOD(HttpResponse, setData);
 PHP_METHOD(HttpResponse, getData);
 PHP_METHOD(HttpResponse, setFile);
index 5212915..c9de4d4 100644 (file)
@@ -29,8 +29,10 @@ typedef enum {
 
 #define http_send_status(s) sapi_header_op(SAPI_HEADER_SET_STATUS, (void *) (s) TSRMLS_CC)
 #define http_send_header(h) http_send_status_header(0, (h))
-#define http_send_status_header(s, h) _http_send_status_header((s), (h) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_send_status_header(int status, const char *header TSRMLS_DC);
+#define http_send_header_ex(h, r) http_send_status_header_ex(0, (h), (r))
+#define http_send_status_header(s, h) _http_send_status_header_ex((s), (h), 1 TSRMLS_CC)
+#define http_send_status_header_ex(s, h, r) _http_send_status_header_ex((s), (h), (r) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_send_status_header_ex(int status, const char *header, zend_bool replace TSRMLS_DC);
 
 #define http_send_last_modified(t) _http_send_last_modified((t) TSRMLS_CC)
 PHP_HTTP_API STATUS _http_send_last_modified(time_t t TSRMLS_DC);
index ab80130..4d36587 100644 (file)
@@ -36,6 +36,11 @@ typedef int STATUS;
 /* lenof() */
 #define lenof(S) (sizeof(S) - 1)
 
+/* STR_SET() */
+#define STR_SET(target, source) \
+       if(target) efree(target); \
+       target = source
+
 /* return bool (v == SUCCESS) */
 #define RETVAL_SUCCESS(v) RETVAL_BOOL(SUCCESS == (v))
 #define RETURN_SUCCESS(v) RETURN_BOOL(SUCCESS == (v))
@@ -63,6 +68,12 @@ typedef int STATUS;
                zend_error(E_NOTICE, "Wrong parameter count for %s()", get_active_function_name(TSRMLS_C)); \
        }
 
+/* check if return value is used */
+#define IF_RETVAL_USED \
+       if (!return_value_used) { \
+               return; \
+       } else
+
 /* CR LF */
 #define HTTP_CRLF "\r\n"
 
@@ -100,8 +111,8 @@ typedef int STATUS;
 /* server vars shorthand */
 #define HTTP_SERVER_VARS Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])
 
-#define HTTP_INI_ENTRY(entry, default, scope, global) \
-       STD_PHP_INI_ENTRY(entry, default, scope, http_update_##global, global, zend_http_globals, http_globals)
+#define HTTP_PHP_INI_ENTRY(entry, default, scope, updater, global) \
+       STD_PHP_INI_ENTRY(entry, default, scope, updater, global, zend_http_globals, http_globals)
 
 /* {{{ arrays */
 #define FOREACH_VAL(array, val) FOREACH_HASH_VAL(Z_ARRVAL_P(array), val)
index 08f42b6..b4aaf04 100644 (file)
@@ -22,7 +22,7 @@
 extern zend_class_entry *http_util_object_ce;
 extern zend_function_entry http_util_object_fe[];
 
-#define http_util_object_init _http_util_object_init
+#define http_util_object_init() _http_util_object_init(INIT_FUNC_ARGS_PASSTHRU)
 extern void _http_util_object_init(INIT_FUNC_ARGS);
 
 PHP_METHOD(HttpUtil, date);