X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=php_http_message_parser.c;h=4162e3710cf060f027840bf92a16a4524de54803;hb=1421b2b78469a66ebe3cd2958a608de9a036bca9;hp=3eb85719f2e8fe5523852976fef814cc5e8c0cf2;hpb=8d05291f42b3b42159b3fe91492aa4862f3d4405;p=m6w6%2Fext-http diff --git a/php_http_message_parser.c b/php_http_message_parser.c index 3eb8571..4162e37 100644 --- a/php_http_message_parser.c +++ b/php_http_message_parser.c @@ -10,7 +10,7 @@ +--------------------------------------------------------------------+ */ -#include "php_http.h" +#include "php_http_api.h" typedef struct php_http_message_parser_state_spec { php_http_message_parser_state_t state; @@ -102,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) { @@ -113,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