LCOV - code coverage report
Current view: top level - ext/http - php_http_header_parser.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 195 203 96.1 %
Date: 2015-02-17 20:30:22 Functions: 16 16 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :     +--------------------------------------------------------------------+
       3             :     | PECL :: http                                                       |
       4             :     +--------------------------------------------------------------------+
       5             :     | Redistribution and use in source and binary forms, with or without |
       6             :     | modification, are permitted provided that the conditions mentioned |
       7             :     | in the accompanying LICENSE file are met.                          |
       8             :     +--------------------------------------------------------------------+
       9             :     | Copyright (c) 2004-2014, Michael Wallner <mike@php.net>            |
      10             :     +--------------------------------------------------------------------+
      11             : */
      12             : 
      13             : #include "php_http_api.h"
      14             : 
      15             : #ifndef DBG_PARSER
      16             : #       define DBG_PARSER 0
      17             : #endif
      18             : 
      19             : typedef struct php_http_header_parser_state_spec {
      20             :         php_http_header_parser_state_t state;
      21             :         unsigned need_data:1;
      22             : } php_http_header_parser_state_spec_t;
      23             : 
      24             : static const php_http_header_parser_state_spec_t php_http_header_parser_states[] = {
      25             :                 {PHP_HTTP_HEADER_PARSER_STATE_START,            1},
      26             :                 {PHP_HTTP_HEADER_PARSER_STATE_KEY,                      1},
      27             :                 {PHP_HTTP_HEADER_PARSER_STATE_VALUE,            1},
      28             :                 {PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX,         0},
      29             :                 {PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE,      0},
      30             :                 {PHP_HTTP_HEADER_PARSER_STATE_DONE,                     0}
      31             : };
      32             : 
      33         153 : php_http_header_parser_t *php_http_header_parser_init(php_http_header_parser_t *parser TSRMLS_DC)
      34             : {
      35         153 :         if (!parser) {
      36          10 :                 parser = emalloc(sizeof(*parser));
      37             :         }
      38         153 :         memset(parser, 0, sizeof(*parser));
      39             : 
      40             :         TSRMLS_SET_CTX(parser->ts);
      41             : 
      42         153 :         return parser;
      43             : }
      44             : 
      45        2212 : php_http_header_parser_state_t php_http_header_parser_state_push(php_http_header_parser_t *parser, unsigned argc, ...)
      46             : {
      47             :         va_list va_args;
      48             :         unsigned i;
      49        2212 :         php_http_header_parser_state_t state = 0;
      50             : 
      51             :         /* short circuit */
      52        2212 :         ZEND_PTR_STACK_RESIZE_IF_NEEDED((&parser->stack), argc);
      53             : 
      54        2212 :         va_start(va_args, argc);
      55        4424 :         for (i = 0; i < argc; ++i) {
      56        2212 :                 state = va_arg(va_args, php_http_header_parser_state_t);
      57        2212 :                 zend_ptr_stack_push(&parser->stack, (void *) state);
      58             :         }
      59        2212 :         va_end(va_args);
      60             : 
      61        2212 :         return state;
      62             : }
      63             : 
      64         449 : php_http_header_parser_state_t php_http_header_parser_state_is(php_http_header_parser_t *parser)
      65             : {
      66         449 :         if (parser->stack.top) {
      67         426 :                 return (php_http_header_parser_state_t) parser->stack.elements[parser->stack.top - 1];
      68             :         }
      69             : 
      70          23 :         return PHP_HTTP_HEADER_PARSER_STATE_START;
      71             : }
      72             : 
      73        2298 : php_http_header_parser_state_t php_http_header_parser_state_pop(php_http_header_parser_t *parser)
      74             : {
      75        2298 :         if (parser->stack.top) {
      76        2154 :                 return (php_http_header_parser_state_t) zend_ptr_stack_pop(&parser->stack);
      77             :         }
      78             : 
      79         144 :         return PHP_HTTP_HEADER_PARSER_STATE_START;
      80             : }
      81             : 
      82         153 : void php_http_header_parser_dtor(php_http_header_parser_t *parser)
      83             : {
      84         153 :         zend_ptr_stack_destroy(&parser->stack);
      85         153 :         php_http_info_dtor(&parser->info);
      86         153 :         PTR_FREE(parser->_key.str);
      87         153 :         PTR_FREE(parser->_val.str);
      88         153 : }
      89             : 
      90          10 : void php_http_header_parser_free(php_http_header_parser_t **parser)
      91             : {
      92          10 :         if (*parser) {
      93          10 :                 php_http_header_parser_dtor(*parser);
      94          10 :                 efree(*parser);
      95          10 :                 *parser = NULL;
      96             :         }
      97          10 : }
      98             : 
      99             : /* NOTE: 'str' has to be null terminated */
     100          13 : static void php_http_header_parser_error(size_t valid_len, char *str, size_t len, const char *eol_str TSRMLS_DC)
     101             : {
     102             :         int escaped_len;
     103             :         char *escaped_str;
     104             : 
     105          13 :         escaped_str = php_addcslashes(str, len, &escaped_len, 0, ZEND_STRL("\x0..\x1F\x7F..\xFF") TSRMLS_CC);
     106             : 
     107          13 :         if (valid_len != len && (!eol_str || (str+valid_len) != eol_str)) {
     108           9 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse headers: unexpected character '\\%03o' at pos %zu of '%.*s'", str[valid_len], valid_len, escaped_len, escaped_str);
     109           4 :         } else if (eol_str) {
     110           3 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse headers: unexpected end of line at pos %zu of '%.*s'", eol_str - str, escaped_len, escaped_str);
     111             :         } else {
     112           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse headers: unexpected end of input at pos %zu of '%.*s'", len, escaped_len, escaped_str);
     113             :         }
     114             : 
     115          13 :         efree(escaped_str);
     116          13 : }
     117             : 
     118         300 : STATUS php_http_header_parser_parse(php_http_header_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg)
     119             : {
     120             :         TSRMLS_FETCH_FROM_CTX(parser->ts);
     121             : 
     122        2681 :         while (buffer->used || !php_http_header_parser_states[php_http_header_parser_state_is(parser)].need_data) {
     123             : #if DBG_PARSER
     124             :                 const char *state[] = {"START", "KEY", "VALUE", "VALUE_EX", "HEADER_DONE", "DONE"};
     125             :                 fprintf(stderr, "#HP: %s (avail:%zu, num:%d cleanup:%u)\n", php_http_header_parser_state_is(parser) < 0 ? "FAILURE" : state[php_http_header_parser_state_is(parser)], buffer->used, headers?zend_hash_num_elements(headers):0, flags);
     126             :                 _dpf(0, buffer->data, buffer->used);
     127             : #endif
     128        2298 :                 switch (php_http_header_parser_state_pop(parser)) {
     129             :                         case PHP_HTTP_HEADER_PARSER_STATE_FAILURE:
     130           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse headers");
     131           0 :                                 return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
     132             : 
     133             :                         case PHP_HTTP_HEADER_PARSER_STATE_START: {
     134         144 :                                 char *ptr = buffer->data;
     135             : 
     136         288 :                                 while (ptr - buffer->data < buffer->used && PHP_HTTP_IS_CTYPE(space, *ptr)) {
     137           0 :                                         ++ptr;
     138             :                                 }
     139             : 
     140         144 :                                 php_http_buffer_cut(buffer, 0, ptr - buffer->data);
     141         144 :                                 php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_KEY);
     142         144 :                                 break;
     143             :                         }
     144             : 
     145             :                         case PHP_HTTP_HEADER_PARSER_STATE_KEY: {
     146         622 :                                 const char *colon, *eol_str = NULL;
     147         622 :                                 int eol_len = 0;
     148             : 
     149         622 :                                 if (buffer->data == (eol_str = php_http_locate_bin_eol(buffer->data, buffer->used, &eol_len))) {
     150             :                                         /* end of headers */
     151          86 :                                         php_http_buffer_cut(buffer, 0, eol_len);
     152          86 :                                         php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_DONE);
     153         536 :                                 } else if (php_http_info_parse(&parser->info, php_http_buffer_fix(buffer)->data TSRMLS_CC)) {
     154             :                                         /* new message starting with request/response line */
     155         126 :                                         if (callback_func) {
     156         125 :                                                 callback_func(callback_arg, &headers, &parser->info TSRMLS_CC);
     157             :                                         }
     158         126 :                                         php_http_info_dtor(&parser->info);
     159         126 :                                         php_http_buffer_cut(buffer, 0, eol_str + eol_len - buffer->data);
     160         126 :                                         php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
     161         808 :                                 } else if ((colon = memchr(buffer->data, ':', buffer->used)) && (!eol_str || eol_str > colon)) {
     162             :                                         /* header: string */
     163             :                                         size_t valid_len;
     164             : 
     165         399 :                                         parser->_key.len = colon - buffer->data;
     166         399 :                                         parser->_key.str = estrndup(buffer->data, parser->_key.len);
     167             : 
     168         399 :                                         valid_len = strspn(parser->_key.str, PHP_HTTP_HEADER_NAME_CHARS);
     169         399 :                                         if (valid_len != parser->_key.len) {
     170           1 :                                                 php_http_header_parser_error(valid_len, parser->_key.str, parser->_key.len, eol_str TSRMLS_CC);
     171           1 :                                                 PTR_SET(parser->_key.str, NULL);
     172          13 :                                                 return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
     173             :                                         }
     174         398 :                                         while (PHP_HTTP_IS_CTYPE(space, *++colon) && *colon != '\n' && *colon != '\r');
     175         398 :                                         php_http_buffer_cut(buffer, 0, colon - buffer->data);
     176         398 :                                         php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
     177          11 :                                 } else if (eol_str || (flags & PHP_HTTP_HEADER_PARSER_CLEANUP)) {
     178             :                                         /* neither reqeust/response line nor 'header:' string, or injected new line or NUL etc. */
     179           9 :                                         php_http_buffer_fix(buffer);
     180           9 :                                         php_http_header_parser_error(strspn(buffer->data, PHP_HTTP_HEADER_NAME_CHARS), buffer->data, buffer->used, eol_str TSRMLS_CC);
     181           9 :                                         return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
     182             :                                 } else {
     183             :                                         /* keep feeding */
     184           2 :                                         return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_KEY);
     185             :                                 }
     186         610 :                                 break;
     187             :                         }
     188             : 
     189             :                         case PHP_HTTP_HEADER_PARSER_STATE_VALUE: {
     190             :                                 const char *eol_str;
     191             :                                 int eol_len;
     192             : 
     193             : #define SET_ADD_VAL(slen, eol_len) \
     194             :         do { \
     195             :                 const char *ptr = buffer->data; \
     196             :                 size_t len = slen; \
     197             :                  \
     198             :                 while (len > 0 && PHP_HTTP_IS_CTYPE(space, *ptr)) { \
     199             :                         ++ptr; \
     200             :                         --len; \
     201             :                 } \
     202             :                 while (len > 0 && PHP_HTTP_IS_CTYPE(space, ptr[len - 1])) { \
     203             :                         --len; \
     204             :                 } \
     205             :                  \
     206             :                 if (len > 0) { \
     207             :                         if (parser->_val.str) { \
     208             :                                 parser->_val.str = erealloc(parser->_val.str, parser->_val.len + len + 2); \
     209             :                                 parser->_val.str[parser->_val.len++] = ' '; \
     210             :                                 memcpy(&parser->_val.str[parser->_val.len], ptr, len); \
     211             :                                 parser->_val.len += len; \
     212             :                                 parser->_val.str[parser->_val.len] = '\0'; \
     213             :                         } else { \
     214             :                                 parser->_val.len = len; \
     215             :                                 parser->_val.str = estrndup(ptr, len); \
     216             :                         } \
     217             :                 } \
     218             :                 php_http_buffer_cut(buffer, 0, slen + eol_len); \
     219             :         } while (0)
     220             : 
     221         409 :                                 if ((eol_str = php_http_locate_bin_eol(buffer->data, buffer->used, &eol_len))) {
     222         401 :                                         SET_ADD_VAL(eol_str - buffer->data, eol_len);
     223         401 :                                         php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
     224           8 :                                 } else if (flags & PHP_HTTP_HEADER_PARSER_CLEANUP) {
     225           5 :                                         if (buffer->used) {
     226           5 :                                                 SET_ADD_VAL(buffer->used, 0);
     227             :                                         }
     228           5 :                                         php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
     229             :                                 } else {
     230           3 :                                         return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
     231             :                                 }
     232         406 :                                 break;
     233             :                         }
     234             : 
     235             :                         case PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX:
     236         514 :                                 if (buffer->used && (*buffer->data == ' ' || *buffer->data == '\t')) {
     237           9 :                                         php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
     238         505 :                                 } else if (buffer->used || (flags & PHP_HTTP_HEADER_PARSER_CLEANUP)) {
     239         392 :                                         php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
     240             :                                 } else {
     241             :                                         /* keep feeding */
     242         113 :                                         return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
     243             :                                 }
     244         401 :                                 break;
     245             : 
     246             :                         case PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE:
     247         523 :                                 if (parser->_key.str && parser->_val.str) {
     248             :                                         zval array, **exist;
     249         396 :                                         size_t valid_len = strlen(parser->_val.str);
     250             : 
     251             :                                         /* check for truncation */
     252         396 :                                         if (valid_len != parser->_val.len) {
     253           3 :                                                 php_http_header_parser_error(valid_len, parser->_val.str, parser->_val.len, NULL TSRMLS_CC);
     254             : 
     255           3 :                                                 PTR_SET(parser->_key.str, NULL);
     256           3 :                                                 PTR_SET(parser->_val.str, NULL);
     257             : 
     258           3 :                                                 return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
     259             :                                         }
     260             : 
     261         393 :                                         if (!headers && callback_func) {
     262           1 :                                                 callback_func(callback_arg, &headers, NULL TSRMLS_CC);
     263             :                                         }
     264             : 
     265         393 :                                         INIT_PZVAL_ARRAY(&array, headers);
     266         393 :                                         php_http_pretty_key(parser->_key.str, parser->_key.len, 1, 1);
     267         393 :                                         if (SUCCESS == zend_symtable_find(headers, parser->_key.str, parser->_key.len + 1, (void *) &exist)) {
     268           8 :                                                 convert_to_array(*exist);
     269           8 :                                                 add_next_index_stringl(*exist, parser->_val.str, parser->_val.len, 0);
     270             :                                         } else {
     271         385 :                                                 add_assoc_stringl_ex(&array, parser->_key.str, parser->_key.len + 1, parser->_val.str, parser->_val.len, 0);
     272             :                                         }
     273         393 :                                         parser->_val.str = NULL;
     274             :                                 }
     275             : 
     276         520 :                                 PTR_SET(parser->_key.str, NULL);
     277         520 :                                 PTR_SET(parser->_val.str, NULL);
     278             : 
     279         520 :                                 php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_KEY);
     280         520 :                                 break;
     281             : 
     282             :                         case PHP_HTTP_HEADER_PARSER_STATE_DONE:
     283          86 :                                 return PHP_HTTP_HEADER_PARSER_STATE_DONE;
     284             :                 }
     285             :         }
     286             : 
     287          83 :         return php_http_header_parser_state_is(parser);
     288             : }
     289             : 
     290          12 : php_http_header_parser_state_t php_http_header_parser_parse_stream(php_http_header_parser_t *parser, php_http_buffer_t *buf, php_stream *s, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg)
     291             : {
     292          12 :         php_http_message_parser_state_t state = PHP_HTTP_MESSAGE_PARSER_STATE_START;
     293             :         TSRMLS_FETCH_FROM_CTX(parser->ts);
     294             : 
     295          12 :         if (!buf->data) {
     296           1 :                 php_http_buffer_resize_ex(buf, 0x1000, 1, 0);
     297             :         }
     298             :         while (1) {
     299          18 :                 size_t justread = 0;
     300             : #if DBG_PARSER
     301             :                 const char *states[] = {"START", "KEY", "VALUE", "VALUE_EX", "HEADER_DONE", "DONE"};
     302             :                 fprintf(stderr, "#SHP: %s (f:%u)\n", states[state], flags);
     303             : #endif
     304             :                 /* resize if needed */
     305          18 :                 if (buf->free < 0x1000) {
     306           1 :                         php_http_buffer_resize_ex(buf, 0x1000, 1, 0);
     307             :                 }
     308          18 :                 switch (state) {
     309             :                 case PHP_HTTP_HEADER_PARSER_STATE_FAILURE:
     310             :                 case PHP_HTTP_HEADER_PARSER_STATE_DONE:
     311          13 :                         return state;
     312             : 
     313             :                 default:
     314             :                         /* read line */
     315          17 :                         php_stream_get_line(s, buf->data + buf->used, buf->free, &justread);
     316             :                         /* if we fail reading a whole line, try a single char */
     317          17 :                         if (!justread) {
     318          11 :                                 int c = php_stream_getc(s);
     319             : 
     320          11 :                                 if (c != EOF) {
     321           0 :                                         char s[1] = {c};
     322           0 :                                         justread = php_http_buffer_append(buf, s, 1);
     323             :                                 }
     324             :                         }
     325          17 :                         php_http_buffer_account(buf, justread);
     326             :                 }
     327             : 
     328          17 :                 if (justread) {
     329           6 :                         state = php_http_header_parser_parse(parser, buf, flags, headers, callback_func, callback_arg);
     330          11 :                 } else if (php_stream_eof(s)) {
     331           0 :                         return php_http_header_parser_parse(parser, buf, flags | PHP_HTTP_HEADER_PARSER_CLEANUP, headers, callback_func, callback_arg);
     332             :                 } else  {
     333          11 :                         return state;
     334             :                 }
     335           6 :         }
     336             : 
     337             :         return PHP_HTTP_HEADER_PARSER_STATE_DONE;
     338             : }
     339             : 
     340             : zend_class_entry *php_http_header_parser_class_entry;
     341             : static zend_object_handlers php_http_header_parser_object_handlers;
     342             : 
     343          10 : zend_object_value php_http_header_parser_object_new(zend_class_entry *ce TSRMLS_DC)
     344             : {
     345          10 :         return php_http_header_parser_object_new_ex(ce, NULL, NULL TSRMLS_CC);
     346             : }
     347             : 
     348          10 : zend_object_value php_http_header_parser_object_new_ex(zend_class_entry *ce, php_http_header_parser_t *parser, php_http_header_parser_object_t **ptr TSRMLS_DC)
     349             : {
     350             :         php_http_header_parser_object_t *o;
     351             : 
     352          10 :         o = ecalloc(1, sizeof(php_http_header_parser_object_t));
     353          10 :         zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
     354          10 :         object_properties_init((zend_object *) o, ce);
     355             : 
     356          10 :         if (ptr) {
     357           0 :                 *ptr = o;
     358             :         }
     359             : 
     360          10 :         if (parser) {
     361           0 :                 o->parser = parser;
     362             :         } else {
     363          10 :                 o->parser = php_http_header_parser_init(NULL TSRMLS_CC);
     364             :         }
     365          10 :         o->buffer = php_http_buffer_new();
     366             : 
     367          10 :         o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_http_header_parser_object_free, NULL TSRMLS_CC);
     368          10 :         o->zv.handlers = &php_http_header_parser_object_handlers;
     369             : 
     370          10 :         return o->zv;
     371             : }
     372             : 
     373          10 : void php_http_header_parser_object_free(void *object TSRMLS_DC)
     374             : {
     375          10 :         php_http_header_parser_object_t *o = (php_http_header_parser_object_t *) object;
     376             : 
     377          10 :         if (o->parser) {
     378          10 :                 php_http_header_parser_free(&o->parser);
     379             :         }
     380          10 :         if (o->buffer) {
     381          10 :                 php_http_buffer_free(&o->buffer);
     382             :         }
     383          10 :         zend_object_std_dtor((zend_object *) o TSRMLS_CC);
     384          10 :         efree(o);
     385          10 : }
     386             : 
     387             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpHeaderParser_getState, 0, 0, 0)
     388             : ZEND_END_ARG_INFO();
     389           6 : static PHP_METHOD(HttpHeaderParser, getState)
     390             : {
     391           6 :         php_http_header_parser_object_t *parser_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
     392             : 
     393           6 :         zend_parse_parameters_none();
     394             :         /* always return the real state */
     395           6 :         RETVAL_LONG(php_http_header_parser_state_is(parser_obj->parser));
     396           6 : }
     397             : 
     398             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpHeaderParser_parse, 0, 0, 3)
     399             :         ZEND_ARG_INFO(0, data)
     400             :         ZEND_ARG_INFO(0, flags)
     401             :         ZEND_ARG_ARRAY_INFO(1, headers, 1)
     402             : ZEND_END_ARG_INFO();
     403          17 : static PHP_METHOD(HttpHeaderParser, parse)
     404             : {
     405             :         php_http_header_parser_object_t *parser_obj;
     406             :         zval *zmsg;
     407             :         char *data_str;
     408             :         int data_len;
     409             :         long flags;
     410             : 
     411          34 :         php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "slz", &data_str, &data_len, &flags, &zmsg), invalid_arg, return);
     412             : 
     413          17 :         if (Z_TYPE_P(zmsg) != IS_ARRAY) {
     414           7 :                 zval_dtor(zmsg);
     415           7 :                 array_init(zmsg);
     416             :         }
     417          17 :         parser_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
     418          17 :         php_http_buffer_append(parser_obj->buffer, data_str, data_len);
     419          17 :         RETVAL_LONG(php_http_header_parser_parse(parser_obj->parser, parser_obj->buffer, flags, Z_ARRVAL_P(zmsg), NULL, NULL));
     420             : }
     421             : 
     422             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpHeaderParser_stream, 0, 0, 3)
     423             :         ZEND_ARG_INFO(0, stream)
     424             :         ZEND_ARG_INFO(0, flags)
     425             :         ZEND_ARG_ARRAY_INFO(1, headers, 1)
     426             : ZEND_END_ARG_INFO();
     427          12 : static PHP_METHOD(HttpHeaderParser, stream)
     428             : {
     429             :         php_http_header_parser_object_t *parser_obj;
     430             :         zend_error_handling zeh;
     431             :         zval *zmsg, *zstream;
     432             :         php_stream *s;
     433             :         long flags;
     434             : 
     435          12 :         php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &zstream, &flags, &zmsg), invalid_arg, return);
     436             : 
     437          12 :         zend_replace_error_handling(EH_THROW, php_http_exception_unexpected_val_class_entry, &zeh TSRMLS_CC);
     438          12 :         php_stream_from_zval(s, &zstream);
     439          12 :         zend_restore_error_handling(&zeh TSRMLS_CC);
     440             : 
     441          12 :         if (Z_TYPE_P(zmsg) != IS_ARRAY) {
     442           1 :                 zval_dtor(zmsg);
     443           1 :                 array_init(zmsg);
     444             :         }
     445          12 :         parser_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
     446          12 :         RETVAL_LONG(php_http_header_parser_parse_stream(parser_obj->parser, parser_obj->buffer, s, flags, Z_ARRVAL_P(zmsg), NULL, NULL));
     447             : }
     448             : 
     449             : static zend_function_entry php_http_header_parser_methods[] = {
     450             :                 PHP_ME(HttpHeaderParser, getState, ai_HttpHeaderParser_getState, ZEND_ACC_PUBLIC)
     451             :                 PHP_ME(HttpHeaderParser, parse, ai_HttpHeaderParser_parse, ZEND_ACC_PUBLIC)
     452             :                 PHP_ME(HttpHeaderParser, stream, ai_HttpHeaderParser_stream, ZEND_ACC_PUBLIC)
     453             :                 {NULL, NULL, NULL}
     454             : };
     455             : 
     456         374 : PHP_MINIT_FUNCTION(http_header_parser)
     457             : {
     458             :         zend_class_entry ce;
     459             : 
     460         374 :         INIT_NS_CLASS_ENTRY(ce, "http\\Header", "Parser", php_http_header_parser_methods);
     461         374 :         php_http_header_parser_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
     462         374 :         memcpy(&php_http_header_parser_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
     463         374 :         php_http_header_parser_class_entry->create_object = php_http_header_parser_object_new;
     464         374 :         php_http_header_parser_object_handlers.clone_obj = NULL;
     465             : 
     466         374 :         zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("CLEANUP"), PHP_HTTP_HEADER_PARSER_CLEANUP TSRMLS_CC);
     467             : 
     468         374 :         zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_FAILURE"), PHP_HTTP_HEADER_PARSER_STATE_FAILURE TSRMLS_CC);
     469         374 :         zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_START"), PHP_HTTP_HEADER_PARSER_STATE_START TSRMLS_CC);
     470         374 :         zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_KEY"), PHP_HTTP_HEADER_PARSER_STATE_KEY TSRMLS_CC);
     471         374 :         zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE"), PHP_HTTP_HEADER_PARSER_STATE_VALUE TSRMLS_CC);
     472         374 :         zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_VALUE_EX"), PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX TSRMLS_CC);
     473         374 :         zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_HEADER_DONE"), PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE TSRMLS_CC);
     474         374 :         zend_declare_class_constant_long(php_http_header_parser_class_entry, ZEND_STRL("STATE_DONE"), PHP_HTTP_HEADER_PARSER_STATE_DONE TSRMLS_CC);
     475             : 
     476         374 :         return SUCCESS;
     477             : }
     478             : 
     479             : /*
     480             :  * Local variables:
     481             :  * tab-width: 4
     482             :  * c-basic-offset: 4
     483             :  * End:
     484             :  * vim600: noet sw=4 ts=4 fdm=marker
     485             :  * vim<600: noet sw=4 ts=4
     486             :  */
     487             : 

Generated by: LCOV version 1.11