Mercurial > hg > nginx-quic
annotate src/imap/ngx_imap_parse.c @ 573:58475592100c release-0.3.8
nginx-0.3.8-RELEASE import
*) Security: nginx now checks URI got from a backend in
"X-Accel-Redirect" header line or in SSI file for the "/../" paths
and zeroes.
*) Change: nginx now does not treat the empty user name in the
"Authorization" header line as valid one.
*) Feature: the "ssl_session_timeout" directives of the
ngx_http_ssl_module and ngx_imap_ssl_module.
*) Feature: the "auth_http_header" directive of the
ngx_imap_auth_http_module.
*) Feature: the "add_header" directive.
*) Feature: the ngx_http_realip_module.
*) Feature: the new variables to use in the "log_format" directive:
$bytes_sent, $apache_bytes_sent, $status, $time_gmt, $uri,
$request_time, $request_length, $upstream_status,
$upstream_response_time, $gzip_ratio, $uid_got, $uid_set,
$connection, $pipe, and $msec. The parameters in the "%name" form
will be canceled soon.
*) Change: now the false variable values in the "if" directive are the
empty string "" and string starting with "0".
*) Bugfix: while using proxied or FastCGI-server nginx may leave
connections and temporary files with client requests in open state.
*) Bugfix: the worker processes did not flush the buffered logs on
graceful exit.
*) Bugfix: if the request URI was changes by the "rewrite" directive
and the request was proxied in location given by regular expression,
then the incorrect request was transferred to backend; the bug had
appeared in 0.2.6.
*) Bugfix: the "expires" directive did not remove the previous
"Expires" header.
*) Bugfix: nginx may stop to accept requests if the "rtsig" method and
several worker processes were used.
*) Bugfix: the "\"" and "\'" escape symbols were incorrectly handled in
SSI commands.
*) Bugfix: if the response was ended just after the SSI command and
gzipping was used, then the response did not transferred complete or
did not transferred at all.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Wed, 09 Nov 2005 17:25:55 +0000 |
parents | 511a89da35ad |
children | 4d9ea73a627a |
rev | line source |
---|---|
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
1 |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
2 /* |
444
42d11f017717
nginx-0.1.0-2004-09-29-20:00:49 import; remove years from copyright
Igor Sysoev <igor@sysoev.ru>
parents:
441
diff
changeset
|
3 * Copyright (C) Igor Sysoev |
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
4 */ |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
5 |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
6 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
7 #include <ngx_config.h> |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
8 #include <ngx_core.h> |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
9 #include <ngx_event.h> |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
10 #include <ngx_imap.h> |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
11 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
12 |
527 | 13 ngx_int_t ngx_imap_parse_command(ngx_imap_session_t *s) |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
14 { |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
15 u_char ch, *p, *c; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
16 ngx_str_t *arg; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
17 enum { |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
18 sw_start = 0, |
527 | 19 sw_spaces_before_command, |
20 sw_command, | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
21 sw_spaces_before_argument, |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
22 sw_argument, |
543 | 23 sw_backslash, |
527 | 24 sw_literal, |
543 | 25 sw_no_sync_literal_argument, |
527 | 26 sw_start_literal_argument, |
27 sw_literal_argument, | |
28 sw_end_literal_argument, | |
29 sw_almost_done | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
30 } state; |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
31 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
32 state = s->state; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
33 |
527 | 34 for (p = s->buffer->pos; p < s->buffer->last; p++) { |
35 ch = *p; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
36 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
37 switch (state) { |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
38 |
527 | 39 /* IMAP tag */ |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
40 case sw_start: |
527 | 41 switch (ch) { |
42 case ' ': | |
43 s->tag.len = p - s->buffer->start + 1; | |
44 s->tag.data = s->buffer->start; | |
45 state = sw_spaces_before_command; | |
46 break; | |
47 case CR: | |
48 s->state = sw_start; | |
49 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
50 case LF: | |
51 s->state = sw_start; | |
52 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
53 } | |
54 break; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
55 |
527 | 56 case sw_spaces_before_command: |
57 switch (ch) { | |
58 case ' ': | |
59 break; | |
60 case CR: | |
61 s->state = sw_start; | |
62 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
63 case LF: | |
64 s->state = sw_start; | |
65 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
66 default: | |
67 s->cmd_start = p; | |
68 state = sw_command; | |
69 break; | |
70 } | |
71 break; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
72 |
527 | 73 case sw_command: |
74 if (ch == ' ' || ch == CR || ch == LF) { | |
75 | |
76 c = s->cmd_start; | |
77 | |
78 switch (p - c) { | |
79 | |
80 case 4: | |
81 if ((c[0] == 'N' || c[0] == 'n') | |
82 && (c[1] == 'O'|| c[1] == 'o') | |
83 && (c[2] == 'O'|| c[2] == 'o') | |
84 && (c[3] == 'P'|| c[3] == 'p')) | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
85 { |
527 | 86 s->command = NGX_IMAP_NOOP; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
87 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
88 } else { |
527 | 89 goto invalid; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
90 } |
527 | 91 break; |
92 | |
93 case 5: | |
94 if ((c[0] == 'L'|| c[0] == 'l') | |
95 && (c[1] == 'O'|| c[1] == 'o') | |
96 && (c[2] == 'G'|| c[2] == 'g') | |
97 && (c[3] == 'I'|| c[3] == 'i') | |
98 && (c[4] == 'N'|| c[4] == 'n')) | |
99 { | |
100 s->command = NGX_IMAP_LOGIN; | |
101 | |
102 } else { | |
103 goto invalid; | |
104 } | |
105 break; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
106 |
527 | 107 case 6: |
108 if ((c[0] == 'L'|| c[0] == 'l') | |
109 && (c[1] == 'O'|| c[1] == 'o') | |
110 && (c[2] == 'G'|| c[2] == 'g') | |
111 && (c[3] == 'O'|| c[3] == 'o') | |
112 && (c[4] == 'U'|| c[4] == 'u') | |
113 && (c[5] == 'T'|| c[5] == 't')) | |
114 { | |
115 s->command = NGX_IMAP_LOGOUT; | |
116 | |
117 } else { | |
118 goto invalid; | |
119 } | |
120 break; | |
121 | |
122 case 10: | |
123 if ((c[0] == 'C'|| c[0] == 'c') | |
124 && (c[1] == 'A'|| c[1] == 'a') | |
125 && (c[2] == 'P'|| c[2] == 'p') | |
126 && (c[3] == 'A'|| c[3] == 'a') | |
127 && (c[4] == 'B'|| c[4] == 'b') | |
128 && (c[5] == 'I'|| c[5] == 'i') | |
129 && (c[6] == 'L'|| c[6] == 'l') | |
130 && (c[7] == 'I'|| c[7] == 'i') | |
131 && (c[8] == 'T'|| c[8] == 't') | |
132 && (c[9] == 'Y'|| c[9] == 'y')) | |
133 { | |
134 s->command = NGX_IMAP_CAPABILITY; | |
135 | |
136 } else { | |
137 goto invalid; | |
138 } | |
139 break; | |
140 | |
141 default: | |
142 goto invalid; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
143 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
144 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
145 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
146 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
147 state = sw_spaces_before_argument; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
148 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
149 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
150 state = sw_almost_done; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
151 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
152 case LF: |
527 | 153 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
154 } |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
155 break; |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
156 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
157 |
527 | 158 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { |
159 goto invalid; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
160 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
161 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
162 break; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
163 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
164 case sw_spaces_before_argument: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
165 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
166 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
167 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
168 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
169 state = sw_almost_done; |
527 | 170 s->arg_end = p; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
171 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
172 case LF: |
527 | 173 s->arg_end = p; |
174 goto done; | |
175 case '"': | |
176 if (s->args.nelts <= 2) { | |
177 s->quoted = 1; | |
178 s->arg_start = p + 1; | |
179 state = sw_argument; | |
180 break; | |
181 } | |
182 goto invalid; | |
183 case '{': | |
184 if (s->args.nelts <= 2) { | |
185 state = sw_literal; | |
186 break; | |
187 } | |
188 goto invalid; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
189 default: |
527 | 190 if (s->args.nelts <= 2) { |
191 s->arg_start = p; | |
192 state = sw_argument; | |
193 break; | |
194 } | |
195 goto invalid; | |
196 } | |
197 break; | |
198 | |
199 case sw_argument: | |
200 switch (ch) { | |
201 case '"': | |
202 if (!s->quoted) { | |
203 break; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
204 } |
527 | 205 s->quoted = 0; |
206 /* fall through */ | |
207 case ' ': | |
208 case CR: | |
209 case LF: | |
210 arg = ngx_array_push(&s->args); | |
211 if (arg == NULL) { | |
212 return NGX_ERROR; | |
213 } | |
214 arg->len = p - s->arg_start; | |
215 arg->data = s->arg_start; | |
216 s->arg_start = NULL; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
217 |
527 | 218 switch (ch) { |
219 case '"': | |
220 case ' ': | |
221 state = sw_spaces_before_argument; | |
222 break; | |
223 case CR: | |
224 state = sw_almost_done; | |
225 break; | |
226 case LF: | |
227 goto done; | |
228 } | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
229 break; |
543 | 230 case '\\': |
231 if (s->quoted) { | |
232 s->backslash = 1; | |
233 state = sw_backslash; | |
234 } | |
235 break; | |
236 } | |
237 break; | |
238 | |
239 case sw_backslash: | |
240 switch (ch) { | |
241 case CR: | |
242 case LF: | |
243 goto invalid; | |
244 default: | |
245 state = sw_argument; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
246 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
247 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
248 |
527 | 249 case sw_literal: |
250 if (ch >= '0' && ch <= '9') { | |
251 s->literal_len = s->literal_len * 10 + (ch - '0'); | |
252 break; | |
253 } | |
254 if (ch == '}') { | |
255 state = sw_start_literal_argument; | |
256 break; | |
257 } | |
543 | 258 if (ch == '+') { |
259 state = sw_no_sync_literal_argument; | |
260 break; | |
261 } | |
262 goto invalid; | |
263 | |
264 case sw_no_sync_literal_argument: | |
265 if (ch == '}') { | |
266 s->no_sync_literal = 1; | |
267 state = sw_start_literal_argument; | |
268 break; | |
269 } | |
527 | 270 goto invalid; |
271 | |
272 case sw_start_literal_argument: | |
273 switch (ch) { | |
274 case CR: | |
275 break; | |
276 case LF: | |
277 s->buffer->pos = p + 1; | |
278 s->arg_start = p + 1; | |
543 | 279 if (s->no_sync_literal == 0) { |
280 s->state = sw_literal_argument; | |
281 return NGX_IMAP_NEXT; | |
282 } | |
283 state = sw_literal_argument; | |
284 s->no_sync_literal = 0; | |
285 break; | |
286 default: | |
287 goto invalid; | |
527 | 288 } |
543 | 289 break; |
527 | 290 |
291 case sw_literal_argument: | |
529 | 292 if (s->literal_len && --s->literal_len) { |
527 | 293 break; |
294 } | |
295 | |
296 arg = ngx_array_push(&s->args); | |
297 if (arg == NULL) { | |
298 return NGX_ERROR; | |
299 } | |
300 arg->len = p + 1 - s->arg_start; | |
301 arg->data = s->arg_start; | |
302 s->arg_start = NULL; | |
303 state = sw_end_literal_argument; | |
304 | |
305 break; | |
306 | |
307 case sw_end_literal_argument: | |
308 switch (ch) { | |
309 case '{': | |
310 if (s->args.nelts <= 2) { | |
311 state = sw_literal; | |
312 break; | |
313 } | |
314 goto invalid; | |
315 case CR: | |
316 state = sw_almost_done; | |
317 break; | |
318 case LF: | |
319 goto done; | |
320 default: | |
529 | 321 state = sw_spaces_before_argument; |
322 break; | |
527 | 323 } |
324 break; | |
325 | |
326 case sw_almost_done: | |
327 switch (ch) { | |
328 case LF: | |
329 goto done; | |
330 default: | |
331 goto invalid; | |
332 } | |
333 } | |
334 } | |
335 | |
336 s->buffer->pos = p; | |
337 s->state = state; | |
338 | |
339 return NGX_AGAIN; | |
340 | |
341 done: | |
342 | |
343 s->buffer->pos = p + 1; | |
344 | |
345 if (s->arg_start) { | |
346 arg = ngx_array_push(&s->args); | |
347 if (arg == NULL) { | |
348 return NGX_ERROR; | |
349 } | |
350 arg->len = s->arg_end - s->arg_start; | |
351 arg->data = s->arg_start; | |
543 | 352 |
527 | 353 s->arg_start = NULL; |
354 s->cmd_start = NULL; | |
355 s->quoted = 0; | |
543 | 356 s->no_sync_literal = 0; |
527 | 357 s->literal_len = 0; |
358 } | |
359 | |
360 s->state = sw_start; | |
361 | |
362 return NGX_OK; | |
363 | |
364 invalid: | |
365 | |
366 s->state = sw_start; | |
367 s->quoted = 0; | |
543 | 368 s->no_sync_literal = 0; |
527 | 369 s->literal_len = 0; |
370 | |
371 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
372 } | |
373 | |
374 | |
375 ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s) | |
376 { | |
377 u_char ch, *p, *c, c0, c1, c2, c3; | |
378 ngx_str_t *arg; | |
379 enum { | |
380 sw_start = 0, | |
381 sw_spaces_before_argument, | |
382 sw_argument, | |
383 sw_almost_done | |
384 } state; | |
385 | |
386 state = s->state; | |
387 | |
388 for (p = s->buffer->pos; p < s->buffer->last; p++) { | |
389 ch = *p; | |
390 | |
391 switch (state) { | |
392 | |
393 /* POP3 command */ | |
394 case sw_start: | |
395 if (ch == ' ' || ch == CR || ch == LF) { | |
396 c = s->buffer->start; | |
397 | |
398 if (p - c == 4) { | |
399 | |
400 c0 = ngx_toupper(c[0]); | |
401 c1 = ngx_toupper(c[1]); | |
402 c2 = ngx_toupper(c[2]); | |
403 c3 = ngx_toupper(c[3]); | |
404 | |
405 if (c0 == 'U' && c1 == 'S' && c2 == 'E' && c3 == 'R') | |
406 { | |
407 s->command = NGX_POP3_USER; | |
408 | |
409 } else if (c0 == 'P' && c1 == 'A' && c2 == 'S' && c3 == 'S') | |
410 { | |
411 s->command = NGX_POP3_PASS; | |
412 | |
413 } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T') | |
414 { | |
415 s->command = NGX_POP3_QUIT; | |
416 | |
417 } else if (c0 == 'C' && c1 == 'A' && c2 == 'P' && c3 == 'A') | |
418 { | |
419 s->command = NGX_POP3_CAPA; | |
420 | |
421 } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P') | |
422 { | |
423 s->command = NGX_POP3_NOOP; | |
424 | |
425 } else { | |
426 goto invalid; | |
427 } | |
428 | |
429 } else { | |
430 goto invalid; | |
431 } | |
432 | |
433 switch (ch) { | |
434 case ' ': | |
435 state = sw_spaces_before_argument; | |
436 break; | |
437 case CR: | |
438 state = sw_almost_done; | |
439 break; | |
440 case LF: | |
441 goto done; | |
442 } | |
443 break; | |
444 } | |
445 | |
446 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { | |
447 goto invalid; | |
448 } | |
449 | |
450 break; | |
451 | |
452 case sw_spaces_before_argument: | |
453 switch (ch) { | |
454 case ' ': | |
455 break; | |
456 case CR: | |
457 state = sw_almost_done; | |
458 s->arg_end = p; | |
459 break; | |
460 case LF: | |
461 s->arg_end = p; | |
462 goto done; | |
463 default: | |
464 if (s->args.nelts <= 2) { | |
465 state = sw_argument; | |
466 s->arg_start = p; | |
467 break; | |
468 } | |
469 goto invalid; | |
470 } | |
471 break; | |
472 | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
473 case sw_argument: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
474 switch (ch) { |
543 | 475 |
476 /* | |
477 * the space should be considered part of the at username | |
478 * or password, but not of argument in other commands | |
479 * | |
480 * case ' ': | |
481 */ | |
482 | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
483 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
484 case LF: |
501 | 485 arg = ngx_array_push(&s->args); |
486 if (arg == NULL) { | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
487 return NGX_ERROR; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
488 } |
527 | 489 arg->len = p - s->arg_start; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
490 arg->data = s->arg_start; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
491 s->arg_start = NULL; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
492 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
493 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
494 case ' ': |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
495 state = sw_spaces_before_argument; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
496 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
497 case CR: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
498 state = sw_almost_done; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
499 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
500 case LF: |
527 | 501 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
502 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
503 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
504 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
505 default: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
506 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
507 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
508 break; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
509 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
510 case sw_almost_done: |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
511 switch (ch) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
512 case LF: |
527 | 513 goto done; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
514 default: |
527 | 515 goto invalid; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
516 } |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
517 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
518 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
519 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
520 s->buffer->pos = p; |
527 | 521 s->state = state; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
522 |
527 | 523 return NGX_AGAIN; |
524 | |
525 done: | |
526 | |
527 s->buffer->pos = p + 1; | |
528 | |
529 if (s->arg_start) { | |
530 arg = ngx_array_push(&s->args); | |
531 if (arg == NULL) { | |
532 return NGX_ERROR; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
533 } |
527 | 534 arg->len = s->arg_end - s->arg_start; |
535 arg->data = s->arg_start; | |
536 s->arg_start = NULL; | |
537 } | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
538 |
527 | 539 s->state = sw_start; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
417
diff
changeset
|
540 |
527 | 541 return NGX_OK; |
542 | |
543 invalid: | |
544 | |
545 s->state = sw_start; | |
546 | |
547 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
548 } |