# HG changeset patch # User Igor Sysoev # Date 1276614814 0 # Node ID e4cabc48b862a4d902266ab496f85af42c6d1d1c # Parent 8a6b36db2398cc378ad2d1b25e2025bca93596a8 ngx_http_parse_status_line() diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -51,6 +51,14 @@ struct ngx_http_log_ctx_s { }; +typedef struct { + ngx_uint_t code; + ngx_uint_t count; + u_char *start; + u_char *end; +} ngx_http_status_t; + + #define ngx_http_get_module_ctx(r, module) (r)->ctx[module.ctx_index] #define ngx_http_set_ctx(r, c, module) r->ctx[module.ctx_index] = c; @@ -70,6 +78,8 @@ int ngx_http_ssl_servername(ngx_ssl_conn ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b); ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes); +ngx_int_t ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b, + ngx_http_status_t *status); ngx_int_t ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args, ngx_uint_t *flags); ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -1318,6 +1318,211 @@ args: ngx_int_t +ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b, + ngx_http_status_t *status) +{ + u_char ch; + u_char *p; + enum { + sw_start = 0, + sw_H, + sw_HT, + sw_HTT, + sw_HTTP, + sw_first_major_digit, + sw_major_digit, + sw_first_minor_digit, + sw_minor_digit, + sw_status, + sw_space_after_status, + sw_status_text, + sw_almost_done + } state; + + state = r->state; + + for (p = b->pos; p < b->last; p++) { + ch = *p; + + switch (state) { + + /* "HTTP/" */ + case sw_start: + switch (ch) { + case 'H': + state = sw_H; + break; + default: + return NGX_ERROR; + } + break; + + case sw_H: + switch (ch) { + case 'T': + state = sw_HT; + break; + default: + return NGX_ERROR; + } + break; + + case sw_HT: + switch (ch) { + case 'T': + state = sw_HTT; + break; + default: + return NGX_ERROR; + } + break; + + case sw_HTT: + switch (ch) { + case 'P': + state = sw_HTTP; + break; + default: + return NGX_ERROR; + } + break; + + case sw_HTTP: + switch (ch) { + case '/': + state = sw_first_major_digit; + break; + default: + return NGX_ERROR; + } + break; + + /* the first digit of major HTTP version */ + case sw_first_major_digit: + if (ch < '1' || ch > '9') { + return NGX_ERROR; + } + + state = sw_major_digit; + break; + + /* the major HTTP version or dot */ + case sw_major_digit: + if (ch == '.') { + state = sw_first_minor_digit; + break; + } + + if (ch < '0' || ch > '9') { + return NGX_ERROR; + } + + break; + + /* the first digit of minor HTTP version */ + case sw_first_minor_digit: + if (ch < '0' || ch > '9') { + return NGX_ERROR; + } + + state = sw_minor_digit; + break; + + /* the minor HTTP version or the end of the request line */ + case sw_minor_digit: + if (ch == ' ') { + state = sw_status; + break; + } + + if (ch < '0' || ch > '9') { + return NGX_ERROR; + } + + break; + + /* HTTP status code */ + case sw_status: + if (ch == ' ') { + break; + } + + if (ch < '0' || ch > '9') { + return NGX_ERROR; + } + + status->code = status->code * 10 + ch - '0'; + + if (++status->count == 3) { + state = sw_space_after_status; + status->start = p - 2; + } + + break; + + /* space or end of line */ + case sw_space_after_status: + switch (ch) { + case ' ': + state = sw_status_text; + break; + case '.': /* IIS may send 403.1, 403.2, etc */ + state = sw_status_text; + break; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + default: + return NGX_ERROR; + } + break; + + /* any text until end of line */ + case sw_status_text: + switch (ch) { + case CR: + state = sw_almost_done; + + break; + case LF: + goto done; + } + break; + + /* end of status line */ + case sw_almost_done: + status->end = p - 1; + switch (ch) { + case LF: + goto done; + default: + return NGX_ERROR; + } + } + } + + b->pos = p; + r->state = state; + + return NGX_AGAIN; + +done: + + b->pos = p + 1; + + if (status->end == NULL) { + status->end = p; + } + + r->state = sw_start; + + return NGX_OK; +} + + +ngx_int_t ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args, ngx_uint_t *flags) {