comparison src/http/ngx_http_script.c @ 456:ca8f7f6cab16 NGINX_0_7_40

nginx 0.7.40 *) Feature: the "location" directive supports captures in regular expressions. *) Feature: an "alias" directive with capture references may be used inside a location given by a regular expression with captures. *) Feature: the "server_name" directive supports captures in regular expressions. *) Workaround: the ngx_http_autoindex_module did not show the trailing slash in directories on XFS filesystem; the issue had appeared in 0.7.15. Thanks to Dmitry Kuzmenko.
author Igor Sysoev <http://sysoev.ru>
date Mon, 09 Mar 2009 00:00:00 +0300
parents 33394d1255b0
children c8cfb6c462ef
comparison
equal deleted inserted replaced
455:ead634c4b006 456:ca8f7f6cab16
38 ngx_str_t name; 38 ngx_str_t name;
39 uintptr_t *code; 39 uintptr_t *code;
40 ngx_uint_t i, n, bracket; 40 ngx_uint_t i, n, bracket;
41 ngx_http_script_var_code_t *var_code; 41 ngx_http_script_var_code_t *var_code;
42 ngx_http_script_copy_code_t *copy; 42 ngx_http_script_copy_code_t *copy;
43 #if (NGX_PCRE)
43 ngx_http_script_copy_capture_code_t *copy_capture; 44 ngx_http_script_copy_capture_code_t *copy_capture;
45 #endif
44 46
45 if (sc->flushes && *sc->flushes == NULL) { 47 if (sc->flushes && *sc->flushes == NULL) {
46 n = sc->variables ? sc->variables : 1; 48 n = sc->variables ? sc->variables : 1;
47 *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t)); 49 *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t));
48 if (*sc->flushes == NULL) { 50 if (*sc->flushes == NULL) {
87 89
88 if (++i == sc->source->len) { 90 if (++i == sc->source->len) {
89 goto invalid_variable; 91 goto invalid_variable;
90 } 92 }
91 93
94 #if (NGX_PCRE)
95
96 /* NGX_HTTP_MAX_CAPTURES is 9 */
97
92 if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') { 98 if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
93 99
94 n = sc->source->data[i] - '0'; 100 n = sc->source->data[i] - '0';
95 101
96 if (sc->captures_mask & (1 << n)) { 102 if (sc->captures_mask & (1 << n)) {
127 133
128 i++; 134 i++;
129 135
130 continue; 136 continue;
131 } 137 }
138
139 #endif
132 140
133 if (sc->source->data[i] == '{') { 141 if (sc->source->data[i] == '{') {
134 bracket = 1; 142 bracket = 1;
135 143
136 if (++i == sc->source->len) { 144 if (++i == sc->source->len) {
517 } 525 }
518 } 526 }
519 527
520 528
521 size_t 529 size_t
522 ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
523 {
524 ngx_http_script_copy_capture_code_t *code;
525
526 code = (ngx_http_script_copy_capture_code_t *) e->ip;
527
528 e->ip += sizeof(ngx_http_script_copy_capture_code_t);
529
530 if (code->n < e->ncaptures) {
531 if ((e->is_args || e->quote)
532 && (e->request->quoted_uri || e->request->plus_in_uri))
533 {
534 return e->captures[code->n + 1] - e->captures[code->n]
535 + 2 * ngx_escape_uri(NULL,
536 &e->line.data[e->captures[code->n]],
537 e->captures[code->n + 1] - e->captures[code->n],
538 NGX_ESCAPE_ARGS);
539 } else {
540 return e->captures[code->n + 1] - e->captures[code->n];
541 }
542 }
543
544 return 0;
545 }
546
547
548 void
549 ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
550 {
551 u_char *p;
552 ngx_http_script_copy_capture_code_t *code;
553
554 code = (ngx_http_script_copy_capture_code_t *) e->ip;
555
556 e->ip += sizeof(ngx_http_script_copy_capture_code_t);
557
558 p = e->pos;
559
560 if (code->n < e->ncaptures) {
561 if ((e->is_args || e->quote)
562 && (e->request->quoted_uri || e->request->plus_in_uri))
563 {
564 e->pos = (u_char *) ngx_escape_uri(p,
565 &e->line.data[e->captures[code->n]],
566 e->captures[code->n + 1] - e->captures[code->n],
567 NGX_ESCAPE_ARGS);
568 } else {
569 e->pos = ngx_copy(p,
570 &e->line.data[e->captures[code->n]],
571 e->captures[code->n + 1] - e->captures[code->n]);
572 }
573 }
574
575 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
576 "http script capture: \"%*s\"", e->pos - p, p);
577 }
578
579
580 size_t
581 ngx_http_script_mark_args_code(ngx_http_script_engine_t *e) 530 ngx_http_script_mark_args_code(ngx_http_script_engine_t *e)
582 { 531 {
583 e->is_args = 1; 532 e->is_args = 1;
584 e->ip += sizeof(uintptr_t); 533 e->ip += sizeof(uintptr_t);
585 534
595 544
596 e->is_args = 1; 545 e->is_args = 1;
597 e->args = e->pos; 546 e->args = e->pos;
598 e->ip += sizeof(uintptr_t); 547 e->ip += sizeof(uintptr_t);
599 } 548 }
600
601 549
602 550
603 #if (NGX_PCRE) 551 #if (NGX_PCRE)
604 552
605 void 553 void
626 e->sp--; 574 e->sp--;
627 e->line.len = e->sp->len; 575 e->line.len = e->sp->len;
628 e->line.data = e->sp->data; 576 e->line.data = e->sp->data;
629 } 577 }
630 578
631 rc = ngx_regex_exec(code->regex, &e->line, e->captures, code->ncaptures); 579 if (code->ncaptures && r->captures == NULL) {
580
581 r->captures = ngx_palloc(r->pool,
582 (NGX_HTTP_MAX_CAPTURES + 1) * 3 * sizeof(int));
583 if (r->captures == NULL) {
584 e->ip = ngx_http_script_exit;
585 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
586 return;
587 }
588 }
589
590 rc = ngx_regex_exec(code->regex, &e->line, r->captures, code->ncaptures);
632 591
633 if (rc == NGX_REGEX_NO_MATCHED) { 592 if (rc == NGX_REGEX_NO_MATCHED) {
634 if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) { 593 if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
635 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, 594 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
636 "\"%V\" does not match \"%V\"", 595 "\"%V\" does not match \"%V\"",
637 &code->name, &e->line); 596 &code->name, &e->line);
638 } 597 }
639 598
640 e->ncaptures = 0; 599 r->ncaptures = 0;
641 600
642 if (code->test) { 601 if (code->test) {
643 if (code->negative_test) { 602 if (code->negative_test) {
644 e->sp->len = 1; 603 e->sp->len = 1;
645 e->sp->data = (u_char *) "1"; 604 e->sp->data = (u_char *) "1";
672 if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) { 631 if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
673 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, 632 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
674 "\"%V\" matches \"%V\"", &code->name, &e->line); 633 "\"%V\" matches \"%V\"", &code->name, &e->line);
675 } 634 }
676 635
677 e->ncaptures = code->ncaptures; 636 r->ncaptures = code->ncaptures;
637 r->captures_data = e->line.data;
678 638
679 if (code->test) { 639 if (code->test) {
680 if (code->negative_test) { 640 if (code->negative_test) {
681 e->sp->len = 0; 641 e->sp->len = 0;
682 e->sp->data = (u_char *) ""; 642 e->sp->data = (u_char *) "";
723 NGX_ESCAPE_ARGS); 683 NGX_ESCAPE_ARGS);
724 } 684 }
725 } 685 }
726 686
727 for (n = 1; n < (ngx_uint_t) rc; n++) { 687 for (n = 1; n < (ngx_uint_t) rc; n++) {
728 e->buf.len += e->captures[2 * n + 1] - e->captures[2 * n]; 688 e->buf.len += r->captures[2 * n + 1] - r->captures[2 * n];
729 } 689 }
730 690
731 } else { 691 } else {
732 ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); 692 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
733 693
734 le.ip = code->lengths->elts; 694 le.ip = code->lengths->elts;
735 le.line = e->line; 695 le.line = e->line;
736 le.request = r; 696 le.request = r;
737 le.captures = e->captures;
738 le.ncaptures = e->ncaptures;
739 le.quote = code->redirect; 697 le.quote = code->redirect;
740 698
741 len = 0; 699 len = 0;
742 700
743 while (*(uintptr_t *) le.ip) { 701 while (*(uintptr_t *) le.ip) {
872 } 830 }
873 831
874 e->ip += sizeof(ngx_http_script_regex_end_code_t); 832 e->ip += sizeof(ngx_http_script_regex_end_code_t);
875 } 833 }
876 834
835
836 size_t
837 ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
838 {
839 int *cap;
840 u_char *p;
841 ngx_uint_t n;
842 ngx_http_request_t *r;
843 ngx_http_script_copy_capture_code_t *code;
844
845 r = e->request;
846
847 code = (ngx_http_script_copy_capture_code_t *) e->ip;
848
849 e->ip += sizeof(ngx_http_script_copy_capture_code_t);
850
851 n = code->n;
852
853 if (n < r->ncaptures) {
854
855 cap = r->captures;
856
857 if ((e->is_args || e->quote)
858 && (e->request->quoted_uri || e->request->plus_in_uri))
859 {
860 p = r->captures_data;
861
862 return cap[n + 1] - cap[n]
863 + 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n],
864 NGX_ESCAPE_ARGS);
865 } else {
866 return cap[n + 1] - cap[n];
867 }
868 }
869
870 return 0;
871 }
872
873
874 void
875 ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
876 {
877 int *cap;
878 u_char *p, *pos;
879 ngx_uint_t n;
880 ngx_http_request_t *r;
881 ngx_http_script_copy_capture_code_t *code;
882
883 r = e->request;
884
885 code = (ngx_http_script_copy_capture_code_t *) e->ip;
886
887 e->ip += sizeof(ngx_http_script_copy_capture_code_t);
888
889 n = code->n;
890
891 pos = e->pos;
892
893 if (n < r->ncaptures) {
894
895 cap = r->captures;
896 p = r->captures_data;
897
898 if ((e->is_args || e->quote)
899 && (e->request->quoted_uri || e->request->plus_in_uri))
900 {
901 e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
902 cap[n + 1] - cap[n],
903 NGX_ESCAPE_ARGS);
904 } else {
905 e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
906 }
907 }
908
909 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
910 "http script capture: \"%*s\"", e->pos - pos, pos);
911 }
912
877 #endif 913 #endif
878 914
879 915
880 void 916 void
881 ngx_http_script_return_code(ngx_http_script_engine_t *e) 917 ngx_http_script_return_code(ngx_http_script_engine_t *e)
1131 ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); 1167 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
1132 1168
1133 le.ip = code->lengths->elts; 1169 le.ip = code->lengths->elts;
1134 le.line = e->line; 1170 le.line = e->line;
1135 le.request = e->request; 1171 le.request = e->request;
1136 le.captures = e->captures;
1137 le.ncaptures = e->ncaptures;
1138 le.quote = e->quote; 1172 le.quote = e->quote;
1139 1173
1140 for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) { 1174 for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
1141 lcode = *(ngx_http_script_len_code_pt *) le.ip; 1175 lcode = *(ngx_http_script_len_code_pt *) le.ip;
1142 } 1176 }