{PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH, 1},
{PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED, 1},
{PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE, 0},
+ {PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL, 0},
{PHP_HTTP_MESSAGE_PARSER_STATE_DONE, 0}
};
#if DBG_PARSER
const char *php_http_message_parser_state_name(php_http_message_parser_state_t state) {
- const char *states[] = {"START", "HEADER", "HEADER_DONE", "BODY", "BODY_DUMB", "BODY_LENGTH", "BODY_CHUNK", "BODY_DONE", "DONE"};
+ const char *states[] = {"START", "HEADER", "HEADER_DONE", "BODY", "BODY_DUMB", "BODY_LENGTH", "BODY_CHUNK", "BODY_DONE", "UPDATE_CL", "DONE"};
if (state < 0 || state > (sizeof(states)/sizeof(char*))-1) {
return "FAILURE";
case PHP_HTTP_MESSAGE_PARSER_STATE_BODY:
case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:
+ case PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL:
/* should not occur */
abort();
break;
{
zval *h, *h_loc = NULL, *h_con = NULL, **h_cl = NULL, **h_cr = NULL, **h_te = NULL;
+ /* Content-Range has higher precedence than Content-Length,
+ * and content-length denotes the original length of the entity,
+ * so let's *NOT* remove CR/CL, because that would fundamentally
+ * change the meaning of the whole message
+ */
if ((h = php_http_message_header(*message, ZEND_STRL("Transfer-Encoding"), 1))) {
- zend_hash_update(&(*message)->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), &h, sizeof(zval *), (void *) &h_te);
+ zend_hash_update(&(*message)->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), (void *) &h, sizeof(zval *), (void *) &h_te);
zend_hash_del(&(*message)->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding"));
+
+ /* reset */
+ MAKE_STD_ZVAL(h);
+ ZVAL_LONG(h, 0);
+ zend_hash_update(&(*message)->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &h, sizeof(zval *), NULL);
+ } else if ((h = php_http_message_header(*message, ZEND_STRL("Content-Length"), 1))) {
+ zend_hash_update(&(*message)->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), (void *) &h, sizeof(zval *), (void *) &h_cl);
}
- if ((h = php_http_message_header(*message, ZEND_STRL("Content-Length"), 1))) {
- zend_hash_update(&(*message)->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), &h, sizeof(zval *), (void *) &h_cl);
- }
+
if ((h = php_http_message_header(*message, ZEND_STRL("Content-Range"), 1))) {
- zend_hash_update(&(*message)->hdrs, "X-Original-Content-Range", sizeof("X-Original-Content-Range"), &h, sizeof(zval *), (void *) &h_cr);
- zend_hash_del(&(*message)->hdrs, "Content-Range", sizeof("Content-Range"));
+ zend_hash_find(&(*message)->hdrs, ZEND_STRS("Content-Range"), (void *) &h_cr);
+ if (h != *h_cr) {
+ zend_hash_update(&(*message)->hdrs, "Content-Range", sizeof("Content-Range"), &h, sizeof(zval *), (void *) &h_cr);
+ } else {
+ zval_ptr_dtor(&h);
+ }
}
- /* default */
- MAKE_STD_ZVAL(h);
- ZVAL_LONG(h, 0);
- zend_hash_update(&(*message)->hdrs, "Content-Length", sizeof("Content-Length"), &h, sizeof(zval *), NULL);
-
/* so, if curl sees a 3xx code, a Location header and a Connection:close header
* it decides not to read the response body.
*/
case PHP_HTTP_MESSAGE_PARSER_STATE_BODY:
{
if (len) {
- zval *zcl;
-
+ /* FIXME: what if we re-use the parser? */
if (parser->inflate) {
char *dec_str = NULL;
size_t dec_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));
- zend_hash_update(&(*message)->hdrs, "Content-Length", sizeof("Content-Length"), &zcl, sizeof(zval *), NULL);
}
if (cut) {
{
php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
- if (parser->dechunk) {
+ if (parser->dechunk && parser->dechunk->ctx) {
char *dec_str = NULL;
size_t dec_len;
str = dec_str;
len = dec_len;
cut = 0;
- php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+ php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
}
}
break;
}
- case PHP_HTTP_MESSAGE_PARSER_STATE_DONE: {
+ case PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL:
+ {
+ zval *zcl;
+ MAKE_STD_ZVAL(zcl);
+ ZVAL_LONG(zcl, php_http_message_body_size((*message)->body));
+ zend_hash_update(&(*message)->hdrs, "Content-Length", sizeof("Content-Length"), &zcl, sizeof(zval *), NULL);
+ break;
+ }
+
+ case PHP_HTTP_MESSAGE_PARSER_STATE_DONE:
+ {
char *ptr = buffer->data;
while (ptr - buffer->data < buffer->used && PHP_HTTP_IS_CTYPE(space, *ptr)) {
["Accept-Ranges"]=>
string(5) "bytes"
["Content-Length"]=>
- int(0)
+ string(1) "0"
["Vary"]=>
string(15) "Accept-Encoding"
["Connection"]=>
GET /default/empty.txt HTTP/1.1
Host: localhost
Connection: close
-Content-Length: 0
HTTP/1.1 200 OK
Date: Thu, 26 Aug 2010 09:55:09 GMT
Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
Etag: "2002a-0-48549d615a35c"
Accept-Ranges: bytes
Vary: Accept-Encoding
-Content-Length: 0
Connection: close
Content-Type: text/plain
X-Original-Content-Length: 20
bool(true)
int(200)
string(2) "OK"
-array(11) {
+array(10) {
["Date"]=>
string(29) "Thu, 26 Aug 2010 09:55:09 GMT"
["Server"]=>
string(5) "bytes"
["Vary"]=>
string(15) "Accept-Encoding"
- ["Content-Length"]=>
- int(0)
["Connection"]=>
string(5) "close"
["Content-Type"]=>
Host: localhost
Accept-Encoding: gzip
Connection: close
-Content-Length: 0
HTTP/1.1 200 OK
Date: Thu, 26 Aug 2010 11:41:02 GMT
Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
GET /default/empty.php HTTP/1.1
Connection: close
Host: localhost
-Content-Length: 0
HTTP/1.1 200 OK
Date: Thu, 26 Aug 2010 12:51:28 GMT
Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
GET /cgi-bin/chunked.sh HTTP/1.1
Host: localhost
Connection: close
-Content-Length: 0
---
HTTP/1.1 200 OK
Date: Wed, 25 Aug 2010 12:11:44 GMT
["Accept-Ranges"]=>
string(5) "bytes"
["Content-Length"]=>
- int(0)
+ string(1) "0"
["Vary"]=>
string(15) "Accept-Encoding"
["Connection"]=>
GET /default/empty.txt HTTP/1.1
Host: localhost
Connection: close
-Content-Length: 0
HTTP/1.1 200 OK
Date: Thu, 26 Aug 2010 09:55:09 GMT
Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
Etag: "2002a-0-48549d615a35c"
Accept-Ranges: bytes
Vary: Accept-Encoding
-Content-Length: 0
Connection: close
Content-Type: text/plain
X-Original-Content-Length: 20
bool(true)
int(200)
string(2) "OK"
-array(11) {
+array(10) {
["Date"]=>
string(29) "Thu, 26 Aug 2010 09:55:09 GMT"
["Server"]=>
string(5) "bytes"
["Vary"]=>
string(15) "Accept-Encoding"
- ["Content-Length"]=>
- int(0)
["Connection"]=>
string(5) "close"
["Content-Type"]=>
Host: localhost
Accept-Encoding: gzip
Connection: close
-Content-Length: 0
HTTP/1.1 200 OK
Date: Thu, 26 Aug 2010 11:41:02 GMT
Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
GET /default/empty.php HTTP/1.1
Connection: close
Host: localhost
-Content-Length: 0
HTTP/1.1 200 OK
Date: Thu, 26 Aug 2010 12:51:28 GMT
Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/1.0.0a mod_fastcgi/2.4.6
GET /cgi-bin/chunked.sh HTTP/1.1
Host: localhost
Connection: close
-Content-Length: 0
Done