Mercurial > hg > nginx-ranges
comparison src/http/ngx_http_parse.c @ 28:7ca9bdc82b3f NGINX_0_1_14
nginx 0.1.14
*) Feature: the autoconfiguration directives:
--http-client-body-temp-path=PATH, --http-proxy-temp-path=PATH, and
--http-fastcgi-temp-path=PATH
*) Change: the directory name for the temporary files with the client
request body is specified by directive client_body_temp_path, by
default it is <prefix>/client_body_temp.
*) Feature: the ngx_http_fastcgi_module and the directives:
fastcgi_pass, fastcgi_root, fastcgi_index, fastcgi_params,
fastcgi_connect_timeout, fastcgi_send_timeout, fastcgi_read_timeout,
fastcgi_send_lowat, fastcgi_header_buffer_size, fastcgi_buffers,
fastcgi_busy_buffers_size, fastcgi_temp_path,
fastcgi_max_temp_file_size, fastcgi_temp_file_write_size,
fastcgi_next_upstream, and fastcgi_x_powered_by.
*) Bugfix: the "[alert] zero size buf" error; bug appeared in 0.1.3.
*) Change: the URI must be specified after the host name in the
proxy_pass directive.
*) Change: the %3F symbol in the URI was considered as the argument
string start.
*) Feature: the unix domain sockets support in the
ngx_http_proxy_module.
*) Feature: the ssl_engine and ssl_ciphers directives.
Thanks to Sergey Skvortsov for SSL-accelerator.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Tue, 18 Jan 2005 00:00:00 +0300 |
parents | 8b6db3bda591 |
children | aab2ea7c0458 |
comparison
equal
deleted
inserted
replaced
27:66901c2556fd | 28:7ca9bdc82b3f |
---|---|
32 sw_http_HTTP, | 32 sw_http_HTTP, |
33 sw_first_major_digit, | 33 sw_first_major_digit, |
34 sw_major_digit, | 34 sw_major_digit, |
35 sw_first_minor_digit, | 35 sw_first_minor_digit, |
36 sw_minor_digit, | 36 sw_minor_digit, |
37 sw_almost_done, | 37 sw_almost_done |
38 sw_done | |
39 } state; | 38 } state; |
40 | 39 |
41 state = r->state; | 40 state = r->state; |
42 p = b->pos; | 41 |
43 | 42 for (p = b->pos; p < b->last; p++) { |
44 while (p < b->last && state < sw_done) { | 43 ch = *p; |
45 ch = *p++; | |
46 | 44 |
47 /* gcc 2.95.2 and msvc 6.0 compile this switch as an jump table */ | 45 /* gcc 2.95.2 and msvc 6.0 compile this switch as an jump table */ |
48 | 46 |
49 switch (state) { | 47 switch (state) { |
50 | 48 |
51 /* HTTP methods: GET, HEAD, POST */ | 49 /* HTTP methods: GET, HEAD, POST */ |
52 case sw_start: | 50 case sw_start: |
53 r->request_start = p - 1; | 51 r->request_start = p; |
54 | 52 |
55 if (ch == CR || ch == LF) { | 53 if (ch == CR || ch == LF) { |
56 break; | 54 break; |
57 } | 55 } |
58 | 56 |
63 state = sw_method; | 61 state = sw_method; |
64 break; | 62 break; |
65 | 63 |
66 case sw_method: | 64 case sw_method: |
67 if (ch == ' ') { | 65 if (ch == ' ') { |
68 r->method_end = p - 1; | 66 r->method_end = p; |
69 m = r->request_start; | 67 m = r->request_start; |
70 | 68 |
71 if (r->method_end - m == 3) { | 69 if (p - m == 3) { |
72 | 70 |
73 if (m[0] == 'G' && m[1] == 'E' && m[2] == 'T') { | 71 if (m[0] == 'G' && m[1] == 'E' && m[2] == 'T') { |
74 r->method = NGX_HTTP_GET; | 72 r->method = NGX_HTTP_GET; |
75 } | 73 } |
76 | 74 |
77 } else if (r->method_end - m == 4) { | 75 } else if (p - m == 4) { |
78 | 76 |
79 if (m[0] == 'P' && m[1] == 'O' | 77 if (m[0] == 'P' && m[1] == 'O' |
80 && m[2] == 'T' && m[3] == 'T') | 78 && m[2] == 'S' && m[3] == 'T') |
81 { | 79 { |
82 r->method = NGX_HTTP_POST; | 80 r->method = NGX_HTTP_POST; |
83 | 81 |
84 } else if (m[0] == 'H' && m[1] == 'E' | 82 } else if (m[0] == 'H' && m[1] == 'E' |
85 && m[2] == 'A' && m[3] == 'D') | 83 && m[2] == 'A' && m[3] == 'D') |
111 | 109 |
112 /* space* before URI */ | 110 /* space* before URI */ |
113 case sw_spaces_before_uri: | 111 case sw_spaces_before_uri: |
114 switch (ch) { | 112 switch (ch) { |
115 case '/': | 113 case '/': |
116 r->uri_start = p - 1; | 114 r->uri_start = p; |
117 state = sw_after_slash_in_uri; | 115 state = sw_after_slash_in_uri; |
118 break; | 116 break; |
119 case ' ': | 117 case ' ': |
120 break; | 118 break; |
121 default: | 119 default: |
122 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { | 120 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { |
123 r->schema_start = p - 1; | 121 r->schema_start = p; |
124 state = sw_schema; | 122 state = sw_schema; |
125 break; | 123 break; |
126 } | 124 } |
127 return NGX_HTTP_PARSE_INVALID_REQUEST; | 125 return NGX_HTTP_PARSE_INVALID_REQUEST; |
128 } | 126 } |
129 break; | 127 break; |
130 | 128 |
131 case sw_schema: | 129 case sw_schema: |
132 switch (ch) { | 130 switch (ch) { |
133 case ':': | 131 case ':': |
134 r->schema_end = p - 1; | 132 r->schema_end = p; |
135 state = sw_schema_slash; | 133 state = sw_schema_slash; |
136 break; | 134 break; |
137 default: | 135 default: |
138 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { | 136 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { |
139 break; | 137 break; |
153 break; | 151 break; |
154 | 152 |
155 case sw_schema_slash_slash: | 153 case sw_schema_slash_slash: |
156 switch (ch) { | 154 switch (ch) { |
157 case '/': | 155 case '/': |
158 r->host_start = p - 1; | 156 r->host_start = p; |
159 state = sw_host; | 157 state = sw_host; |
160 break; | 158 break; |
161 default: | 159 default: |
162 return NGX_HTTP_PARSE_INVALID_REQUEST; | 160 return NGX_HTTP_PARSE_INVALID_REQUEST; |
163 } | 161 } |
164 break; | 162 break; |
165 | 163 |
166 case sw_host: | 164 case sw_host: |
167 switch (ch) { | 165 switch (ch) { |
168 case ':': | 166 case ':': |
169 r->host_end = p - 1; | 167 r->host_end = p; |
170 state = sw_port; | 168 state = sw_port; |
171 break; | 169 break; |
172 case '/': | 170 case '/': |
173 r->host_end = p - 1; | 171 r->host_end = p; |
174 r->uri_start = p - 1; | 172 r->uri_start = p; |
175 state = sw_after_slash_in_uri; | 173 state = sw_after_slash_in_uri; |
176 break; | 174 break; |
177 default: | 175 default: |
178 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') | 176 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') |
179 || (ch >= '0' && ch <= '9') || ch == '.' || ch == '-') | 177 || (ch >= '0' && ch <= '9') || ch == '.' || ch == '-') |
185 break; | 183 break; |
186 | 184 |
187 case sw_port: | 185 case sw_port: |
188 switch (ch) { | 186 switch (ch) { |
189 case '/': | 187 case '/': |
190 r->port_end = p - 1; | 188 r->port_end = p; |
191 r->uri_start = p - 1; | 189 r->uri_start = p; |
192 state = sw_after_slash_in_uri; | 190 state = sw_after_slash_in_uri; |
193 break; | 191 break; |
194 default: | 192 default: |
195 if (ch < '0' && ch > '9') { | 193 if (ch < '0' && ch > '9') { |
196 return NGX_HTTP_PARSE_INVALID_REQUEST; | 194 return NGX_HTTP_PARSE_INVALID_REQUEST; |
201 | 199 |
202 /* check "/.", "//", "%", and "\" (Win32) in URI */ | 200 /* check "/.", "//", "%", and "\" (Win32) in URI */ |
203 case sw_after_slash_in_uri: | 201 case sw_after_slash_in_uri: |
204 switch (ch) { | 202 switch (ch) { |
205 case CR: | 203 case CR: |
206 r->uri_end = p - 1; | 204 r->uri_end = p; |
207 r->http_minor = 9; | 205 r->http_minor = 9; |
208 state = sw_almost_done; | 206 state = sw_almost_done; |
209 break; | 207 break; |
210 case LF: | 208 case LF: |
211 r->uri_end = p - 1; | 209 r->uri_end = p; |
212 r->http_minor = 9; | 210 r->http_minor = 9; |
213 state = sw_done; | 211 goto done; |
214 break; | |
215 case ' ': | 212 case ' ': |
216 r->uri_end = p - 1; | 213 r->uri_end = p; |
217 state = sw_http_09; | 214 state = sw_http_09; |
218 break; | 215 break; |
219 case '.': | 216 case '.': |
220 r->complex_uri = 1; | 217 r->complex_uri = 1; |
221 state = sw_uri; | 218 state = sw_uri; |
231 #endif | 228 #endif |
232 case '/': | 229 case '/': |
233 r->complex_uri = 1; | 230 r->complex_uri = 1; |
234 break; | 231 break; |
235 case '?': | 232 case '?': |
236 r->args_start = p; | 233 r->args_start = p + 1; |
237 state = sw_uri; | 234 state = sw_uri; |
238 break; | 235 break; |
239 default: | 236 default: |
240 state = sw_check_uri; | 237 state = sw_check_uri; |
241 break; | 238 break; |
244 | 241 |
245 /* check "/", "%" and "\" (Win32) in URI */ | 242 /* check "/", "%" and "\" (Win32) in URI */ |
246 case sw_check_uri: | 243 case sw_check_uri: |
247 switch (ch) { | 244 switch (ch) { |
248 case CR: | 245 case CR: |
249 r->uri_end = p - 1; | 246 r->uri_end = p; |
250 r->http_minor = 9; | 247 r->http_minor = 9; |
251 state = sw_almost_done; | 248 state = sw_almost_done; |
252 break; | 249 break; |
253 case LF: | 250 case LF: |
254 r->uri_end = p - 1; | 251 r->uri_end = p; |
255 r->http_minor = 9; | 252 r->http_minor = 9; |
256 state = sw_done; | 253 goto done; |
257 break; | |
258 case ' ': | 254 case ' ': |
259 r->uri_end = p - 1; | 255 r->uri_end = p; |
260 state = sw_http_09; | 256 state = sw_http_09; |
261 break; | 257 break; |
262 case '.': | 258 case '.': |
263 r->uri_ext = p; | 259 r->uri_ext = p + 1; |
264 break; | 260 break; |
265 #if (NGX_WIN32) | 261 #if (NGX_WIN32) |
266 case '\\': | 262 case '\\': |
267 r->complex_uri = 1; | 263 r->complex_uri = 1; |
268 state = sw_after_slash_in_uri; | 264 state = sw_after_slash_in_uri; |
275 case '%': | 271 case '%': |
276 r->quoted_uri = 1; | 272 r->quoted_uri = 1; |
277 state = sw_uri; | 273 state = sw_uri; |
278 break; | 274 break; |
279 case '?': | 275 case '?': |
280 r->args_start = p; | 276 r->args_start = p + 1; |
281 state = sw_uri; | 277 state = sw_uri; |
282 break; | 278 break; |
283 } | 279 } |
284 break; | 280 break; |
285 | 281 |
286 /* URI */ | 282 /* URI */ |
287 case sw_uri: | 283 case sw_uri: |
288 switch (ch) { | 284 switch (ch) { |
289 case CR: | 285 case CR: |
290 r->uri_end = p - 1; | 286 r->uri_end = p; |
291 r->http_minor = 9; | 287 r->http_minor = 9; |
292 state = sw_almost_done; | 288 state = sw_almost_done; |
293 break; | 289 break; |
294 case LF: | 290 case LF: |
295 r->uri_end = p - 1; | 291 r->uri_end = p; |
296 r->http_minor = 9; | 292 r->http_minor = 9; |
297 state = sw_done; | 293 goto done; |
298 break; | |
299 case ' ': | 294 case ' ': |
300 r->uri_end = p - 1; | 295 r->uri_end = p; |
301 state = sw_http_09; | 296 state = sw_http_09; |
302 break; | 297 break; |
303 } | 298 } |
304 break; | 299 break; |
305 | 300 |
312 r->http_minor = 9; | 307 r->http_minor = 9; |
313 state = sw_almost_done; | 308 state = sw_almost_done; |
314 break; | 309 break; |
315 case LF: | 310 case LF: |
316 r->http_minor = 9; | 311 r->http_minor = 9; |
317 state = sw_done; | 312 goto done; |
318 break; | |
319 case 'H': | 313 case 'H': |
314 r->http_protocol.data = p; | |
320 state = sw_http_H; | 315 state = sw_http_H; |
321 break; | 316 break; |
322 default: | 317 default: |
323 return NGX_HTTP_PARSE_INVALID_REQUEST; | 318 return NGX_HTTP_PARSE_INVALID_REQUEST; |
324 } | 319 } |
404 state = sw_almost_done; | 399 state = sw_almost_done; |
405 break; | 400 break; |
406 } | 401 } |
407 | 402 |
408 if (ch == LF) { | 403 if (ch == LF) { |
409 state = sw_done; | 404 goto done; |
410 break; | |
411 } | 405 } |
412 | 406 |
413 if (ch < '0' || ch > '9') { | 407 if (ch < '0' || ch > '9') { |
414 return NGX_HTTP_PARSE_INVALID_REQUEST; | 408 return NGX_HTTP_PARSE_INVALID_REQUEST; |
415 } | 409 } |
417 r->http_minor = r->http_minor * 10 + ch - '0'; | 411 r->http_minor = r->http_minor * 10 + ch - '0'; |
418 break; | 412 break; |
419 | 413 |
420 /* end of request line */ | 414 /* end of request line */ |
421 case sw_almost_done: | 415 case sw_almost_done: |
422 r->request_end = p - 2; | 416 r->request_end = p - 1; |
423 switch (ch) { | 417 switch (ch) { |
424 case LF: | 418 case LF: |
425 state = sw_done; | 419 goto done; |
426 break; | 420 default: |
427 default: | 421 return NGX_HTTP_PARSE_INVALID_REQUEST; |
428 return NGX_HTTP_PARSE_INVALID_REQUEST; | 422 } |
429 } | |
430 break; | |
431 | |
432 /* suppress warning */ | |
433 case sw_done: | |
434 break; | 423 break; |
435 } | 424 } |
436 } | 425 } |
437 | 426 |
438 b->pos = p; | 427 b->pos = p; |
439 | 428 r->state = state; |
440 if (state == sw_done) { | 429 |
441 if (r->request_end == NULL) { | 430 return NGX_AGAIN; |
442 r->request_end = p - 1; | 431 |
443 } | 432 done: |
444 | 433 |
445 r->http_version = r->http_major * 1000 + r->http_minor; | 434 b->pos = p + 1; |
446 r->state = sw_start; | 435 |
447 | 436 if (r->request_end == NULL) { |
448 if (r->http_version == 9 && r->method != NGX_HTTP_GET) { | 437 r->request_end = p; |
449 return NGX_HTTP_PARSE_INVALID_09_METHOD; | |
450 } | |
451 | |
452 return NGX_OK; | |
453 | |
454 } else { | |
455 r->state = state; | |
456 return NGX_AGAIN; | |
457 } | 438 } |
439 | |
440 r->http_version = r->http_major * 1000 + r->http_minor; | |
441 r->state = sw_start; | |
442 | |
443 if (r->http_version == 9 && r->method != NGX_HTTP_GET) { | |
444 return NGX_HTTP_PARSE_INVALID_09_METHOD; | |
445 } | |
446 | |
447 return NGX_OK; | |
458 } | 448 } |
459 | 449 |
460 | 450 |
461 ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b) | 451 ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b) |
462 { | 452 { |
467 sw_space_before_value, | 457 sw_space_before_value, |
468 sw_value, | 458 sw_value, |
469 sw_space_after_value, | 459 sw_space_after_value, |
470 sw_almost_done, | 460 sw_almost_done, |
471 sw_header_almost_done, | 461 sw_header_almost_done, |
472 sw_ignore_line, | 462 sw_ignore_line |
473 sw_done, | |
474 sw_header_done | |
475 } state; | 463 } state; |
476 | 464 |
477 state = r->state; | 465 state = r->state; |
478 p = b->pos; | 466 |
479 | 467 for (p = b->pos; p < b->last; p++) { |
480 while (p < b->last && state < sw_done) { | 468 ch = *p; |
481 ch = *p++; | |
482 | 469 |
483 switch (state) { | 470 switch (state) { |
484 | 471 |
485 /* first char */ | 472 /* first char */ |
486 case sw_start: | 473 case sw_start: |
487 switch (ch) { | 474 switch (ch) { |
488 case CR: | 475 case CR: |
489 r->header_end = p - 1; | 476 r->header_end = p; |
490 state = sw_header_almost_done; | 477 state = sw_header_almost_done; |
491 break; | 478 break; |
492 case LF: | 479 case LF: |
493 r->header_end = p - 1; | 480 r->header_end = p; |
494 state = sw_header_done; | 481 goto header_done; |
495 break; | |
496 default: | 482 default: |
497 state = sw_name; | 483 state = sw_name; |
498 r->header_name_start = p - 1; | 484 r->header_name_start = p; |
499 | 485 |
500 c = (u_char) (ch | 0x20); | 486 c = (u_char) (ch | 0x20); |
501 if (c >= 'a' && c <= 'z') { | 487 if (c >= 'a' && c <= 'z') { |
502 break; | 488 break; |
503 } | 489 } |
521 if (c >= 'a' && c <= 'z') { | 507 if (c >= 'a' && c <= 'z') { |
522 break; | 508 break; |
523 } | 509 } |
524 | 510 |
525 if (ch == ':') { | 511 if (ch == ':') { |
526 r->header_name_end = p - 1; | 512 r->header_name_end = p; |
527 state = sw_space_before_value; | 513 state = sw_space_before_value; |
528 break; | 514 break; |
529 } | 515 } |
530 | 516 |
531 if (ch == '-' || ch == '_' || ch == '~' || ch == '.') { | 517 if (ch == '-' || ch == '_' || ch == '~' || ch == '.') { |
537 } | 523 } |
538 | 524 |
539 /* IIS may send the duplicate "HTTP/1.1 ..." lines */ | 525 /* IIS may send the duplicate "HTTP/1.1 ..." lines */ |
540 if (ch == '/' | 526 if (ch == '/' |
541 && r->proxy | 527 && r->proxy |
542 && p - r->header_start == 5 | 528 && p - r->header_start == 4 |
543 && ngx_strncmp(r->header_start, "HTTP", 4) == 0) | 529 && ngx_strncmp(r->header_start, "HTTP", 4) == 0) |
544 { | 530 { |
545 state = sw_ignore_line; | 531 state = sw_ignore_line; |
546 break; | 532 break; |
547 } | 533 } |
552 case sw_space_before_value: | 538 case sw_space_before_value: |
553 switch (ch) { | 539 switch (ch) { |
554 case ' ': | 540 case ' ': |
555 break; | 541 break; |
556 case CR: | 542 case CR: |
557 r->header_start = r->header_end = p - 1; | 543 r->header_start = r->header_end = p; |
558 state = sw_almost_done; | 544 state = sw_almost_done; |
559 break; | 545 break; |
560 case LF: | 546 case LF: |
561 r->header_start = r->header_end = p - 1; | 547 r->header_start = r->header_end = p; |
562 state = sw_done; | 548 goto done; |
563 break; | 549 default: |
564 default: | 550 r->header_start = p; |
565 r->header_start = p - 1; | |
566 state = sw_value; | 551 state = sw_value; |
567 break; | 552 break; |
568 } | 553 } |
569 break; | 554 break; |
570 | 555 |
571 /* header value */ | 556 /* header value */ |
572 case sw_value: | 557 case sw_value: |
573 switch (ch) { | 558 switch (ch) { |
574 case ' ': | 559 case ' ': |
575 r->header_end = p - 1; | 560 r->header_end = p; |
576 state = sw_space_after_value; | 561 state = sw_space_after_value; |
577 break; | 562 break; |
578 case CR: | 563 case CR: |
579 r->header_end = p - 1; | 564 r->header_end = p; |
580 state = sw_almost_done; | 565 state = sw_almost_done; |
581 break; | 566 break; |
582 case LF: | 567 case LF: |
583 r->header_end = p - 1; | 568 r->header_end = p; |
584 state = sw_done; | 569 goto done; |
585 break; | |
586 } | 570 } |
587 break; | 571 break; |
588 | 572 |
589 /* space* before end of header line */ | 573 /* space* before end of header line */ |
590 case sw_space_after_value: | 574 case sw_space_after_value: |
593 break; | 577 break; |
594 case CR: | 578 case CR: |
595 state = sw_almost_done; | 579 state = sw_almost_done; |
596 break; | 580 break; |
597 case LF: | 581 case LF: |
598 state = sw_done; | 582 goto done; |
599 break; | |
600 default: | 583 default: |
601 state = sw_value; | 584 state = sw_value; |
602 break; | 585 break; |
603 } | 586 } |
604 break; | 587 break; |
616 | 599 |
617 /* end of header line */ | 600 /* end of header line */ |
618 case sw_almost_done: | 601 case sw_almost_done: |
619 switch (ch) { | 602 switch (ch) { |
620 case LF: | 603 case LF: |
621 state = sw_done; | 604 goto done; |
622 break; | |
623 default: | 605 default: |
624 return NGX_HTTP_PARSE_INVALID_HEADER; | 606 return NGX_HTTP_PARSE_INVALID_HEADER; |
625 } | 607 } |
626 break; | 608 break; |
627 | 609 |
628 /* end of header */ | 610 /* end of header */ |
629 case sw_header_almost_done: | 611 case sw_header_almost_done: |
630 switch (ch) { | 612 switch (ch) { |
631 case LF: | 613 case LF: |
632 state = sw_header_done; | 614 goto header_done; |
633 break; | |
634 default: | 615 default: |
635 return NGX_HTTP_PARSE_INVALID_HEADER; | 616 return NGX_HTTP_PARSE_INVALID_HEADER; |
636 } | 617 } |
637 break; | |
638 | |
639 /* suppress warning */ | |
640 case sw_done: | |
641 case sw_header_done: | |
642 break; | 618 break; |
643 } | 619 } |
644 } | 620 } |
645 | 621 |
646 b->pos = p; | 622 b->pos = p; |
647 | 623 r->state = state; |
648 if (state == sw_done) { | 624 |
649 r->state = sw_start; | 625 return NGX_AGAIN; |
650 return NGX_OK; | 626 |
651 | 627 done: |
652 } else if (state == sw_header_done) { | 628 |
653 r->state = sw_start; | 629 b->pos = p + 1; |
654 return NGX_HTTP_PARSE_HEADER_DONE; | 630 r->state = sw_start; |
655 | 631 |
656 } else { | 632 return NGX_OK; |
657 r->state = state; | 633 |
658 return NGX_AGAIN; | 634 header_done: |
659 } | 635 |
636 b->pos = p + 1; | |
637 r->state = sw_start; | |
638 | |
639 return NGX_HTTP_PARSE_HEADER_DONE; | |
660 } | 640 } |
661 | 641 |
662 | 642 |
663 ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r) | 643 ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r) |
664 { | 644 { |
675 #endif | 655 #endif |
676 sw_quoted, | 656 sw_quoted, |
677 sw_quoted_second | 657 sw_quoted_second |
678 } state, quoted_state; | 658 } state, quoted_state; |
679 | 659 |
660 #if (NGX_SUPPRESS_WARN) | |
680 decoded = '\0'; | 661 decoded = '\0'; |
681 quoted_state = sw_usual; | 662 quoted_state = sw_usual; |
663 #endif | |
682 | 664 |
683 state = sw_usual; | 665 state = sw_usual; |
684 p = r->uri_start; | 666 p = r->uri_start; |
685 u = r->uri.data; | 667 u = r->uri.data; |
686 r->uri_ext = NULL; | 668 r->uri_ext = NULL; |
687 r->args_start = NULL; | 669 r->args_start = NULL; |
688 | 670 |
689 ch = *p++; | 671 ch = *p++; |
690 | 672 |
691 while (p <= r->uri_end && r->args_start == NULL) { | 673 while (p <= r->uri_end) { |
692 | 674 |
693 /* | 675 /* |
694 * we use "ch = *p++" inside the cycle but this operation is safe | 676 * we use "ch = *p++" inside the cycle, but this operation is safe, |
695 * because after the URI there is always at least one charcter: | 677 * because after the URI there is always at least one charcter: |
696 * the line feed | 678 * the line feed |
697 */ | 679 */ |
698 | 680 |
699 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 681 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
729 quoted_state = state; | 711 quoted_state = state; |
730 state = sw_quoted; | 712 state = sw_quoted; |
731 break; | 713 break; |
732 case '?': | 714 case '?': |
733 r->args_start = p; | 715 r->args_start = p; |
734 break; | 716 goto done; |
735 case ':': | 717 case ':': |
736 state = sw_colon; | 718 state = sw_colon; |
737 *u++ = ch; | 719 *u++ = ch; |
738 break; | 720 break; |
739 case '.': | 721 case '.': |
764 break; | 746 break; |
765 case '%': | 747 case '%': |
766 quoted_state = state; | 748 quoted_state = state; |
767 state = sw_quoted; | 749 state = sw_quoted; |
768 break; | 750 break; |
751 case '?': | |
752 r->args_start = p; | |
753 goto done; | |
769 default: | 754 default: |
770 state = sw_usual; | 755 state = sw_usual; |
771 *u++ = ch; | 756 *u++ = ch; |
772 break; | 757 break; |
773 } | 758 } |
792 break; | 777 break; |
793 case '%': | 778 case '%': |
794 quoted_state = state; | 779 quoted_state = state; |
795 state = sw_quoted; | 780 state = sw_quoted; |
796 break; | 781 break; |
782 case '?': | |
783 r->args_start = p; | |
784 goto done; | |
797 default: | 785 default: |
798 state = sw_usual; | 786 state = sw_usual; |
799 *u++ = ch; | 787 *u++ = ch; |
800 break; | 788 break; |
801 } | 789 } |
816 break; | 804 break; |
817 case '%': | 805 case '%': |
818 quoted_state = state; | 806 quoted_state = state; |
819 state = sw_quoted; | 807 state = sw_quoted; |
820 break; | 808 break; |
809 case '?': | |
810 r->args_start = p; | |
811 goto done; | |
821 default: | 812 default: |
822 state = sw_usual; | 813 state = sw_usual; |
823 *u++ = ch; | 814 *u++ = ch; |
824 break; | 815 break; |
825 } | 816 } |
842 break; | 833 break; |
843 case '%': | 834 case '%': |
844 quoted_state = state; | 835 quoted_state = state; |
845 state = sw_quoted; | 836 state = sw_quoted; |
846 break; | 837 break; |
838 case '?': | |
839 r->args_start = p; | |
840 goto done; | |
847 default: | 841 default: |
848 state = sw_usual; | 842 state = sw_usual; |
849 *u++ = ch; | 843 *u++ = ch; |
850 break; | 844 break; |
851 } | 845 } |
870 break; | 864 break; |
871 case '%': | 865 case '%': |
872 quoted_state = state; | 866 quoted_state = state; |
873 state = sw_quoted; | 867 state = sw_quoted; |
874 break; | 868 break; |
869 case '?': | |
870 r->args_start = p; | |
871 goto done; | |
875 #if (NGX_WIN32) | 872 #if (NGX_WIN32) |
876 case '.': | 873 case '.': |
877 state = sw_dot_dot_dot; | 874 state = sw_dot_dot_dot; |
878 *u++ = ch; | 875 *u++ = ch; |
879 break; | 876 break; |
951 } | 948 } |
952 | 949 |
953 c = (u_char) (ch | 0x20); | 950 c = (u_char) (ch | 0x20); |
954 if (c >= 'a' && c <= 'f') { | 951 if (c >= 'a' && c <= 'f') { |
955 ch = (u_char) ((decoded << 4) + c - 'a' + 10); | 952 ch = (u_char) ((decoded << 4) + c - 'a' + 10); |
956 if (ch == '%') { | 953 if (ch == '?') { |
957 state = sw_usual; | |
958 *u++ = ch; | 954 *u++ = ch; |
959 ch = *p++; | 955 ch = *p++; |
960 break; | |
961 } | 956 } |
962 state = quoted_state; | 957 state = quoted_state; |
963 break; | 958 break; |
964 } | 959 } |
965 | 960 |
966 return NGX_HTTP_PARSE_INVALID_REQUEST; | 961 return NGX_HTTP_PARSE_INVALID_REQUEST; |
967 } | 962 } |
968 } | 963 } |
964 | |
965 done: | |
969 | 966 |
970 r->uri.len = u - r->uri.data; | 967 r->uri.len = u - r->uri.data; |
971 r->uri.data[r->uri.len] = '\0'; | 968 r->uri.data[r->uri.len] = '\0'; |
972 | 969 |
973 if (r->uri_ext) { | 970 if (r->uri_ext) { |