implement message body reference counting
authorMichael Wallner <mike@php.net>
Fri, 21 Dec 2012 13:56:45 +0000 (13:56 +0000)
committerMichael Wallner <mike@php.net>
Fri, 21 Dec 2012 13:56:45 +0000 (13:56 +0000)
13 files changed:
php_http_client.c
php_http_client_request.c
php_http_curl_client.c
php_http_env.c
php_http_env_response.c
php_http_headers.c
php_http_message.c
php_http_message.h
php_http_message_body.c
php_http_message_body.h
php_http_message_parser.c
phpunit/MessageBodyTest.php
phpunit/MessageTest.php

index 5aca3bc..29da4c9 100644 (file)
@@ -32,11 +32,11 @@ PHP_HTTP_API php_http_client_t *php_http_client_init(php_http_client_t *h, php_h
        }
        h->request.buffer = php_http_buffer_init(NULL);
        h->request.parser = php_http_message_parser_init(NULL TSRMLS_CC);
-       h->request.message = php_http_message_init(NULL, 0 TSRMLS_CC);
+       h->request.message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
 
        h->response.buffer = php_http_buffer_init(NULL);
        h->response.parser = php_http_message_parser_init(NULL TSRMLS_CC);
-       h->response.message = php_http_message_init(NULL, 0 TSRMLS_CC);
+       h->response.message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
 
        TSRMLS_SET_CTX(h->ts);
 
@@ -100,11 +100,11 @@ PHP_HTTP_API php_http_client_t *php_http_client_copy(php_http_client_t *from, ph
 
                to->request.buffer = php_http_buffer_init(NULL);
                to->request.parser = php_http_message_parser_init(NULL TSRMLS_CC);
-               to->request.message = php_http_message_init(NULL, 0 TSRMLS_CC);
+               to->request.message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
 
                to->response.buffer = php_http_buffer_init(NULL);
                to->response.parser = php_http_message_parser_init(NULL TSRMLS_CC);
-               to->response.message = php_http_message_init(NULL, 0 TSRMLS_CC);
+               to->response.message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
 
                TSRMLS_SET_CTX(to->ts);
 
@@ -452,7 +452,7 @@ STATUS php_http_client_object_handle_response(zval *zclient TSRMLS_DC)
                        zend_update_property(php_http_client_class_entry, zclient, ZEND_STRL("responseMessage"), message TSRMLS_CC);
                        zval_ptr_dtor(&message);
 
-                       obj->client->response.message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->client->response.message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                } else {
                        zend_update_property_null(php_http_client_class_entry, zclient, ZEND_STRL("responseMessage") TSRMLS_CC);
                }
@@ -469,7 +469,7 @@ STATUS php_http_client_object_handle_response(zval *zclient TSRMLS_DC)
                        ZVAL_OBJVAL(message, php_http_message_object_new_ex(php_http_message_get_class_entry(), msg, NULL TSRMLS_CC), 0);
                        zend_update_property(php_http_client_class_entry, zclient, ZEND_STRL("requestMessage"), message TSRMLS_CC);
                        zval_ptr_dtor(&message);
-                       obj->client->request.message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->client->request.message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
        }
 
@@ -932,7 +932,7 @@ PHP_METHOD(HttpClient, request)
                        MAKE_STD_ZVAL(req);
                        ZVAL_OBJVAL(req, ov, 0);
 
-                       msg_obj->message = php_http_message_init(NULL, PHP_HTTP_REQUEST TSRMLS_CC);
+                       msg_obj->message = php_http_message_init(NULL, PHP_HTTP_REQUEST, NULL TSRMLS_CC);
                        PHP_HTTP_INFO(msg_obj->message).request.url = estrndup(url_str, url_len);
                        PHP_HTTP_INFO(msg_obj->message).request.method = estrndup(meth_str, meth_len);
 
index 2050bf2..2a842b4 100644 (file)
@@ -86,11 +86,23 @@ PHP_METHOD(HttpClientRequest, __construct)
        with_error_handling(EH_THROW, php_http_exception_get_class_entry()) {
                if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!a!O!", &meth_str, &meth_len, &url_str, &url_len, &zheaders, &zbody, php_http_message_body_get_class_entry())) {
                        php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+                       php_http_message_body_object_t *body_obj = NULL;
+
+                       if (zbody) {
+                               body_obj = zend_object_store_get_object(zbody TSRMLS_CC);
+                               Z_OBJ_ADDREF_P(zbody);
+                               obj->body = Z_OBJVAL_P(zbody);
+                               php_http_message_body_addref(body_obj->body);
+                       }
 
                        if (obj->message) {
                                php_http_message_set_type(obj->message, PHP_HTTP_REQUEST);
+                               if (body_obj) {
+                                       php_http_message_body_free(&obj->message->body);
+                                       obj->message->body = body_obj->body;
+                               }
                        } else {
-                               obj->message = php_http_message_init(NULL, PHP_HTTP_REQUEST TSRMLS_CC);
+                               obj->message = php_http_message_init(NULL, PHP_HTTP_REQUEST, body_obj ? body_obj->body : NULL TSRMLS_CC);
                        }
 
                        if (meth_str && meth_len) {
@@ -102,14 +114,6 @@ PHP_METHOD(HttpClientRequest, __construct)
                        if (zheaders) {
                                array_copy(Z_ARRVAL_P(zheaders), &obj->message->hdrs);
                        }
-                       if (zbody) {
-                               php_http_message_body_object_t *body_obj = zend_object_store_get_object(zbody TSRMLS_CC);
-
-                               php_http_message_body_dtor(&obj->message->body);
-                               php_http_message_body_copy(body_obj->body, &obj->message->body, 0);
-                               Z_OBJ_ADDREF_P(zbody);
-                               obj->body = Z_OBJVAL_P(zbody);
-                       }
                }
        } end_error_handling();
 }
index 58f0d93..c0930db 100644 (file)
@@ -1211,16 +1211,16 @@ PHP_HTTP_API STATUS php_http_curl_client_prepare(php_http_client_t *h, php_http_
        }
 
        /* attach request body */
-       if ((body_size = php_http_message_body_size(&msg->body))) {
+       if ((body_size = php_http_message_body_size(msg->body))) {
                /* RFC2616, section 4.3 (para. 4) states that »a message-body MUST NOT be included in a request if the
                 * specification of the request method (section 5.1.1) does not allow sending an entity-body in request.«
                 * Following the clause in section 5.1.1 (para. 2) that request methods »MUST be implemented with the
                 * same semantics as those specified in section 9« reveal that not any single defined HTTP/1.1 method
                 * does not allow a request body.
                 */
-               php_stream_rewind(php_http_message_body_stream(&msg->body));
-               curl_easy_setopt(curl->handle, CURLOPT_IOCTLDATA, &msg->body);
-               curl_easy_setopt(curl->handle, CURLOPT_READDATA, &msg->body);
+               php_stream_rewind(php_http_message_body_stream(msg->body));
+               curl_easy_setopt(curl->handle, CURLOPT_IOCTLDATA, msg->body);
+               curl_easy_setopt(curl->handle, CURLOPT_READDATA, msg->body);
                curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE, body_size);
                curl_easy_setopt(curl->handle, CURLOPT_POSTFIELDSIZE, body_size);
        }
index 0aeb80d..c11e4fc 100644 (file)
@@ -813,7 +813,7 @@ PHP_METHOD(HttpEnv, getRequestBody)
                        zend_object_value ov;
                        php_http_message_body_t *body = php_http_env_get_request_body(TSRMLS_C);
 
-                       if (SUCCESS == php_http_new(&ov, class_entry, (php_http_new_t) php_http_message_body_object_new_ex, php_http_message_body_get_class_entry(), php_http_message_body_copy(body, NULL, 0), NULL TSRMLS_CC)) {
+                       if (SUCCESS == php_http_new(&ov, class_entry, (php_http_new_t) php_http_message_body_object_new_ex, php_http_message_body_get_class_entry(), php_http_message_body_init(&body, NULL TSRMLS_CC), NULL TSRMLS_CC)) {
                                RETVAL_OBJVAL(ov, 0);
                        }
                }
index 2f75eca..53af327 100644 (file)
@@ -363,7 +363,7 @@ static STATUS php_http_env_response_send_head(php_http_env_response_t *r, php_ht
 
        if ((zoption = get_option(options, ZEND_STRL("headers") TSRMLS_CC))) {
                if (Z_TYPE_P(zoption) == IS_ARRAY) {
-                       php_http_headers_to_callback(Z_ARRVAL_P(zoption), 0, r->ops->set_header, r TSRMLS_CC);
+                       php_http_headers_to_callback(Z_ARRVAL_P(zoption), 0, (php_http_pass_format_callback_t) r->ops->set_header, r TSRMLS_CC);
                }
                zval_ptr_dtor(&zoption);
        }
@@ -1158,8 +1158,8 @@ PHP_METHOD(HttpEnvResponse, __invoke)
        if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &ob_str, &ob_len, &ob_flags)) {
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
-               if (obj->body.handle || SUCCESS == php_http_new(&obj->body, php_http_message_body_get_class_entry(), (php_http_new_t) php_http_message_body_object_new_ex, NULL, (void *) php_http_message_body_copy(&obj->message->body, NULL, 0), NULL TSRMLS_CC)) {
-                       php_http_message_body_append(&obj->message->body, ob_str, ob_len);
+               if (obj->body.handle || SUCCESS == php_http_new(&obj->body, php_http_message_body_get_class_entry(), (php_http_new_t) php_http_message_body_object_new_ex, NULL, (void *) php_http_message_body_init(&obj->message->body, NULL TSRMLS_CC), NULL TSRMLS_CC)) {
+                       php_http_message_body_append(obj->message->body, ob_str, ob_len);
                        RETURN_TRUE;
                }
                RETURN_FALSE;
index 71edefd..519eb7a 100644 (file)
@@ -82,7 +82,7 @@ PHP_HTTP_API void php_http_headers_to_callback(HashTable *headers, zend_bool crl
 
 PHP_HTTP_API void php_http_headers_to_string(php_http_buffer_t *str, HashTable *headers TSRMLS_DC)
 {
-       php_http_headers_to_callback(headers, 1, php_http_buffer_appendf, str TSRMLS_CC);
+       php_http_headers_to_callback(headers, 1, (php_http_pass_format_callback_t) php_http_buffer_appendf, str TSRMLS_CC);
 }
 
 PHP_HTTP_API zval *php_http_header_value_to_string(zval *header TSRMLS_DC)
index d063b21..c0e60f2 100644 (file)
@@ -20,7 +20,7 @@ PHP_HTTP_API zend_bool php_http_message_info_callback(php_http_message_t **messa
 
        /* advance message */
        if (!old || old->type || zend_hash_num_elements(&old->hdrs)) {
-               (*message) = php_http_message_init(NULL, 0 TSRMLS_CC);
+               (*message) = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                (*message)->parent = old;
                if (headers) {
                        (*headers) = &((*message)->hdrs);
@@ -34,7 +34,7 @@ PHP_HTTP_API zend_bool php_http_message_info_callback(php_http_message_t **messa
        return old != *message;
 }
 
-PHP_HTTP_API php_http_message_t *php_http_message_init(php_http_message_t *message, php_http_message_type_t type TSRMLS_DC)
+PHP_HTTP_API php_http_message_t *php_http_message_init(php_http_message_t *message, php_http_message_type_t type, php_http_message_body_t *body TSRMLS_DC)
 {
        if (!message) {
                message = emalloc(sizeof(*message));
@@ -46,7 +46,7 @@ PHP_HTTP_API php_http_message_t *php_http_message_init(php_http_message_t *messa
        message->http.version.major = 1;
        message->http.version.minor = 1;
        zend_hash_init(&message->hdrs, 0, NULL, ZVAL_PTR_DTOR, 0);
-       php_http_message_body_init(&message->body, NULL TSRMLS_CC);
+       message->body = body ? body : php_http_message_body_init(NULL, NULL TSRMLS_CC);
 
        return message;
 }
@@ -57,10 +57,11 @@ PHP_HTTP_API php_http_message_t *php_http_message_init_env(php_http_message_t *m
        zval *sval, tval;
        php_http_message_body_t *mbody;
        
-       message = php_http_message_init(message, type TSRMLS_CC);
-       
        switch (type) {
                case PHP_HTTP_REQUEST:
+                       mbody = php_http_env_get_request_body(TSRMLS_C);
+                       php_http_message_body_addref(mbody);
+                       message = php_http_message_init(message, type, mbody TSRMLS_CC);
                        if ((sval = php_http_env_get_server_var(ZEND_STRL("SERVER_PROTOCOL"), 1 TSRMLS_CC)) && !strncmp(Z_STRVAL_P(sval), "HTTP/", lenof("HTTP/"))) {
                                php_http_version_parse(&message->http.version, Z_STRVAL_P(sval) TSRMLS_CC);
                        }
@@ -72,14 +73,10 @@ PHP_HTTP_API php_http_message_t *php_http_message_init_env(php_http_message_t *m
                        }
                        
                        php_http_env_get_request_headers(&message->hdrs TSRMLS_CC);
-
-                       if ((mbody = php_http_env_get_request_body(TSRMLS_C))) {
-                               php_http_message_body_dtor(&message->body);
-                               php_http_message_body_copy(mbody, &message->body, 0);
-                       }
                        break;
                        
                case PHP_HTTP_RESPONSE:
+                       message = php_http_message_init(NULL, type, NULL TSRMLS_CC);
                        if (!SG(sapi_headers).http_status_line || !php_http_info_parse((php_http_info_t *) &message->http, SG(sapi_headers).http_status_line TSRMLS_CC)) {
                                if (!(message->http.info.response.code = SG(sapi_headers).http_response_code)) {
                                        message->http.info.response.code = 200;
@@ -97,7 +94,7 @@ PHP_HTTP_API php_http_message_t *php_http_message_init_env(php_http_message_t *m
                                        php_http_error(HE_WARNING, PHP_HTTP_E_RUNTIME, "Could not fetch response body");
                                        goto error;
                                } else {
-                                       php_http_message_body_append(&message->body, Z_STRVAL(tval), Z_STRLEN(tval));
+                                       php_http_message_body_append(message->body, Z_STRVAL(tval), Z_STRLEN(tval));
                                        zval_dtor(&tval);
                                }
                        }
@@ -107,7 +104,9 @@ PHP_HTTP_API php_http_message_t *php_http_message_init_env(php_http_message_t *m
                default:
                error:
                        if (free_msg) {
-                               php_http_message_free(&message);
+                               if (message) {
+                                       php_http_message_free(&message);
+                               }
                        } else {
                                message = NULL;
                        }
@@ -128,7 +127,7 @@ PHP_HTTP_API php_http_message_t *php_http_message_parse(php_http_message_t *msg,
        php_http_message_parser_init(&p TSRMLS_CC);
 
        if ((free_msg = !msg)) {
-               msg = php_http_message_init(NULL, 0 TSRMLS_CC);
+               msg = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
        }
 
        if (greedy) {
@@ -277,25 +276,25 @@ PHP_HTTP_API void php_http_message_update_headers(php_http_message_t *msg)
        zval *h;
        size_t size;
 
-       if (php_http_message_body_stream(&msg->body)->readfilters.head) {
+       if (php_http_message_body_stream(msg->body)->readfilters.head) {
                /* if a read stream filter is attached to the body the caller must also care for the headers */
-       } else if ((size = php_http_message_body_size(&msg->body))) {
+       } else if ((size = php_http_message_body_size(msg->body))) {
                MAKE_STD_ZVAL(h);
                ZVAL_LONG(h, size);
                zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), &h, sizeof(zval *), NULL);
 
-               if (msg->body.boundary) {
+               if (msg->body->boundary) {
                        char *str;
                        size_t len;
 
                        if (!(h = php_http_message_header(msg, ZEND_STRL("Content-Type"), 1))) {
-                               len = spprintf(&str, 0, "multipart/form-data; boundary=\"%s\"", msg->body.boundary);
+                               len = spprintf(&str, 0, "multipart/form-data; boundary=\"%s\"", msg->body->boundary);
                                MAKE_STD_ZVAL(h);
                                ZVAL_STRINGL(h, str, len, 0);
                                zend_hash_update(&msg->hdrs, "Content-Type", sizeof("Content-Type"), &h, sizeof(zval *), NULL);
                        } else if (!php_http_match(Z_STRVAL_P(h), "boundary=", PHP_HTTP_MATCH_WORD)) {
                                zval_dtor(h);
-                               Z_STRLEN_P(h) = spprintf(&Z_STRVAL_P(h), 0, "%s; boundary=\"%s\"", Z_STRVAL_P(h), msg->body.boundary);
+                               Z_STRLEN_P(h) = spprintf(&Z_STRVAL_P(h), 0, "%s; boundary=\"%s\"", Z_STRVAL_P(h), msg->body->boundary);
                                zend_hash_update(&msg->hdrs, "Content-Type", sizeof("Content-Type"), &h, sizeof(zval *), NULL);
                        } else {
                                zval_ptr_dtor(&h);
@@ -334,9 +333,9 @@ PHP_HTTP_API void php_http_message_to_callback(php_http_message_t *msg, php_http
        cb(cb_arg, str.data, str.used);
        php_http_buffer_dtor(&str);
 
-       if (php_http_message_body_size(&msg->body)) {
+       if (php_http_message_body_size(msg->body)) {
                cb(cb_arg, ZEND_STRL(PHP_HTTP_CRLF));
-               php_http_message_body_to_callback(&msg->body, cb, cb_arg, 0, 0);
+               php_http_message_body_to_callback(msg->body, cb, cb_arg, 0, 0);
        }
 }
 
@@ -347,9 +346,9 @@ PHP_HTTP_API void php_http_message_to_string(php_http_message_t *msg, char **str
 
        php_http_buffer_init_ex(&str, 0x1000, 0);
        message_headers(msg, &str);
-       if (php_http_message_body_size(&msg->body)) {
+       if (php_http_message_body_size(msg->body)) {
                php_http_buffer_appends(&str, PHP_HTTP_CRLF);
-               php_http_message_body_to_callback(&msg->body, (php_http_pass_callback_t) php_http_buffer_append, &str, 0, 0);
+               php_http_message_body_to_callback(msg->body, (php_http_pass_callback_t) php_http_buffer_append, &str, 0, 0);
        }
 
        data = php_http_buffer_data(&str, string, length);
@@ -437,19 +436,17 @@ PHP_HTTP_API php_http_message_t *php_http_message_copy_ex(php_http_message_t *fr
                info.type = from->type;
                info.http = from->http;
                
-               copy = temp = php_http_message_init(to, 0 TSRMLS_CC);
+               copy = temp = php_http_message_init(to, 0, php_http_message_body_copy(from->body, NULL) TSRMLS_CC);
                php_http_message_set_info(temp, &info);
                zend_hash_copy(&temp->hdrs, &from->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
-               php_http_message_body_copy(&from->body, &temp->body, 1);
        
                if (parents) while (from->parent) {
                        info.type = from->parent->type;
                        info.http = from->parent->http;
                
-                       temp->parent = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       temp->parent = php_http_message_init(NULL, 0, php_http_message_body_copy(from->parent->body, NULL) TSRMLS_CC);
                        php_http_message_set_info(temp->parent, &info);
                        zend_hash_copy(&temp->parent->hdrs, &from->parent->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
-                       php_http_message_body_copy(&from->parent->body, &temp->parent->body, 1);
                
                        temp = temp->parent;
                        from = from->parent;
@@ -468,7 +465,7 @@ PHP_HTTP_API void php_http_message_dtor(php_http_message_t *message)
 {
        if (message) {
                zend_hash_destroy(&message->hdrs);
-               php_http_message_body_dtor(&message->body);
+               php_http_message_body_free(&message->body);
                
                switch (message->type) {
                        case PHP_HTTP_REQUEST:
@@ -1001,16 +998,12 @@ STATUS php_http_message_object_set_body(php_http_message_object_t *msg_obj, zval
 
        if (msg_obj->body.handle) {
                zend_objects_store_del_ref_by_handle(msg_obj->body.handle TSRMLS_CC);
-               php_http_message_body_dtor(&msg_obj->message->body);
        }
+       php_http_message_body_free(&msg_obj->message->body);
 
-       php_http_message_body_copy(body_obj->body, &msg_obj->message->body, 0);
+       msg_obj->message->body = php_http_message_body_init(&body_obj->body, NULL TSRMLS_CC);
        msg_obj->body = Z_OBJVAL_P(zbody);
 
-       if (tmp) {
-               zval_ptr_dtor(&tmp);
-       }
-
        return SUCCESS;
 }
 
@@ -1033,14 +1026,11 @@ zend_object_value php_http_message_object_new_ex(zend_class_entry *ce, php_http_
        }
 
        if (msg) {
-               php_http_message_body_object_t *body_obj;
-
                o->message = msg;
                if (msg->parent) {
                        o->parent = php_http_message_object_new_ex(ce, msg->parent, NULL TSRMLS_CC);
                }
-               o->body = php_http_message_body_object_new_ex(php_http_message_body_get_class_entry(), &msg->body, &body_obj TSRMLS_CC);
-               body_obj->shared = 1;
+               o->body = php_http_message_body_object_new_ex(php_http_message_body_get_class_entry(), php_http_message_body_init(&msg->body, NULL TSRMLS_CC), NULL TSRMLS_CC);
        }
 
        ov.handle = zend_objects_store_put((zend_object *) o, NULL, php_http_message_object_free, NULL TSRMLS_CC);
@@ -1206,7 +1196,7 @@ static HashTable *php_http_message_object_get_props(zval *object TSRMLS_DC)
 
        MAKE_STD_ZVAL(body);
        if (!obj->body.handle) {
-               php_http_new(&obj->body, php_http_message_body_get_class_entry(), (php_http_new_t) php_http_message_body_object_new_ex, NULL, (void *) php_http_message_body_copy(&obj->message->body, NULL, 0), NULL TSRMLS_CC);
+               php_http_new(&obj->body, php_http_message_body_get_class_entry(), (php_http_new_t) php_http_message_body_object_new_ex, NULL, (void *) php_http_message_body_init(&obj->message->body, NULL TSRMLS_CC), NULL TSRMLS_CC);
        }
        ZVAL_OBJVAL(body, obj->body, 1);
        ASSOC_PROP(array, zval, "body", body);
@@ -1265,7 +1255,7 @@ PHP_METHOD(HttpMessage, __construct)
                        }
                }
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
        } end_error_handling();
 
@@ -1278,12 +1268,11 @@ PHP_METHOD(HttpMessage, getBody)
                        php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                        if (!obj->message) {
-                               obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                               obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                        }
                        if (!obj->body.handle) {
-                               php_http_message_body_object_t *body_obj;
-                               obj->body = php_http_message_body_object_new_ex(php_http_message_body_get_class_entry(), &obj->message->body, &body_obj TSRMLS_CC);
-                               body_obj->shared = 1;
+                               php_http_message_body_addref(obj->message->body);
+                               php_http_new(&obj->body, php_http_message_body_get_class_entry(), (php_http_new_t) php_http_message_body_object_new_ex, NULL, obj->message->body, NULL TSRMLS_CC);
                        }
                        if (obj->body.handle) {
                                RETVAL_OBJVAL(obj->body, 1);
@@ -1300,7 +1289,7 @@ PHP_METHOD(HttpMessage, setBody)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
                php_http_message_object_prophandler_set_body(obj, zbody TSRMLS_CC);
        }
@@ -1315,7 +1304,7 @@ PHP_METHOD(HttpMessage, addBody)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
                php_http_message_body_object_t *new_obj = zend_object_store_get_object(new_body TSRMLS_CC);
 
-               php_http_message_body_to_callback(new_obj->body, (php_http_pass_callback_t) php_http_message_body_append, &obj->message->body, 0, 0);
+               php_http_message_body_to_callback(new_obj->body, (php_http_pass_callback_t) php_http_message_body_append, obj->message->body, 0, 0);
        }
        RETVAL_ZVAL(getThis(), 1, 0);
 }
@@ -1331,7 +1320,7 @@ PHP_METHOD(HttpMessage, getHeader)
                zval *header;
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                if ((header = php_http_message_header(obj->message, header_str, header_len, 0))) {
@@ -1347,7 +1336,7 @@ PHP_METHOD(HttpMessage, getHeaders)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                array_init(return_value);
@@ -1366,7 +1355,7 @@ PHP_METHOD(HttpMessage, setHeader)
                char *name = php_http_pretty_key(estrndup(name_str, name_len), name_len, 1, 1);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                if (!zvalue) {
@@ -1388,7 +1377,7 @@ PHP_METHOD(HttpMessage, setHeaders)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                zend_hash_clean(&obj->message->hdrs);
@@ -1411,7 +1400,7 @@ PHP_METHOD(HttpMessage, addHeader)
                zval *header;
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                Z_ADDREF_P(zvalue);
@@ -1436,7 +1425,7 @@ PHP_METHOD(HttpMessage, addHeaders)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                array_join(Z_ARRVAL_P(new_headers), &obj->message->hdrs, append, ARRAY_JOIN_STRONLY|ARRAY_JOIN_PRETTIFY);
@@ -1450,7 +1439,7 @@ PHP_METHOD(HttpMessage, getType)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                RETURN_LONG(obj->message->type);
@@ -1465,7 +1454,7 @@ PHP_METHOD(HttpMessage, setType)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                php_http_message_set_type(obj->message, type);
@@ -1479,7 +1468,7 @@ PHP_METHOD(HttpMessage, getInfo)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                switch (obj->message->type) {
@@ -1510,7 +1499,7 @@ PHP_METHOD(HttpMessage, setInfo)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                php_http_message_set_info(obj->message, &inf);
@@ -1527,7 +1516,7 @@ PHP_METHOD(HttpMessage, getHttpVersion)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                php_http_version_to_string(&obj->message->http.version, &str, &len, NULL, NULL TSRMLS_CC);
@@ -1547,7 +1536,7 @@ PHP_METHOD(HttpMessage, setHttpVersion)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                if (php_http_version_parse(&version, v_str TSRMLS_CC)) {
@@ -1563,7 +1552,7 @@ PHP_METHOD(HttpMessage, getResponseCode)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                PHP_HTTP_MESSAGE_TYPE_CHECK(RESPONSE, obj->message, RETURN_FALSE);
@@ -1581,7 +1570,7 @@ PHP_METHOD(HttpMessage, setResponseCode)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                PHP_HTTP_MESSAGE_TYPE_CHECK(RESPONSE, obj->message, RETURN_FALSE);
@@ -1602,7 +1591,7 @@ PHP_METHOD(HttpMessage, getResponseStatus)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                PHP_HTTP_MESSAGE_TYPE_CHECK(RESPONSE, obj->message, RETURN_FALSE);
@@ -1625,7 +1614,7 @@ PHP_METHOD(HttpMessage, setResponseStatus)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                PHP_HTTP_MESSAGE_TYPE_CHECK(RESPONSE, obj->message, RETURN_FALSE);
@@ -1640,7 +1629,7 @@ PHP_METHOD(HttpMessage, getRequestMethod)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                PHP_HTTP_MESSAGE_TYPE_CHECK(REQUEST, obj->message, RETURN_FALSE);
@@ -1663,7 +1652,7 @@ PHP_METHOD(HttpMessage, setRequestMethod)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                PHP_HTTP_MESSAGE_TYPE_CHECK(REQUEST, obj->message, RETURN_FALSE);
@@ -1683,7 +1672,7 @@ PHP_METHOD(HttpMessage, getRequestUrl)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                PHP_HTTP_MESSAGE_TYPE_CHECK(REQUEST, obj->message, RETURN_FALSE);
@@ -1706,7 +1695,7 @@ PHP_METHOD(HttpMessage, setRequestUrl)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                PHP_HTTP_MESSAGE_TYPE_CHECK(REQUEST, obj->message, RETURN_FALSE);
@@ -1727,7 +1716,7 @@ PHP_METHOD(HttpMessage, getParentMessage)
                        php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                        if (!obj->message) {
-                               obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                               obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                        }
 
                        if (obj->message->parent) {
@@ -1749,7 +1738,7 @@ PHP_METHOD(HttpMessage, toString)
                size_t length;
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                if (include_parent) {
@@ -1775,7 +1764,7 @@ PHP_METHOD(HttpMessage, toStream)
                php_stream_from_zval(s, &zstream);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                php_http_message_to_callback(obj->message, (php_http_pass_callback_t) _php_stream_write, s);
@@ -1810,7 +1799,7 @@ PHP_METHOD(HttpMessage, serialize)
                size_t length;
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                php_http_message_serialize(obj->message, &string, &length);
@@ -1835,7 +1824,7 @@ PHP_METHOD(HttpMessage, unserialize)
                if ((msg = php_http_message_parse(NULL, serialized, (size_t) length, 1 TSRMLS_CC))) {
                        obj->message = msg;
                } else {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                        php_http_error(HE_ERROR, PHP_HTTP_E_RUNTIME, "Could not unserialize HttpMessage");
                }
        }
@@ -1848,7 +1837,7 @@ PHP_METHOD(HttpMessage, detach)
                        php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                        if (!obj->message) {
-                               obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                               obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                        }
 
                        RETVAL_OBJVAL(php_http_message_object_new_ex(obj->zo.ce, php_http_message_copy_ex(obj->message, NULL, 0), NULL TSRMLS_CC), 0);
@@ -1867,10 +1856,10 @@ PHP_METHOD(HttpMessage, prepend)
                php_http_message_object_t *prepend_obj = zend_object_store_get_object(prepend TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
                if (!prepend_obj->message) {
-                       prepend_obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       prepend_obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                /* safety check */
@@ -1920,7 +1909,7 @@ PHP_METHOD(HttpMessage, splitMultipartBody)
                if (php_http_message_is_multipart(obj->message, &boundary)) {
                        php_http_message_t *msg;
 
-                       if ((msg = php_http_message_body_split(&obj->message->body, boundary))) {
+                       if ((msg = php_http_message_body_split(obj->message->body, boundary))) {
                                RETVAL_OBJVAL(php_http_message_object_new_ex(php_http_message_class_entry, msg, NULL TSRMLS_CC), 0);
                        }
                }
@@ -1935,7 +1924,7 @@ PHP_METHOD(HttpMessage, count)
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->message) {
-                       obj->message = php_http_message_init(NULL, 0 TSRMLS_CC);
+                       obj->message = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                }
 
                php_http_message_count(i, obj->message);
index cb4c116..4ba9619 100644 (file)
@@ -30,7 +30,7 @@ typedef struct php_http_message php_http_message_t;
 struct php_http_message {
        PHP_HTTP_INFO_IMPL(http, type)
        HashTable hdrs;
-       php_http_message_body_t body;
+       php_http_message_body_t *body;
        php_http_message_t *parent;
        void *opaque;
 #ifdef ZTS
@@ -40,7 +40,7 @@ struct php_http_message {
 
 PHP_HTTP_API zend_bool php_http_message_info_callback(php_http_message_t **message, HashTable **headers, php_http_info_t *info TSRMLS_DC);
 
-PHP_HTTP_API php_http_message_t *php_http_message_init(php_http_message_t *m, php_http_message_type_t t TSRMLS_DC);
+PHP_HTTP_API php_http_message_t *php_http_message_init(php_http_message_t *m, php_http_message_type_t t, php_http_message_body_t *body TSRMLS_DC);
 PHP_HTTP_API php_http_message_t *php_http_message_init_env(php_http_message_t *m, php_http_message_type_t t TSRMLS_DC);
 PHP_HTTP_API php_http_message_t *php_http_message_copy(php_http_message_t *from, php_http_message_t *to);
 PHP_HTTP_API php_http_message_t *php_http_message_copy_ex(php_http_message_t *from, php_http_message_t *to, zend_bool parents);
index 45fe95e..b2fe399 100644 (file)
 static STATUS add_recursive_fields(php_http_message_body_t *body, const char *name, zval *value);
 static STATUS add_recursive_files(php_http_message_body_t *body, const char *name, zval *value);
 
-PHP_HTTP_API php_http_message_body_t *php_http_message_body_init(php_http_message_body_t *body, php_stream *stream TSRMLS_DC)
+PHP_HTTP_API php_http_message_body_t *php_http_message_body_init(php_http_message_body_t **body_ptr, php_stream *stream TSRMLS_DC)
 {
-       if (!body) {
-               body = emalloc(sizeof(php_http_message_body_t));
+       php_http_message_body_t *body;
+
+       if (body_ptr && *body_ptr) {
+               body = *body_ptr;
+               ++body->refcount;
+               return body;
        }
-       memset(body, 0, sizeof(*body));
        
+       body = ecalloc(1, sizeof(php_http_message_body_t));
+       body->refcount = 1;
+
        if (stream) {
                php_stream_auto_cleanup(stream);
                body->stream_id = php_stream_get_resource_id(stream);
@@ -51,42 +57,48 @@ PHP_HTTP_API php_http_message_body_t *php_http_message_body_init(php_http_messag
        return body;
 }
 
-PHP_HTTP_API php_http_message_body_t *php_http_message_body_copy(php_http_message_body_t *from, php_http_message_body_t *to, zend_bool dup_internal_stream_and_contents)
+PHP_HTTP_API unsigned php_http_message_body_addref(php_http_message_body_t *body)
 {
-       if (!from) {
-               return NULL;
-       } else {
+       return ++body->refcount;
+}
+
+PHP_HTTP_API php_http_message_body_t *php_http_message_body_copy(php_http_message_body_t *from, php_http_message_body_t *to)
+{
+       if (from) {
                TSRMLS_FETCH_FROM_CTX(from->ts);
                
-               if (dup_internal_stream_and_contents) {
-                       to = php_http_message_body_init(to, NULL TSRMLS_CC);
-                       php_http_message_body_to_stream(from, php_http_message_body_stream(to), 0, 0);
+               if (to) {
+                       php_stream_truncate_set_size(php_http_message_body_stream(to), 0);
                } else {
-                       to = php_http_message_body_init(to, php_http_message_body_stream(from) TSRMLS_CC);
+                       to = php_http_message_body_init(NULL, NULL TSRMLS_CC);
                }
+               php_http_message_body_to_stream(from, php_http_message_body_stream(to), 0, 0);
 
+               if (to->boundary) {
+                       efree(to->boundary);
+               }
                if (from->boundary) {
                        to->boundary = estrdup(from->boundary);
                }
-
-               return to;
+       } else {
+               to = NULL;
        }
+       return to;
 }
 
-PHP_HTTP_API void php_http_message_body_dtor(php_http_message_body_t *body)
+PHP_HTTP_API void php_http_message_body_free(php_http_message_body_t **body_ptr)
 {
-       TSRMLS_FETCH_FROM_CTX(body->ts);
-       /* NO FIXME: shows leakinfo in DEBUG mode */
-       zend_list_delete(body->stream_id);
-       STR_FREE(body->boundary);
-}
+       if (*body_ptr) {
+               php_http_message_body_t *body = *body_ptr;
 
-PHP_HTTP_API void php_http_message_body_free(php_http_message_body_t **body)
-{
-       if (*body) {
-               php_http_message_body_dtor(*body);
-               efree(*body);
-               *body = NULL;
+               if (!--body->refcount) {
+                       TSRMLS_FETCH_FROM_CTX(body->ts);
+                       /* NO FIXME: shows leakinfo in DEBUG mode */
+                       zend_list_delete(body->stream_id);
+                       STR_FREE(body->boundary);
+                       efree(body);
+               }
+               *body_ptr = NULL;
        }
 }
 
@@ -468,7 +480,7 @@ static size_t splitbody(void *opaque, char *buf, size_t len TSRMLS_DC)
                                        /* advance messages */
                                        php_http_message_t *msg;
 
-                                       msg = php_http_message_init(NULL, 0 TSRMLS_CC);
+                                       msg = php_http_message_init(NULL, 0, NULL TSRMLS_CC);
                                        msg->parent = arg->parser->message;
                                        arg->parser->message = msg;
                                }
@@ -639,8 +651,9 @@ zend_object_value php_http_message_body_object_clone(zval *object TSRMLS_DC)
        zend_object_value new_ov;
        php_http_message_body_object_t *new_obj = NULL;
        php_http_message_body_object_t *old_obj = zend_object_store_get_object(object TSRMLS_CC);
+       php_http_message_body_t *body = php_http_message_body_copy(old_obj->body, NULL);
 
-       new_ov = php_http_message_body_object_new_ex(old_obj->zo.ce, php_http_message_body_copy(old_obj->body, NULL, 1), &new_obj TSRMLS_CC);
+       new_ov = php_http_message_body_object_new_ex(old_obj->zo.ce, body, &new_obj TSRMLS_CC);
        zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(object) TSRMLS_CC);
 
        return new_ov;
@@ -669,10 +682,10 @@ PHP_METHOD(HttpMessageBody, __construct)
                                php_stream_from_zval(stream, &zstream);
 
                                if (stream) {
-                                       if (obj->body && !obj->shared) {
-                                               php_http_message_body_dtor(obj->body);
+                                       if (obj->body) {
+                                               php_http_message_body_free(&obj->body);
                                        }
-                                       obj->body = php_http_message_body_init(obj->body, stream TSRMLS_CC);
+                                       obj->body = php_http_message_body_init(NULL, stream TSRMLS_CC);
                                }
                        }
                        if (!obj->body) {
index 1e6f4ea..55016b7 100644 (file)
@@ -17,6 +17,7 @@ typedef struct php_http_message_body {
        int stream_id;
        php_stream_statbuf ssb;
        char *boundary;
+       unsigned refcount;
 #ifdef ZTS
        void ***ts;
 #endif
@@ -24,8 +25,9 @@ typedef struct php_http_message_body {
 
 struct php_http_message;
 
-PHP_HTTP_API php_http_message_body_t *php_http_message_body_init(php_http_message_body_t *body, php_stream *stream TSRMLS_DC);
-PHP_HTTP_API php_http_message_body_t *php_http_message_body_copy(php_http_message_body_t *from, php_http_message_body_t *to, zend_bool dup_internal_stream_and_contents);
+PHP_HTTP_API php_http_message_body_t *php_http_message_body_init(php_http_message_body_t **body, php_stream *stream TSRMLS_DC);
+PHP_HTTP_API unsigned php_http_message_body_addref(php_http_message_body_t *body);
+PHP_HTTP_API php_http_message_body_t *php_http_message_body_copy(php_http_message_body_t *from, php_http_message_body_t *to);
 PHP_HTTP_API STATUS php_http_message_body_add_form(php_http_message_body_t *body, HashTable *fields, HashTable *files);
 PHP_HTTP_API STATUS php_http_message_body_add_form_field(php_http_message_body_t *body, const char *name, const char *value_str, size_t value_len);
 PHP_HTTP_API STATUS php_http_message_body_add_form_file(php_http_message_body_t *body, const char *name, const char *ctype, const char *file, php_stream *stream);
@@ -35,7 +37,6 @@ PHP_HTTP_API size_t php_http_message_body_appendf(php_http_message_body_t *body,
 PHP_HTTP_API void php_http_message_body_to_string(php_http_message_body_t *body, char **buf, size_t *len, off_t offset, size_t forlen);
 PHP_HTTP_API void php_http_message_body_to_stream(php_http_message_body_t *body, php_stream *s, off_t offset, size_t forlen);
 PHP_HTTP_API void php_http_message_body_to_callback(php_http_message_body_t *body, php_http_pass_callback_t cb, void *cb_arg, off_t offset, size_t forlen);
-PHP_HTTP_API void php_http_message_body_dtor(php_http_message_body_t *body);
 PHP_HTTP_API void php_http_message_body_free(php_http_message_body_t **body);
 PHP_HTTP_API const php_stream_statbuf *php_http_message_body_stat(php_http_message_body_t *body);
 #define php_http_message_body_size(b) (php_http_message_body_stat((b))->sb.st_size)
index 3e46674..5d80766 100644 (file)
@@ -393,11 +393,11 @@ PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse(php_h
                                                len = dec_len;
                                        }
 
-                                       php_stream_write(php_http_message_body_stream(&(*message)->body), str, len);
+                                       php_stream_write(php_http_message_body_stream((*message)->body), str, len);
 
                                        /* keep track */
                                        MAKE_STD_ZVAL(zcl);
-                                       ZVAL_LONG(zcl, php_http_message_body_size(&(*message)->body));
+                                       ZVAL_LONG(zcl, php_http_message_body_size((*message)->body));
                                        zend_hash_update(&(*message)->hdrs, "Content-Length", sizeof("Content-Length"), &zcl, sizeof(zval *), NULL);
                                }
 
index cc0f421..1764ef6 100644 (file)
@@ -124,4 +124,11 @@ class MessageBodyTest extends PHPUnit_Framework_TestCase {
     function testClone() {
         $this->assertEquals((string) $this->file, (string) clone $this->file);
     }
+    
+    function testGetResource() {
+       $stream = $this->file->getResource();
+       $this->assertTrue(is_resource($stream));
+       $stat = fstat($stream);
+       $this->assertEquals(filesize(__FILE__), $stat["size"]);
+    }
 }
index 6dd5b70..485d431 100644 (file)
@@ -46,6 +46,13 @@ class MessageTest extends PHPUnit_Framework_TestCase
                $test->testSetBody($body);
                $this->assertEquals($body, $test->testGetBody());
                $this->assertEquals($body, $test->getBody());
+               $file = fopen(__FILE__,"r");
+               $test->testSetBody($file);
+               $this->assertEquals($file, $test->testGetBody()->getResource());
+               $this->assertEquals($file, $test->getBody()->getResource());
+               $test->testSetBody("data");
+               $this->assertEquals("data", (string) $test->testGetBody());
+               $this->assertEquals("data", (string) $test->getBody());
                $test->testSetRequestMethod("HEAD");
                $this->assertEquals("HEAD", $test->testGetRequestMethod());
                $this->assertEquals("HEAD", $test->getRequestMethod());
@@ -195,6 +202,25 @@ class MessageTest extends PHPUnit_Framework_TestCase
                );
        }
        
+       function testEmptyUrlWarning() {
+               $m = new http\Message;
+               $this->setExpectedException("PHPUnit_Framework_Error_Warning");
+               $m->setRequestUrl("/foo");
+               $m->setType(http\Message::TYPE_REQUEST);
+               $this->setExpectedException("PHPUnit_Framework_Error_Warning");
+               $m->setRequestUrl("");
+       }
+       
+       function testEmptyParentMessage() {
+               $m = new http\Message;
+               try {
+                       $m->getParentMessage();
+                       $this->assertFalse("this code should not be reached");
+               } catch (http\Exception $e) {
+                       $this->assertEquals("HttpMessage does not have a parent message", $e->getMessage());
+               }
+       }
+       
        function testPrependError() {
                $m = new http\Message("HTTP/1.1 200\r\nHTTP/1.1 201");
                try {
@@ -240,7 +266,7 @@ class MessageTest extends PHPUnit_Framework_TestCase
                $m->getBody()->addPart($p);
                $this->assertStringMatchesFormat(
                        "HTTP/1.1 200\r\n".
-                       "Content-Length: 97\r\n".
+                       "Content-Length: %d\r\n".
                        "Content-Type: multipart/form-data; boundary=\"%x.%x\"\r\n".
                        "\r\n".
                        "--%x.%x\r\n".