+
+ if (decoded) {
+ zval *len, **original_len;
+ char *tmp;
+ int tmp_len;
+
+ tmp_len = (int) spprintf(&tmp, 0, "%zu", decoded_len);
+ MAKE_STD_ZVAL(len);
+ ZVAL_STRINGL(len, tmp, tmp_len, 0);
+
+ ZVAL_ADDREF(c);
+ zend_hash_update(&msg->hdrs, "X-Original-Content-Encoding", sizeof("X-Original-Content-Encoding"), (void *) &c, sizeof(zval *), NULL);
+ zend_hash_del(&msg->hdrs, "Content-Encoding", sizeof("Content-Encoding"));
+ if (SUCCESS == zend_hash_find(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &original_len)) {
+ ZVAL_ADDREF(*original_len);
+ zend_hash_update(&msg->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), (void *) original_len, sizeof(zval *), NULL);
+ zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
+ } else {
+ zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
+ }
+
+ phpstr_dtor(PHPSTR(msg));
+ PHPSTR(msg)->data = decoded;
+ PHPSTR(msg)->used = decoded_len;
+ PHPSTR(msg)->free = 1;
+ }
+
+ zval_ptr_dtor(&c);
+ }
+ }
+#endif /* HTTP_HAVE_ZLIB */
+ }
+}
+
+PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, const char *message, size_t message_length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
+{
+ const char *continue_at;
+ zend_bool free_msg = msg ? 0 : 1;
+
+ if ((!message) || (message_length < HTTP_MSG_MIN_SIZE)) {
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Empty or too short HTTP message: '%s'", message);
+ return NULL;
+ }
+
+ msg = http_message_init_rel(msg, 0);
+
+ if (SUCCESS != http_parse_headers_cb(message, &msg->hdrs, 1, (http_info_callback) http_message_info_callback, (void *) &msg)) {
+ if (free_msg) {
+ http_message_free(&msg);
+ }
+ http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse message headers");
+ return NULL;
+ }
+
+ http_message_body_parse(msg, message, message_length, &continue_at);
+
+ /* check for following messages */
+ if (continue_at && (continue_at < (message + message_length))) {
+ while (HTTP_IS_CTYPE(space, *continue_at)) ++continue_at;
+ if (continue_at < (message + message_length)) {
+ http_message *next = NULL, *most = NULL;
+
+ /* set current message to parent of most parent following messages and return deepest */
+ if ((most = next = http_message_parse_rel(NULL, continue_at, message + message_length - continue_at))) {
+ while (most->parent) most = most->parent;
+ most->parent = msg;
+ msg = next;