nginx/src/imap/ngx_imap_parse.c
Igor Sysoev c15717285d nginx-0.1.25-RELEASE import
*) Bugfix: nginx did run on Linux parisc.

    *) Feature: nginx now does not start under FreeBSD if the sysctl
       kern.ipc.somaxconn value is too big.

    *) Bugfix: if a request was internally redirected by the
       ngx_http_index_module module to the ngx_http_proxy_module or
       ngx_http_fastcgi_module modules, then the index file was not closed
       after request completion.

    *) Feature: the "proxy_pass" can be used in location with regular
       expression.

    *) Feature: the ngx_http_rewrite_filter_module module supports the
       condition like "if ($HTTP_USER_AGENT ~ MSIE)".

    *) Bugfix: nginx started too slow if the large number of addresses and
       text values were used in the "geo" directive.

    *) Change: a variable name must be declared as "$name" in the "geo"
       directive. The previous variant without "$" is still supported, but
       will be removed soon.

    *) Feature: the "%{VARIABLE}v" logging parameter.

    *) Feature: the "set $name value" directive.

    *) Bugfix: gcc 4.0 compatibility.

    *) Feature: the --with-openssl-opt=OPTIONS autoconfiguration directive.
2005-03-19 12:38:37 +00:00

190 lines
4.6 KiB
C

/*
* Copyright (C) Igor Sysoev
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_imap.h>
ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s)
{
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;
state = s->state;
p = s->buffer->pos;
while (p < s->buffer->last && state < sw_done) {
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 (c[0] == 'U' && c[1] == 'S'
&& c[2] == 'E' && c[3] == 'R')
{
s->command = NGX_POP3_USER;
} else if (c[0] == 'P' && c[1] == 'A'
&& c[2] == 'S' && c[3] == 'S')
{
s->command = NGX_POP3_PASS;
} else if (c[0] == 'Q' && c[1] == 'U'
&& c[2] == 'I' && c[3] == 'T')
{
s->command = NGX_POP3_QUIT;
#if 0
} else if (c[0] == 'N' && c[1] == 'O'
&& c[2] == 'O' && c[3] == 'P')
{
s->command = NGX_POP3_NOOP;
#endif
} else {
s->state = sw_start;
return NGX_IMAP_PARSE_INVALID_COMMAND;
}
} else {
s->state = sw_start;
return NGX_IMAP_PARSE_INVALID_COMMAND;
}
switch (ch) {
case ' ':
state = sw_spaces_before_argument;
break;
case CR:
state = sw_almost_done;
break;
case LF:
state = sw_done;
break;
}
break;
}
if (ch < 'A' || ch > 'Z') {
s->state = sw_start;
return NGX_IMAP_PARSE_INVALID_COMMAND;
}
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) {
s->state = sw_start;
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:
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;
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:
s->state = sw_start;
return NGX_IMAP_PARSE_INVALID_COMMAND;
}
break;
/* suppress warning */
case sw_done:
break;
}
}
s->buffer->pos = p;
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;
}
s->state = sw_start;
return NGX_OK;
} else {
s->state = state;
return NGX_AGAIN;
}
}