X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=php_http_message_parser.c;h=23cf4f8b79357779c82be746f16b8d1e063d76e5;hp=9accc354882ac2374092a6cf9a90765954033038;hb=66f7e8b6b937976c9c1d3dbfb86a90141b19b5c6;hpb=df06e2dbf48a3b0d96f2c62071c1b5fc907a98d0 diff --git a/php_http_message_parser.c b/php_http_message_parser.c index 9accc35..23cf4f8 100644 --- a/php_http_message_parser.c +++ b/php_http_message_parser.c @@ -1,4 +1,16 @@ -#include "php_http.h" +/* + +--------------------------------------------------------------------+ + | PECL :: http | + +--------------------------------------------------------------------+ + | Redistribution and use in source and binary forms, with or without | + | modification, are permitted provided that the conditions mentioned | + | in the accompanying LICENSE file are met. | + +--------------------------------------------------------------------+ + | Copyright (c) 2004-2011, Michael Wallner | + +--------------------------------------------------------------------+ +*/ + +#include "php_http_api.h" typedef struct php_http_message_parser_state_spec { php_http_message_parser_state_t state; @@ -74,10 +86,10 @@ PHP_HTTP_API void php_http_message_parser_dtor(php_http_message_parser_t *parser php_http_header_parser_dtor(&parser->header); zend_stack_destroy(&parser->stack); if (parser->dechunk) { - php_http_encoding_stream_free(&parser->dechunk TSRMLS_CC); + php_http_encoding_stream_free(&parser->dechunk); } if (parser->inflate) { - php_http_encoding_stream_free(&parser->inflate TSRMLS_CC); + php_http_encoding_stream_free(&parser->inflate); } } @@ -90,6 +102,77 @@ PHP_HTTP_API void php_http_message_parser_free(php_http_message_parser_t **parse } } +PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse_stream(php_http_message_parser_t *parser, php_stream *s, php_http_message_t **message) +{ + php_http_buffer_t buf; + TSRMLS_FETCH_FROM_CTX(parser->ts); + + php_http_buffer_init_ex(&buf, 0x1000, PHP_HTTP_BUFFER_INIT_PREALLOC); + + while (!php_stream_eof(s)) { + size_t len = 0; + + switch (php_http_message_parser_state_is(parser)) { + case PHP_HTTP_MESSAGE_PARSER_STATE_START: + case PHP_HTTP_MESSAGE_PARSER_STATE_HEADER: + case PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE: + /* read line */ + php_stream_get_line(s, buf.data, buf.free, &len); + buf.used += len; + buf.free -= len; + break; + + case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB: + /* read all */ + len = php_stream_read(s, buf.data, buf.free); + buf.used += len; + buf.free -= len; + break; + + case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH: + /* read body_length */ + len = php_stream_read(s, buf.data, MIN(buf.free, parser->body_length)); + buf.used += len; + buf.free -= len; + break; + + case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED: + /* duh, this is very naive */ + if (len) { + size_t read = php_stream_read(s, buf.data, MIN(len, buf.free)); + + buf.used += read; + buf.free -= read; + + len -= read; + } else { + php_stream_get_line(s, buf.data, buf.free, &len); + buf.used += len; + buf.free -= len; + + len = strtoul(buf.data - len, NULL, 16); + } + break; + + case PHP_HTTP_MESSAGE_PARSER_STATE_BODY: + case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE: + /* should not occur */ + abort(); + break; + + case PHP_HTTP_MESSAGE_PARSER_STATE_DONE: + case PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE: + php_http_buffer_dtor(&buf); + return php_http_message_parser_state_is(parser); + } + + php_http_message_parser_parse(parser, &buf, 0, message); + } + + php_http_buffer_dtor(&buf); + return PHP_HTTP_MESSAGE_PARSER_STATE_DONE; +} + PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, php_http_message_t **message) { @@ -101,7 +184,7 @@ PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse(php_h while (buffer->used || !php_http_message_parser_states[php_http_message_parser_state_is(parser)].need_data) { #if 0 const char *state[] = {"START", "HEADER", "HEADER_DONE", "BODY", "BODY_DUMB", "BODY_LENGTH", "BODY_CHUNK", "BODY_DONE", "DONE"}; - fprintf(stderr, "#MP: %s (%d)\n", php_http_message_parser_state_is(parser) < 0 ? "FAILURE" : state[php_http_message_parser_state_is(parser)], (*message)->type); + fprintf(stderr, "#MP: %s (%d)\n", php_http_message_parser_state_is(parser) < 0 ? "FAILURE" : state[php_http_message_parser_state_is(parser)], message && *message ? (*message)->type : -1); _dpf(0, buffer->data, buffer->used); #endif @@ -130,7 +213,7 @@ PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse(php_h { unsigned header_parser_flags = (flags & PHP_HTTP_MESSAGE_PARSER_CLEANUP) ? PHP_HTTP_HEADER_PARSER_CLEANUP : 0; - switch (php_http_header_parser_parse(&parser->header, buffer, header_parser_flags, &(*message)->hdrs, (php_http_info_callback_t) php_http_message_info_callback, message)) { + switch (php_http_header_parser_parse(&parser->header, buffer, header_parser_flags, *message ? &(*message)->hdrs : NULL, (php_http_info_callback_t) php_http_message_info_callback, message)) { case PHP_HTTP_HEADER_PARSER_STATE_FAILURE: return PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE; @@ -277,7 +360,7 @@ PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse(php_h char *dec_str = NULL; size_t dec_len; - if (SUCCESS != php_http_encoding_stream_update(parser->inflate, str, len, &dec_str, &dec_len TSRMLS_CC)) { + if (SUCCESS != php_http_encoding_stream_update(parser->inflate, str, len, &dec_str, &dec_len)) { return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE); } @@ -316,7 +399,7 @@ PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse(php_h len = buffer->used; cut = len; - php_http_message_parser_state_push(parser, 2, !buffer->used?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB, PHP_HTTP_MESSAGE_PARSER_STATE_BODY); + php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE, PHP_HTTP_MESSAGE_PARSER_STATE_BODY); break; } @@ -345,7 +428,7 @@ PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse(php_h char *dec_str = NULL; size_t dec_len; - if (SUCCESS != php_http_encoding_stream_update(parser->dechunk, buffer->data, buffer->used, &dec_str, &dec_len TSRMLS_CC)) { + if (SUCCESS != php_http_encoding_stream_update(parser->dechunk, buffer->data, buffer->used, &dec_str, &dec_len)) { return FAILURE; } @@ -370,7 +453,7 @@ PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse(php_h char *dec_str = NULL; size_t dec_len; - if (SUCCESS != php_http_encoding_stream_finish(parser->dechunk, &dec_str, &dec_len TSRMLS_CC)) { + if (SUCCESS != php_http_encoding_stream_finish(parser->dechunk, &dec_str, &dec_len)) { return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE); } php_http_encoding_stream_dtor(parser->dechunk); @@ -401,3 +484,13 @@ PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse(php_h return php_http_message_parser_state_is(parser); } + +/* + * 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 + */ +