27# define MIN(a,b) ((a) < (b) ? (a) : (b))
31#define CALLBACK2(FOR) \
33 if (settings->on_##FOR) { \
34 if (0 != settings->on_##FOR(parser)) return (p - data); \
44#define CALLBACK_NOCLEAR(FOR) \
47 if (settings->on_##FOR) { \
48 if (0 != settings->on_##FOR(parser, \
61#define CALLBACK(FOR) \
63 CALLBACK_NOCLEAR(FOR); \
68#define PROXY_CONNECTION "proxy-connection"
69#define CONNECTION "connection"
70#define CONTENT_LENGTH "content-length"
71#define TRANSFER_ENCODING "transfer-encoding"
72#define UPGRADE "upgrade"
73#define CHUNKED "chunked"
74#define KEEP_ALIVE "keep-alive"
78static const char *method_strings[] =
116static const char tokens[256] = {
118 0, 0, 0, 0, 0, 0, 0, 0,
120 0, 0, 0, 0, 0, 0, 0, 0,
122 0, 0, 0, 0, 0, 0, 0, 0,
124 0, 0, 0, 0, 0, 0, 0, 0,
126 ' ',
'!',
'"',
'#',
'$',
'%',
'&',
'\'',
128 0, 0,
'*',
'+', 0,
'-',
'.',
'/',
130 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
132 '8',
'9', 0, 0, 0, 0, 0, 0,
134 0,
'a',
'b',
'c',
'd',
'e',
'f',
'g',
136 'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
138 'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
140 'x',
'y',
'z', 0, 0, 0,
'^',
'_',
142 '`',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
144 'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
146 'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
148 'x',
'y',
'z', 0,
'|',
'}',
'~', 0 };
151static const int8_t unhex[256] =
152 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
153 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
154 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
155 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
156 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
157 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
158 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
159 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
163static const uint8_t normal_url_char[256] = {
165 0, 0, 0, 0, 0, 0, 0, 0,
167 0, 0, 0, 0, 0, 0, 0, 0,
169 0, 0, 0, 0, 0, 0, 0, 0,
171 0, 0, 0, 0, 0, 0, 0, 0,
173 0, 1, 1, 0, 1, 1, 1, 1,
175 1, 1, 1, 1, 1, 1, 1, 1,
177 1, 1, 1, 1, 1, 1, 1, 1,
179 1, 1, 1, 1, 1, 1, 1, 0,
181 1, 1, 1, 1, 1, 1, 1, 1,
183 1, 1, 1, 1, 1, 1, 1, 1,
185 1, 1, 1, 1, 1, 1, 1, 1,
187 1, 1, 1, 1, 1, 1, 1, 1,
189 1, 1, 1, 1, 1, 1, 1, 1,
191 1, 1, 1, 1, 1, 1, 1, 1,
193 1, 1, 1, 1, 1, 1, 1, 1,
195 1, 1, 1, 1, 1, 1, 1, 0 };
198#define PARSING_HEADER(state) (state <= s_headers_almost_done && 0 == (parser->flags & F_TRAILING))
240#define LOWER(c) (unsigned char)(c | 0x20)
241#define TOKEN(c) tokens[(unsigned char)c]
244#define start_state (parser->type == PHP_HTTP_REQUEST ? s_start_req : s_start_res)
247#ifdef HTTP_PARSER_STRICT
248# define STRICT_CHECK(cond) if (cond) goto error
249# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
251# define STRICT_CHECK(cond)
252# define NEW_MESSAGE() start_state
263 const char *
p =
data, *pe;
268 uint32_t index = parser->
index;
269 uint32_t nread = parser->
nread;
274 const char *header_field_mark = 0;
275 const char *header_value_mark = 0;
276 const char *fragment_mark = 0;
277 const char *query_string_mark = 0;
278 const char *path_mark = 0;
279 const char *url_mark = 0;
289 header_field_mark =
data;
291 header_value_mark =
data;
293 fragment_mark =
data;
295 query_string_mark =
data;
335 goto start_req_method_assign;
444 if (
ch <
'0' ||
ch >
'9') {
457 if (
ch <
'0' ||
ch >
'9') {
511 start_req_method_assign:
539 matcher = method_strings[parser->
method];
548 if (index == 1 &&
ch ==
'H') {
550 }
else if (index == 2 &&
ch ==
'P') {
556 if (index == 1 &&
ch ==
'O') {
558 }
else if (index == 3 &&
ch ==
'A') {
560 }
else if (index == 1 &&
ch ==
'E') {
562 }
else if (index == 1 &&
ch ==
'-') {
564 }
else if (index == 2 &&
ch ==
'A') {
590 if (
ch ==
' ')
break;
592 if (
ch ==
'/' ||
ch ==
'*') {
601 if (c >=
'a' && c <=
'z') {
614 if (c >=
'a' && c <=
'z')
break;
619 }
else if (
ch ==
'.') {
622 }
else if (
'0' <=
ch &&
ch <=
'9') {
643 if (c >=
'a' && c <=
'z')
break;
644 if ((
ch >=
'0' &&
ch <=
'9') ||
ch ==
'.' ||
ch ==
'-')
break;
669 if (
ch >=
'0' &&
ch <=
'9')
break;
691 if (normal_url_char[(
unsigned char)
ch])
break;
729 if (normal_url_char[(
unsigned char)
ch]) {
765 if (normal_url_char[(
unsigned char)
ch])
break;
802 if (normal_url_char[(
unsigned char)
ch]) {
839 if (normal_url_char[(
unsigned char)
ch])
break;
976 goto headers_almost_done;
1017 switch (header_state) {
1101 }
else if (index ==
sizeof(
UPGRADE)-2) {
1114 assert(0 &&
"Unknown header_state");
1143 if (
ch ==
' ')
break;
1165 switch (header_state) {
1190 }
else if (c ==
'c') {
1216 goto header_almost_done;
1219 switch (header_state) {
1225 assert(0 &&
"Shouldn't get here.");
1229 if (
ch ==
' ')
break;
1241 }
else if (index ==
sizeof(
CHUNKED)-2) {
1260 if (index >
sizeof(
CLOSE)-1 || c !=
CLOSE[index]) {
1262 }
else if (index ==
sizeof(
CLOSE)-2) {
1288 switch (header_state) {
1305 headers_almost_done:
1410 c = unhex[(
unsigned char)
ch];
1411 if (c == -1)
goto error;
1426 c = unhex[(
unsigned char)
ch];
1429 if (
ch ==
';' ||
ch ==
' ') {
1499 assert(0 &&
"unhandled state");
1513 parser->
index = index;
1514 parser->
nread = nread;
1547 return method_strings[m];
assert(mixed $assertion, Throwable|string|null $description=null)
@ h_matching_transfer_encoding
@ h_matching_proxy_connection
@ h_connection_keep_alive
@ h_matching_connection_keep_alive
@ h_transfer_encoding_chunked
@ h_matching_content_length
@ h_matching_connection_close
@ h_matching_transfer_encoding_chunked
const char * php_http_method_str(enum php_http_method m)
#define PARSING_HEADER(state)
#define STRICT_CHECK(cond)
@ F_CONNECTION_KEEP_ALIVE
#define TRANSFER_ENCODING
#define CALLBACK_NOCLEAR(FOR)
int php_http_should_keep_alive(php_http_parser *parser)
void php_http_parser_init(php_http_parser *parser, enum php_http_parser_type t)
size_t php_http_parser_execute(php_http_parser *parser, const php_http_parser_settings *settings, const char *data, size_t len)
@ PHP_HTTP_NOT_IMPLEMENTED
#define PHP_HTTP_MAX_HEADER_SIZE
@ s_chunk_size_almost_done
@ s_res_first_status_code
@ s_req_query_string_start
@ s_req_spaces_before_url
@ s_req_schema_slash_slash
@ s_chunk_data_almost_done
php_http_cb on_headers_complete
unsigned char header_state
unsigned short http_minor
unsigned short status_code
unsigned short http_major