diff options
Diffstat (limited to 'src/imap/ngx_imap_parse.c')
-rw-r--r-- | src/imap/ngx_imap_parse.c | 152 |
1 files changed, 130 insertions, 22 deletions
diff --git a/src/imap/ngx_imap_parse.c b/src/imap/ngx_imap_parse.c index 08ff86355..e29791d73 100644 --- a/src/imap/ngx_imap_parse.c +++ b/src/imap/ngx_imap_parse.c @@ -5,49 +5,75 @@ #include <ngx_imap.h> -ngx_int_t ngx_pop3_parse_command(ngx_imap_request_t *r) +ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s) { - u_char ch, *p, *c; + u_char ch, *p, *c; + ngx_str_t *arg; enum { sw_start = 0, + sw_spaces_before_argument, + sw_argument, + sw_almost_done, sw_done } state; - while (p < r->buf->last && state < sw_done) { + state = s->state; + p = s->buffer->pos; + + while (p < s->buffer->last && state < sw_done) { ch = *p++; switch (state) { - /* POP3 commands */ + /* POP3 command */ + case sw_start: - if (ch == ' ') { - c = r->buf->start; + if (ch == ' ' || ch == CR || ch == LF) { + c = s->buffer->start; - if (p - 1 - m == 4) { + if (p - 1 - c == 4) { - if (*c == 'U' && *(c + 1) == 'S' - && *(c + 2) == 'E' && *(c + 3) == 'R') + if (c[0] == 'U' && c[1] == 'S' + && c[2] == 'E' && c[3] == 'R') { - r->command = NGX_POP3_USER; + s->command = NGX_POP3_USER; - } else if (*c == 'P' && *(c + 1) == 'A' - && *(c + 2) == 'A' && *(c + 3) == 'S') + } else if (c[0] == 'P' && c[1] == 'A' + && c[2] == 'A' && c[3] == 'S') { - r->method = NGX_POP3_PASS; + s->command = NGX_POP3_PASS; - } else if (*c == 'Q' && *(c + 1) == 'U' - && *(c + 2) == 'I' && *(c + 3) == 'T') + } else if (c[0] == 'Q' && c[1] == 'U' + && c[2] == 'I' && c[3] == 'T') { - r->method = NGX_POP3_QUIT; + s->command = NGX_POP3_QUIT; - } else if (*c == 'N' && *(c + 1) == 'O' - && *(c + 2) == 'O' && *(c + 3) == 'P') +#if 0 + } else if (c[0] == 'N' && c[1] == 'O' + && c[2] == 'O' && c[3] == 'P') { - r->method = NGX_POP3_NOOP; + s->command = NGX_POP3_NOOP; +#endif + + } else { + return NGX_IMAP_PARSE_INVALID_COMMAND; } + + } else { + return NGX_IMAP_PARSE_INVALID_COMMAND; } - state = sw_spaces_before_arg; + switch (ch) { + case ' ': + state = sw_spaces_before_argument; + break; + case CR: + state = sw_almost_done; + break; + case LF: + state = sw_done; + break; + } break; } @@ -56,7 +82,72 @@ ngx_int_t ngx_pop3_parse_command(ngx_imap_request_t *r) } 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; + break; + case LF: + state = sw_done; + s->arg_end = p - 1; + break; + default: + if (s->args.nelts > 2) { + return NGX_IMAP_PARSE_INVALID_COMMAND; + } + + state = sw_argument; + s->arg_start = p - 1; + break; + } + break; + + /* the argument */ + case sw_argument: + switch (ch) { + case ' ': + case CR: + case LF: + if (!(arg = ngx_array_push(&s->args))) { + return NGX_ERROR; + } + arg->len = p - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + + switch (ch) { + case ' ': + state = sw_spaces_before_argument; + break; + case CR: + state = sw_almost_done; + break; + case LF: + state = sw_done; + break; + } + break; + + default: + break; + } + break; + + /* end of request line */ + case sw_almost_done: + switch (ch) { + case LF: + state = sw_done; + break; + default: + return NGX_IMAP_PARSE_INVALID_COMMAND; + } + break; /* suppress warning */ case sw_done: @@ -64,5 +155,22 @@ ngx_int_t ngx_pop3_parse_command(ngx_imap_request_t *r) } } - return NGX_OK; + s->buffer->pos = p; + + if (state == sw_done) { + if (s->arg_start) { + if (!(arg = ngx_array_push(&s->args))) { + return NGX_ERROR; + } + arg->len = s->arg_end - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + } + + return NGX_OK; + + } else { + s->state = state; + return NGX_AGAIN; + } } |