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) {