Updated htparse

This commit is contained in:
Tatsuhiro Tsujikawa 2012-07-01 18:37:12 +09:00
parent ebfc313a26
commit fe5dfe533f
4 changed files with 67 additions and 31 deletions

View File

@ -45,7 +45,9 @@ enum eval_hdr_val {
eval_hdr_val_connection, eval_hdr_val_connection,
eval_hdr_val_proxy_connection, eval_hdr_val_proxy_connection,
eval_hdr_val_content_length, eval_hdr_val_content_length,
eval_hdr_val_transfer_encoding eval_hdr_val_transfer_encoding,
eval_hdr_val_hostname,
eval_hdr_val_content_type
}; };
enum parser_flags { enum parser_flags {
@ -109,6 +111,7 @@ struct htparser {
htp_scheme scheme; htp_scheme scheme;
htp_method method; htp_method method;
unsigned char multipart;
unsigned char major; unsigned char major;
unsigned char minor; unsigned char minor;
uint64_t content_len; uint64_t content_len;
@ -258,6 +261,7 @@ __HTPARSE_GENDHOOK(uri);
__HTPARSE_GENDHOOK(hdr_key); __HTPARSE_GENDHOOK(hdr_key);
__HTPARSE_GENDHOOK(hdr_val); __HTPARSE_GENDHOOK(hdr_val);
__HTPARSE_GENDHOOK(body); __HTPARSE_GENDHOOK(body);
__HTPARSE_GENDHOOK(hostname);
static inline uint64_t static inline uint64_t
@ -395,6 +399,11 @@ htparser_get_minor(htparser * p) {
return p->minor; return p->minor;
} }
unsigned char
htparser_get_multipart(htparser * p) {
return p->multipart;
}
void * void *
htparser_get_userdata(htparser * p) { htparser_get_userdata(htparser * p) {
return p->userdata; return p->userdata;
@ -1137,9 +1146,9 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len)
case s_status: case s_status:
/* http response status code */ /* http response status code */
if (ch == ' ') { if (ch == ' ') {
if (p->status) { if (p->status) {
p->state = s_status_text; p->state = s_status_text;
} }
break; break;
} }
@ -1262,11 +1271,21 @@ hdrline_start:
p->heval = eval_hdr_val_none; p->heval = eval_hdr_val_none;
switch (p->buf_idx + 1) { switch (p->buf_idx + 1) {
case 5:
if (!strcasecmp(p->buf, "host")) {
p->heval = eval_hdr_val_hostname;
}
break;
case 11: case 11:
if (!strcasecmp(p->buf, "connection")) { if (!strcasecmp(p->buf, "connection")) {
p->heval = eval_hdr_val_connection; p->heval = eval_hdr_val_connection;
} }
break; break;
case 13:
if (!strcasecmp(p->buf, "content-type")) {
p->heval = eval_hdr_val_content_type;
}
break;
case 15: case 15:
if (!strcasecmp(p->buf, "content-length")) { if (!strcasecmp(p->buf, "content-length")) {
p->heval = eval_hdr_val_content_length; p->heval = eval_hdr_val_content_length;
@ -1336,8 +1355,11 @@ hdrline_start:
switch (p->heval) { switch (p->heval) {
case eval_hdr_val_none: case eval_hdr_val_none:
break; break;
case eval_hdr_val_hostname:
res = hook_hostname_run(p, hooks, p->buf, p->buf_idx);
break;
case eval_hdr_val_content_length: case eval_hdr_val_content_length:
p->content_len = str_to_uint64(p->buf, p->buf_idx, &err); p->content_len = str_to_uint64(p->buf, p->buf_idx, &err);
if (err == 1) { if (err == 1) {
p->error = htparse_error_too_big; p->error = htparse_error_too_big;
@ -1366,6 +1388,13 @@ hdrline_start:
p->flags |= parser_flag_chunked; p->flags |= parser_flag_chunked;
} }
break;
case eval_hdr_val_content_type:
if (p->buf[0] == 'm' || p->buf[0] == 'M') {
if (_str8cmp((p->buf + 1), 'u', 'l', 't', 'i', 'p', 'a', 'r', 't')) {
p->multipart = 1;
}
}
break; break;
default: default:
break; break;
@ -1421,6 +1450,13 @@ hdrline_start:
switch (ch) { switch (ch) {
case CR: case CR:
p->state = s_hdrline_almost_done; p->state = s_hdrline_almost_done;
res = hook_on_hdrs_complete_run(p, hooks);
if (res) {
p->error = htparse_error_user;
return i + 1;
}
break; break;
case LF: case LF:
/* got LFLF? is this valid? */ /* got LFLF? is this valid? */
@ -1432,7 +1468,7 @@ hdrline_start:
p->state = s_hdrline_hdr_key; p->state = s_hdrline_hdr_key;
break; break;
} } /* switch */
break; break;
case s_hdrline_almost_done: case s_hdrline_almost_done:
htparse_log_debug("[%p] s_hdrline_almost_done", p); htparse_log_debug("[%p] s_hdrline_almost_done", p);
@ -1444,24 +1480,20 @@ hdrline_start:
p->buf_idx = 0; p->buf_idx = 0;
htparse_log_debug("[%p] HERE", p); htparse_log_debug("[%p] HERE", p);
res = hook_on_hdrs_complete_run(p, hooks); if (p->flags & parser_flag_trailing) {
res = hook_on_msg_complete_run(p, hooks);
if (!res) { p->state = s_start;
if (p->flags & parser_flag_trailing) { } else if (p->flags & parser_flag_chunked) {
res = hook_on_msg_complete_run(p, hooks); p->state = s_chunk_size_start;
p->state = s_start; } else if (p->content_len > 0) {
} else if (p->flags & parser_flag_chunked) { p->state = s_body_read;
p->state = s_chunk_size_start; } else if (p->content_len == 0) {
} else if (p->content_len > 0) { res = hook_on_msg_complete_run(p, hooks);
p->state = s_body_read; p->state = s_start;
} else if (p->content_len == 0) {
res = hook_on_msg_complete_run(p, hooks);
p->state = s_start;
}
} else {
p->state = s_hdrline_done;
} }
p->state = s_hdrline_done;
if (res) { if (res) {
p->error = htparse_error_user; p->error = htparse_error_user;
return i + 1; return i + 1;

View File

@ -67,19 +67,20 @@ typedef int (*htparse_data_hook)(htparser *, const char *, size_t);
struct htparse_hooks { struct htparse_hooks {
htparse_hook on_msg_begin; htparse_hook on_msg_begin;
htparse_data_hook method; htparse_data_hook method;
htparse_data_hook scheme; /* called if scheme is found */ htparse_data_hook scheme; /* called if scheme is found */
htparse_data_hook host; /* called if a host was in the request scheme */ htparse_data_hook host; /* called if a host was in the request scheme */
htparse_data_hook port; /* called if a port was in the request scheme */ htparse_data_hook port; /* called if a port was in the request scheme */
htparse_data_hook path; /* only the path of the uri */ htparse_data_hook path; /* only the path of the uri */
htparse_data_hook args; /* only the arguments of the uri */ htparse_data_hook args; /* only the arguments of the uri */
htparse_data_hook uri; /* the entire uri including path/args */ htparse_data_hook uri; /* the entire uri including path/args */
htparse_hook on_hdrs_begin; htparse_hook on_hdrs_begin;
htparse_data_hook hdr_key; htparse_data_hook hdr_key;
htparse_data_hook hdr_val; htparse_data_hook hdr_val;
htparse_data_hook hostname;
htparse_hook on_hdrs_complete; htparse_hook on_hdrs_complete;
htparse_hook on_new_chunk; /* called after parsed chunk octet */ htparse_hook on_new_chunk; /* called after parsed chunk octet */
htparse_hook on_chunk_complete; /* called after single parsed chunk */ htparse_hook on_chunk_complete; /* called after single parsed chunk */
htparse_hook on_chunks_complete; /* called after all parsed chunks processed */ htparse_hook on_chunks_complete; /* called after all parsed chunks processed */
htparse_data_hook body; htparse_data_hook body;
htparse_hook on_msg_complete; htparse_hook on_msg_complete;
}; };
@ -94,6 +95,7 @@ void htparser_set_major(htparser *, unsigned char);
void htparser_set_minor(htparser *, unsigned char); void htparser_set_minor(htparser *, unsigned char);
unsigned char htparser_get_major(htparser *); unsigned char htparser_get_major(htparser *);
unsigned char htparser_get_minor(htparser *); unsigned char htparser_get_minor(htparser *);
unsigned char htparser_get_multipart(htparser *);
unsigned int htparser_get_status(htparser *); unsigned int htparser_get_status(htparser *);
uint64_t htparser_get_content_length(htparser *); uint64_t htparser_get_content_length(htparser *);
uint64_t htparser_get_bytes_read(htparser *); uint64_t htparser_get_bytes_read(htparser *);

View File

@ -500,6 +500,7 @@ htparse_hooks htp_hooks = {
0, /* htparse_hook on_hdrs_begin; */ 0, /* htparse_hook on_hdrs_begin; */
htp_hdr_keycb, /* htparse_data_hook hdr_key; */ htp_hdr_keycb, /* htparse_data_hook hdr_key; */
htp_hdr_valcb, /* htparse_data_hook hdr_val; */ htp_hdr_valcb, /* htparse_data_hook hdr_val; */
0, /* htparse_data_hook hostname; */
htp_hdrs_completecb, /* htparse_hook on_hdrs_complete; */ htp_hdrs_completecb, /* htparse_hook on_hdrs_complete; */
0, /*htparse_hook on_new_chunk;*/ 0, /*htparse_hook on_new_chunk;*/
0, /*htparse_hook on_chunk_complete;*/ 0, /*htparse_hook on_chunk_complete;*/

View File

@ -222,6 +222,7 @@ htparse_hooks htp_hooks = {
htp_hdrs_begincb, /* htparse_hook on_hdrs_begin; */ htp_hdrs_begincb, /* htparse_hook on_hdrs_begin; */
htp_hdr_keycb, /* htparse_data_hook hdr_key; */ htp_hdr_keycb, /* htparse_data_hook hdr_key; */
htp_hdr_valcb, /* htparse_data_hook hdr_val; */ htp_hdr_valcb, /* htparse_data_hook hdr_val; */
0, /* htparse_data_hook hostname; */
htp_hdrs_completecb, /* htparse_hook on_hdrs_complete; */ htp_hdrs_completecb, /* htparse_hook on_hdrs_complete; */
0, /*htparse_hook on_new_chunk;*/ 0, /*htparse_hook on_new_chunk;*/
0, /*htparse_hook on_chunk_complete;*/ 0, /*htparse_hook on_chunk_complete;*/