diff options
author | Igor Sysoev <igor@sysoev.ru> | 2005-07-08 14:34:20 +0000 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2005-07-08 14:34:20 +0000 |
commit | 5192b3651f2f44fb5769828a2a4060989c7e9c5f (patch) | |
tree | d1ef9dfd855e836c6f05b496be88dc835537d03f /src/imap/ngx_imap_parse.c | |
parent | 549c6c644976dc694765d77110ebd2504ff7ce2b (diff) | |
download | nginx-release-0.1.38.tar.gz nginx-release-0.1.38.zip |
nginx-0.1.38-RELEASE importrelease-0.1.38
*) Feature: the "limit_rate" directive is supported in in proxy and
FastCGI mode.
*) Feature: the "X-Accel-Limit-Rate" response header line is supported
in proxy and FastCGI mode.
*) Feature: the "break" directive.
*) Feature: the "log_not_found" directive.
*) Bugfix: the response status code was not changed when request was
redirected by the ""X-Accel-Redirect" header line.
*) Bugfix: the variables set by the "set" directive could not be used
in SSI.
*) Bugfix: the segmentation fault may occurred if the SSI page has more
than one remote subrequest.
*) Bugfix: nginx treated the backend response as invalid if the status
line in the header was transferred in two packets; the bug had
appeared in 0.1.29.
*) Feature: the "ssi_types" directive.
*) Feature: the "autoindex_exact_size" directive.
*) Bugfix: the ngx_http_autoindex_module did not support the long file
names in UTF-8.
*) Feature: the IMAP/POP3 proxy.
Diffstat (limited to 'src/imap/ngx_imap_parse.c')
-rw-r--r-- | src/imap/ngx_imap_parse.c | 447 |
1 files changed, 379 insertions, 68 deletions
diff --git a/src/imap/ngx_imap_parse.c b/src/imap/ngx_imap_parse.c index 6c1c3e95a..e3923e892 100644 --- a/src/imap/ngx_imap_parse.c +++ b/src/imap/ngx_imap_parse.c @@ -10,64 +10,383 @@ #include <ngx_imap.h> -ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s) +ngx_int_t ngx_imap_parse_command(ngx_imap_session_t *s) { u_char ch, *p, *c; ngx_str_t *arg; enum { sw_start = 0, + sw_spaces_before_command, + sw_command, sw_spaces_before_argument, sw_argument, - sw_almost_done, - sw_done + sw_literal, + sw_start_literal_argument, + sw_literal_argument, + sw_end_literal_argument, + sw_almost_done } state; state = s->state; - p = s->buffer->pos; - while (p < s->buffer->last && state < sw_done) { - ch = *p++; + for (p = s->buffer->pos; p < s->buffer->last; p++) { + ch = *p; switch (state) { - /* POP3 command */ + /* IMAP tag */ + case sw_start: + switch (ch) { + case ' ': + s->tag.len = p - s->buffer->start + 1; + s->tag.data = s->buffer->start; + state = sw_spaces_before_command; + break; + case CR: + s->state = sw_start; + return NGX_IMAP_PARSE_INVALID_COMMAND; + case LF: + s->state = sw_start; + return NGX_IMAP_PARSE_INVALID_COMMAND; + } + break; + + case sw_spaces_before_command: + switch (ch) { + case ' ': + break; + case CR: + s->state = sw_start; + return NGX_IMAP_PARSE_INVALID_COMMAND; + case LF: + s->state = sw_start; + return NGX_IMAP_PARSE_INVALID_COMMAND; + default: + s->cmd_start = p; + state = sw_command; + break; + } + break; + + case sw_command: + if (ch == ' ' || ch == CR || ch == LF) { + + c = s->cmd_start; + + switch (p - c) { + + case 4: + if ((c[0] == 'N' || c[0] == 'n') + && (c[1] == 'O'|| c[1] == 'o') + && (c[2] == 'O'|| c[2] == 'o') + && (c[3] == 'P'|| c[3] == 'p')) + { + s->command = NGX_IMAP_NOOP; + + } else { + goto invalid; + } + break; + + case 5: + if ((c[0] == 'L'|| c[0] == 'l') + && (c[1] == 'O'|| c[1] == 'o') + && (c[2] == 'G'|| c[2] == 'g') + && (c[3] == 'I'|| c[3] == 'i') + && (c[4] == 'N'|| c[4] == 'n')) + { + s->command = NGX_IMAP_LOGIN; + + } else { + goto invalid; + } + break; + + case 6: + if ((c[0] == 'L'|| c[0] == 'l') + && (c[1] == 'O'|| c[1] == 'o') + && (c[2] == 'G'|| c[2] == 'g') + && (c[3] == 'O'|| c[3] == 'o') + && (c[4] == 'U'|| c[4] == 'u') + && (c[5] == 'T'|| c[5] == 't')) + { + s->command = NGX_IMAP_LOGOUT; + + } else { + goto invalid; + } + break; + + case 10: + if ((c[0] == 'C'|| c[0] == 'c') + && (c[1] == 'A'|| c[1] == 'a') + && (c[2] == 'P'|| c[2] == 'p') + && (c[3] == 'A'|| c[3] == 'a') + && (c[4] == 'B'|| c[4] == 'b') + && (c[5] == 'I'|| c[5] == 'i') + && (c[6] == 'L'|| c[6] == 'l') + && (c[7] == 'I'|| c[7] == 'i') + && (c[8] == 'T'|| c[8] == 't') + && (c[9] == 'Y'|| c[9] == 'y')) + { + s->command = NGX_IMAP_CAPABILITY; + + } else { + goto invalid; + } + break; + + default: + goto invalid; + } + + switch (ch) { + case ' ': + state = sw_spaces_before_argument; + break; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + } + break; + } + + if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { + goto invalid; + } + + break; + + case sw_spaces_before_argument: + switch (ch) { + case ' ': + break; + case CR: + state = sw_almost_done; + s->arg_end = p; + break; + case LF: + s->arg_end = p; + goto done; + case '"': + if (s->args.nelts <= 2) { + s->quoted = 1; + s->arg_start = p + 1; + state = sw_argument; + break; + } + goto invalid; + case '{': + if (s->args.nelts <= 2) { + state = sw_literal; + break; + } + goto invalid; + default: + if (s->args.nelts <= 2) { + s->arg_start = p; + state = sw_argument; + break; + } + goto invalid; + } + break; + + case sw_argument: + switch (ch) { + case '"': + if (!s->quoted) { + break; + } + s->quoted = 0; + /* fall through */ + case ' ': + case CR: + case LF: + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = p - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + + switch (ch) { + case '"': + case ' ': + state = sw_spaces_before_argument; + break; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + } + break; + } + break; + + case sw_literal: + if (ch >= '0' && ch <= '9') { + s->literal_len = s->literal_len * 10 + (ch - '0'); + break; + } + if (ch == '}') { + state = sw_start_literal_argument; + break; + } + goto invalid; + + case sw_start_literal_argument: + switch (ch) { + case CR: + break; + case LF: + s->buffer->pos = p + 1; + s->arg_start = p + 1; + s->state = sw_literal_argument; + return NGX_IMAP_NEXT; + } + goto invalid; + + case sw_literal_argument: + if (--s->literal_len) { + break; + } + + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = p + 1 - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + state = sw_end_literal_argument; + + break; + + case sw_end_literal_argument: + switch (ch) { + case '{': + if (s->args.nelts <= 2) { + state = sw_literal; + break; + } + goto invalid; + case CR: + state = sw_almost_done; + break; + case LF: + goto done; + default: + goto invalid; + } + break; + case sw_almost_done: + switch (ch) { + case LF: + goto done; + default: + goto invalid; + } + } + } + + s->buffer->pos = p; + s->state = state; + + return NGX_AGAIN; + +done: + + s->buffer->pos = p + 1; + + if (s->arg_start) { + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = s->arg_end - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + s->cmd_start = NULL; + s->quoted = 0; + s->literal_len = 0; + } + + s->state = sw_start; + + return NGX_OK; + +invalid: + + s->state = sw_start; + s->quoted = 0; + s->literal_len = 0; + + return NGX_IMAP_PARSE_INVALID_COMMAND; +} + + +ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s) +{ + u_char ch, *p, *c, c0, c1, c2, c3; + ngx_str_t *arg; + enum { + sw_start = 0, + sw_spaces_before_argument, + sw_argument, + sw_almost_done + } state; + + state = s->state; + + for (p = s->buffer->pos; p < s->buffer->last; p++) { + ch = *p; + + switch (state) { + + /* POP3 command */ case sw_start: if (ch == ' ' || ch == CR || ch == LF) { c = s->buffer->start; - if (p - 1 - c == 4) { + if (p - c == 4) { + + c0 = ngx_toupper(c[0]); + c1 = ngx_toupper(c[1]); + c2 = ngx_toupper(c[2]); + c3 = ngx_toupper(c[3]); - if (c[0] == 'U' && c[1] == 'S' - && c[2] == 'E' && c[3] == 'R') + if (c0 == 'U' && c1 == 'S' && c2 == 'E' && c3 == 'R') { s->command = NGX_POP3_USER; - } else if (c[0] == 'P' && c[1] == 'A' - && c[2] == 'S' && c[3] == 'S') + } else if (c0 == 'P' && c1 == 'A' && c2 == 'S' && c3 == 'S') { s->command = NGX_POP3_PASS; - } else if (c[0] == 'Q' && c[1] == 'U' - && c[2] == 'I' && c[3] == 'T') + } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T') { s->command = NGX_POP3_QUIT; -#if 0 - } else if (c[0] == 'N' && c[1] == 'O' - && c[2] == 'O' && c[3] == 'P') + } else if (c0 == 'C' && c1 == 'A' && c2 == 'P' && c3 == 'A') + { + s->command = NGX_POP3_CAPA; + + } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P') { s->command = NGX_POP3_NOOP; -#endif } else { - s->state = sw_start; - return NGX_IMAP_PARSE_INVALID_COMMAND; + goto invalid; } } else { - s->state = sw_start; - return NGX_IMAP_PARSE_INVALID_COMMAND; + goto invalid; } switch (ch) { @@ -78,45 +397,38 @@ ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s) state = sw_almost_done; break; case LF: - state = sw_done; - break; + goto done; } break; } - if (ch < 'A' || ch > 'Z') { - s->state = sw_start; - return NGX_IMAP_PARSE_INVALID_COMMAND; + if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { + goto invalid; } break; - /* the spaces before the argument */ case sw_spaces_before_argument: switch (ch) { case ' ': break; case CR: state = sw_almost_done; - s->arg_end = p - 1; + s->arg_end = p; break; case LF: - state = sw_done; - s->arg_end = p - 1; - break; + s->arg_end = p; + goto done; default: - if (s->args.nelts > 2) { - s->state = sw_start; - return NGX_IMAP_PARSE_INVALID_COMMAND; + if (s->args.nelts <= 2) { + state = sw_argument; + s->arg_start = p; + break; } - - state = sw_argument; - s->arg_start = p - 1; - break; + goto invalid; } break; - /* the argument */ case sw_argument: switch (ch) { case ' ': @@ -126,7 +438,7 @@ ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s) if (arg == NULL) { return NGX_ERROR; } - arg->len = p - 1 - s->arg_start; + arg->len = p - s->arg_start; arg->data = s->arg_start; s->arg_start = NULL; @@ -138,8 +450,7 @@ ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s) state = sw_almost_done; break; case LF: - state = sw_done; - break; + goto done; } break; @@ -148,42 +459,42 @@ ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s) } break; - /* end of request line */ case sw_almost_done: switch (ch) { case LF: - state = sw_done; - break; + goto done; default: - s->state = sw_start; - return NGX_IMAP_PARSE_INVALID_COMMAND; + goto invalid; } - break; - - /* suppress warning */ - case sw_done: - break; } } s->buffer->pos = p; + s->state = state; - if (state == sw_done) { - if (s->arg_start) { - arg = ngx_array_push(&s->args); - if (arg == NULL) { - return NGX_ERROR; - } - arg->len = s->arg_end - s->arg_start; - arg->data = s->arg_start; - s->arg_start = NULL; - } + return NGX_AGAIN; + +done: - s->state = sw_start; - return NGX_OK; + s->buffer->pos = p + 1; - } else { - s->state = state; - return NGX_AGAIN; + if (s->arg_start) { + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = s->arg_end - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; } + + s->state = sw_start; + + return NGX_OK; + +invalid: + + s->state = sw_start; + + return NGX_IMAP_PARSE_INVALID_COMMAND; } |