mirror of
https://github.com/nginx/nginx.git
synced 2025-06-07 17:52:38 +08:00

*) 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.
190 lines
4.6 KiB
C
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;
|
|
}
|
|
}
|