Mercurial > hg > nginx
comparison src/imap/ngx_imap_parse.c @ 527:7fa11e5c6e96 release-0.1.38
nginx-0.1.38-RELEASE import
*) 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.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 08 Jul 2005 14:34:20 +0000 |
parents | d4ea69372b94 |
children | e5d7d0334fdb |
comparison
equal
deleted
inserted
replaced
526:e31ce4d8b8e6 | 527:7fa11e5c6e96 |
---|---|
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_event.h> | 9 #include <ngx_event.h> |
10 #include <ngx_imap.h> | 10 #include <ngx_imap.h> |
11 | 11 |
12 | 12 |
13 ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s) | 13 ngx_int_t ngx_imap_parse_command(ngx_imap_session_t *s) |
14 { | 14 { |
15 u_char ch, *p, *c; | 15 u_char ch, *p, *c; |
16 ngx_str_t *arg; | 16 ngx_str_t *arg; |
17 enum { | 17 enum { |
18 sw_start = 0, | 18 sw_start = 0, |
19 sw_spaces_before_command, | |
20 sw_command, | |
19 sw_spaces_before_argument, | 21 sw_spaces_before_argument, |
20 sw_argument, | 22 sw_argument, |
21 sw_almost_done, | 23 sw_literal, |
22 sw_done | 24 sw_start_literal_argument, |
25 sw_literal_argument, | |
26 sw_end_literal_argument, | |
27 sw_almost_done | |
23 } state; | 28 } state; |
24 | 29 |
25 state = s->state; | 30 state = s->state; |
26 p = s->buffer->pos; | 31 |
27 | 32 for (p = s->buffer->pos; p < s->buffer->last; p++) { |
28 while (p < s->buffer->last && state < sw_done) { | 33 ch = *p; |
29 ch = *p++; | |
30 | 34 |
31 switch (state) { | 35 switch (state) { |
32 | 36 |
37 /* IMAP tag */ | |
38 case sw_start: | |
39 switch (ch) { | |
40 case ' ': | |
41 s->tag.len = p - s->buffer->start + 1; | |
42 s->tag.data = s->buffer->start; | |
43 state = sw_spaces_before_command; | |
44 break; | |
45 case CR: | |
46 s->state = sw_start; | |
47 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
48 case LF: | |
49 s->state = sw_start; | |
50 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
51 } | |
52 break; | |
53 | |
54 case sw_spaces_before_command: | |
55 switch (ch) { | |
56 case ' ': | |
57 break; | |
58 case CR: | |
59 s->state = sw_start; | |
60 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
61 case LF: | |
62 s->state = sw_start; | |
63 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
64 default: | |
65 s->cmd_start = p; | |
66 state = sw_command; | |
67 break; | |
68 } | |
69 break; | |
70 | |
71 case sw_command: | |
72 if (ch == ' ' || ch == CR || ch == LF) { | |
73 | |
74 c = s->cmd_start; | |
75 | |
76 switch (p - c) { | |
77 | |
78 case 4: | |
79 if ((c[0] == 'N' || c[0] == 'n') | |
80 && (c[1] == 'O'|| c[1] == 'o') | |
81 && (c[2] == 'O'|| c[2] == 'o') | |
82 && (c[3] == 'P'|| c[3] == 'p')) | |
83 { | |
84 s->command = NGX_IMAP_NOOP; | |
85 | |
86 } else { | |
87 goto invalid; | |
88 } | |
89 break; | |
90 | |
91 case 5: | |
92 if ((c[0] == 'L'|| c[0] == 'l') | |
93 && (c[1] == 'O'|| c[1] == 'o') | |
94 && (c[2] == 'G'|| c[2] == 'g') | |
95 && (c[3] == 'I'|| c[3] == 'i') | |
96 && (c[4] == 'N'|| c[4] == 'n')) | |
97 { | |
98 s->command = NGX_IMAP_LOGIN; | |
99 | |
100 } else { | |
101 goto invalid; | |
102 } | |
103 break; | |
104 | |
105 case 6: | |
106 if ((c[0] == 'L'|| c[0] == 'l') | |
107 && (c[1] == 'O'|| c[1] == 'o') | |
108 && (c[2] == 'G'|| c[2] == 'g') | |
109 && (c[3] == 'O'|| c[3] == 'o') | |
110 && (c[4] == 'U'|| c[4] == 'u') | |
111 && (c[5] == 'T'|| c[5] == 't')) | |
112 { | |
113 s->command = NGX_IMAP_LOGOUT; | |
114 | |
115 } else { | |
116 goto invalid; | |
117 } | |
118 break; | |
119 | |
120 case 10: | |
121 if ((c[0] == 'C'|| c[0] == 'c') | |
122 && (c[1] == 'A'|| c[1] == 'a') | |
123 && (c[2] == 'P'|| c[2] == 'p') | |
124 && (c[3] == 'A'|| c[3] == 'a') | |
125 && (c[4] == 'B'|| c[4] == 'b') | |
126 && (c[5] == 'I'|| c[5] == 'i') | |
127 && (c[6] == 'L'|| c[6] == 'l') | |
128 && (c[7] == 'I'|| c[7] == 'i') | |
129 && (c[8] == 'T'|| c[8] == 't') | |
130 && (c[9] == 'Y'|| c[9] == 'y')) | |
131 { | |
132 s->command = NGX_IMAP_CAPABILITY; | |
133 | |
134 } else { | |
135 goto invalid; | |
136 } | |
137 break; | |
138 | |
139 default: | |
140 goto invalid; | |
141 } | |
142 | |
143 switch (ch) { | |
144 case ' ': | |
145 state = sw_spaces_before_argument; | |
146 break; | |
147 case CR: | |
148 state = sw_almost_done; | |
149 break; | |
150 case LF: | |
151 goto done; | |
152 } | |
153 break; | |
154 } | |
155 | |
156 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { | |
157 goto invalid; | |
158 } | |
159 | |
160 break; | |
161 | |
162 case sw_spaces_before_argument: | |
163 switch (ch) { | |
164 case ' ': | |
165 break; | |
166 case CR: | |
167 state = sw_almost_done; | |
168 s->arg_end = p; | |
169 break; | |
170 case LF: | |
171 s->arg_end = p; | |
172 goto done; | |
173 case '"': | |
174 if (s->args.nelts <= 2) { | |
175 s->quoted = 1; | |
176 s->arg_start = p + 1; | |
177 state = sw_argument; | |
178 break; | |
179 } | |
180 goto invalid; | |
181 case '{': | |
182 if (s->args.nelts <= 2) { | |
183 state = sw_literal; | |
184 break; | |
185 } | |
186 goto invalid; | |
187 default: | |
188 if (s->args.nelts <= 2) { | |
189 s->arg_start = p; | |
190 state = sw_argument; | |
191 break; | |
192 } | |
193 goto invalid; | |
194 } | |
195 break; | |
196 | |
197 case sw_argument: | |
198 switch (ch) { | |
199 case '"': | |
200 if (!s->quoted) { | |
201 break; | |
202 } | |
203 s->quoted = 0; | |
204 /* fall through */ | |
205 case ' ': | |
206 case CR: | |
207 case LF: | |
208 arg = ngx_array_push(&s->args); | |
209 if (arg == NULL) { | |
210 return NGX_ERROR; | |
211 } | |
212 arg->len = p - s->arg_start; | |
213 arg->data = s->arg_start; | |
214 s->arg_start = NULL; | |
215 | |
216 switch (ch) { | |
217 case '"': | |
218 case ' ': | |
219 state = sw_spaces_before_argument; | |
220 break; | |
221 case CR: | |
222 state = sw_almost_done; | |
223 break; | |
224 case LF: | |
225 goto done; | |
226 } | |
227 break; | |
228 } | |
229 break; | |
230 | |
231 case sw_literal: | |
232 if (ch >= '0' && ch <= '9') { | |
233 s->literal_len = s->literal_len * 10 + (ch - '0'); | |
234 break; | |
235 } | |
236 if (ch == '}') { | |
237 state = sw_start_literal_argument; | |
238 break; | |
239 } | |
240 goto invalid; | |
241 | |
242 case sw_start_literal_argument: | |
243 switch (ch) { | |
244 case CR: | |
245 break; | |
246 case LF: | |
247 s->buffer->pos = p + 1; | |
248 s->arg_start = p + 1; | |
249 s->state = sw_literal_argument; | |
250 return NGX_IMAP_NEXT; | |
251 } | |
252 goto invalid; | |
253 | |
254 case sw_literal_argument: | |
255 if (--s->literal_len) { | |
256 break; | |
257 } | |
258 | |
259 arg = ngx_array_push(&s->args); | |
260 if (arg == NULL) { | |
261 return NGX_ERROR; | |
262 } | |
263 arg->len = p + 1 - s->arg_start; | |
264 arg->data = s->arg_start; | |
265 s->arg_start = NULL; | |
266 state = sw_end_literal_argument; | |
267 | |
268 break; | |
269 | |
270 case sw_end_literal_argument: | |
271 switch (ch) { | |
272 case '{': | |
273 if (s->args.nelts <= 2) { | |
274 state = sw_literal; | |
275 break; | |
276 } | |
277 goto invalid; | |
278 case CR: | |
279 state = sw_almost_done; | |
280 break; | |
281 case LF: | |
282 goto done; | |
283 default: | |
284 goto invalid; | |
285 } | |
286 break; | |
287 | |
288 case sw_almost_done: | |
289 switch (ch) { | |
290 case LF: | |
291 goto done; | |
292 default: | |
293 goto invalid; | |
294 } | |
295 } | |
296 } | |
297 | |
298 s->buffer->pos = p; | |
299 s->state = state; | |
300 | |
301 return NGX_AGAIN; | |
302 | |
303 done: | |
304 | |
305 s->buffer->pos = p + 1; | |
306 | |
307 if (s->arg_start) { | |
308 arg = ngx_array_push(&s->args); | |
309 if (arg == NULL) { | |
310 return NGX_ERROR; | |
311 } | |
312 arg->len = s->arg_end - s->arg_start; | |
313 arg->data = s->arg_start; | |
314 s->arg_start = NULL; | |
315 s->cmd_start = NULL; | |
316 s->quoted = 0; | |
317 s->literal_len = 0; | |
318 } | |
319 | |
320 s->state = sw_start; | |
321 | |
322 return NGX_OK; | |
323 | |
324 invalid: | |
325 | |
326 s->state = sw_start; | |
327 s->quoted = 0; | |
328 s->literal_len = 0; | |
329 | |
330 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
331 } | |
332 | |
333 | |
334 ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s) | |
335 { | |
336 u_char ch, *p, *c, c0, c1, c2, c3; | |
337 ngx_str_t *arg; | |
338 enum { | |
339 sw_start = 0, | |
340 sw_spaces_before_argument, | |
341 sw_argument, | |
342 sw_almost_done | |
343 } state; | |
344 | |
345 state = s->state; | |
346 | |
347 for (p = s->buffer->pos; p < s->buffer->last; p++) { | |
348 ch = *p; | |
349 | |
350 switch (state) { | |
351 | |
33 /* POP3 command */ | 352 /* POP3 command */ |
34 | |
35 case sw_start: | 353 case sw_start: |
36 if (ch == ' ' || ch == CR || ch == LF) { | 354 if (ch == ' ' || ch == CR || ch == LF) { |
37 c = s->buffer->start; | 355 c = s->buffer->start; |
38 | 356 |
39 if (p - 1 - c == 4) { | 357 if (p - c == 4) { |
40 | 358 |
41 if (c[0] == 'U' && c[1] == 'S' | 359 c0 = ngx_toupper(c[0]); |
42 && c[2] == 'E' && c[3] == 'R') | 360 c1 = ngx_toupper(c[1]); |
361 c2 = ngx_toupper(c[2]); | |
362 c3 = ngx_toupper(c[3]); | |
363 | |
364 if (c0 == 'U' && c1 == 'S' && c2 == 'E' && c3 == 'R') | |
43 { | 365 { |
44 s->command = NGX_POP3_USER; | 366 s->command = NGX_POP3_USER; |
45 | 367 |
46 } else if (c[0] == 'P' && c[1] == 'A' | 368 } else if (c0 == 'P' && c1 == 'A' && c2 == 'S' && c3 == 'S') |
47 && c[2] == 'S' && c[3] == 'S') | |
48 { | 369 { |
49 s->command = NGX_POP3_PASS; | 370 s->command = NGX_POP3_PASS; |
50 | 371 |
51 } else if (c[0] == 'Q' && c[1] == 'U' | 372 } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T') |
52 && c[2] == 'I' && c[3] == 'T') | |
53 { | 373 { |
54 s->command = NGX_POP3_QUIT; | 374 s->command = NGX_POP3_QUIT; |
55 | 375 |
56 #if 0 | 376 } else if (c0 == 'C' && c1 == 'A' && c2 == 'P' && c3 == 'A') |
57 } else if (c[0] == 'N' && c[1] == 'O' | 377 { |
58 && c[2] == 'O' && c[3] == 'P') | 378 s->command = NGX_POP3_CAPA; |
379 | |
380 } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P') | |
59 { | 381 { |
60 s->command = NGX_POP3_NOOP; | 382 s->command = NGX_POP3_NOOP; |
61 #endif | |
62 | 383 |
63 } else { | 384 } else { |
64 s->state = sw_start; | 385 goto invalid; |
65 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
66 } | 386 } |
67 | 387 |
68 } else { | 388 } else { |
69 s->state = sw_start; | 389 goto invalid; |
70 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
71 } | 390 } |
72 | 391 |
73 switch (ch) { | 392 switch (ch) { |
74 case ' ': | 393 case ' ': |
75 state = sw_spaces_before_argument; | 394 state = sw_spaces_before_argument; |
76 break; | 395 break; |
77 case CR: | 396 case CR: |
78 state = sw_almost_done; | 397 state = sw_almost_done; |
79 break; | 398 break; |
80 case LF: | 399 case LF: |
81 state = sw_done; | 400 goto done; |
82 break; | 401 } |
83 } | 402 break; |
84 break; | 403 } |
85 } | 404 |
86 | 405 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { |
87 if (ch < 'A' || ch > 'Z') { | 406 goto invalid; |
88 s->state = sw_start; | 407 } |
89 return NGX_IMAP_PARSE_INVALID_COMMAND; | 408 |
90 } | 409 break; |
91 | 410 |
92 break; | |
93 | |
94 /* the spaces before the argument */ | |
95 case sw_spaces_before_argument: | 411 case sw_spaces_before_argument: |
96 switch (ch) { | 412 switch (ch) { |
97 case ' ': | 413 case ' ': |
98 break; | 414 break; |
99 case CR: | 415 case CR: |
100 state = sw_almost_done; | 416 state = sw_almost_done; |
101 s->arg_end = p - 1; | 417 s->arg_end = p; |
102 break; | 418 break; |
103 case LF: | 419 case LF: |
104 state = sw_done; | 420 s->arg_end = p; |
105 s->arg_end = p - 1; | 421 goto done; |
106 break; | 422 default: |
107 default: | 423 if (s->args.nelts <= 2) { |
108 if (s->args.nelts > 2) { | 424 state = sw_argument; |
109 s->state = sw_start; | 425 s->arg_start = p; |
110 return NGX_IMAP_PARSE_INVALID_COMMAND; | 426 break; |
111 } | 427 } |
112 | 428 goto invalid; |
113 state = sw_argument; | 429 } |
114 s->arg_start = p - 1; | 430 break; |
115 break; | 431 |
116 } | |
117 break; | |
118 | |
119 /* the argument */ | |
120 case sw_argument: | 432 case sw_argument: |
121 switch (ch) { | 433 switch (ch) { |
122 case ' ': | 434 case ' ': |
123 case CR: | 435 case CR: |
124 case LF: | 436 case LF: |
125 arg = ngx_array_push(&s->args); | 437 arg = ngx_array_push(&s->args); |
126 if (arg == NULL) { | 438 if (arg == NULL) { |
127 return NGX_ERROR; | 439 return NGX_ERROR; |
128 } | 440 } |
129 arg->len = p - 1 - s->arg_start; | 441 arg->len = p - s->arg_start; |
130 arg->data = s->arg_start; | 442 arg->data = s->arg_start; |
131 s->arg_start = NULL; | 443 s->arg_start = NULL; |
132 | 444 |
133 switch (ch) { | 445 switch (ch) { |
134 case ' ': | 446 case ' ': |
136 break; | 448 break; |
137 case CR: | 449 case CR: |
138 state = sw_almost_done; | 450 state = sw_almost_done; |
139 break; | 451 break; |
140 case LF: | 452 case LF: |
141 state = sw_done; | 453 goto done; |
142 break; | 454 } |
143 } | 455 break; |
144 break; | 456 |
145 | 457 default: |
146 default: | 458 break; |
147 break; | 459 } |
148 } | 460 break; |
149 break; | 461 |
150 | |
151 /* end of request line */ | |
152 case sw_almost_done: | 462 case sw_almost_done: |
153 switch (ch) { | 463 switch (ch) { |
154 case LF: | 464 case LF: |
155 state = sw_done; | 465 goto done; |
156 break; | 466 default: |
157 default: | 467 goto invalid; |
158 s->state = sw_start; | 468 } |
159 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
160 } | |
161 break; | |
162 | |
163 /* suppress warning */ | |
164 case sw_done: | |
165 break; | |
166 } | 469 } |
167 } | 470 } |
168 | 471 |
169 s->buffer->pos = p; | 472 s->buffer->pos = p; |
170 | 473 s->state = state; |
171 if (state == sw_done) { | 474 |
172 if (s->arg_start) { | 475 return NGX_AGAIN; |
173 arg = ngx_array_push(&s->args); | 476 |
174 if (arg == NULL) { | 477 done: |
175 return NGX_ERROR; | 478 |
176 } | 479 s->buffer->pos = p + 1; |
177 arg->len = s->arg_end - s->arg_start; | 480 |
178 arg->data = s->arg_start; | 481 if (s->arg_start) { |
179 s->arg_start = NULL; | 482 arg = ngx_array_push(&s->args); |
483 if (arg == NULL) { | |
484 return NGX_ERROR; | |
180 } | 485 } |
181 | 486 arg->len = s->arg_end - s->arg_start; |
182 s->state = sw_start; | 487 arg->data = s->arg_start; |
183 return NGX_OK; | 488 s->arg_start = NULL; |
184 | |
185 } else { | |
186 s->state = state; | |
187 return NGX_AGAIN; | |
188 } | 489 } |
490 | |
491 s->state = sw_start; | |
492 | |
493 return NGX_OK; | |
494 | |
495 invalid: | |
496 | |
497 s->state = sw_start; | |
498 | |
499 return NGX_IMAP_PARSE_INVALID_COMMAND; | |
189 } | 500 } |