3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
12 static ngx_int_t
ngx_http_script_init_arrays(ngx_http_script_compile_t
*sc
);
13 static ngx_int_t
ngx_http_script_done(ngx_http_script_compile_t
*sc
);
14 static ngx_int_t
ngx_http_script_add_copy_code(ngx_http_script_compile_t
*sc
,
15 ngx_str_t
*value
, ngx_uint_t last
);
16 static ngx_int_t
ngx_http_script_add_var_code(ngx_http_script_compile_t
*sc
,
18 static ngx_int_t
ngx_http_script_add_args_code(ngx_http_script_compile_t
*sc
);
20 static ngx_int_t
ngx_http_script_add_capture_code(ngx_http_script_compile_t
*sc
,
24 ngx_http_script_add_full_name_code(ngx_http_script_compile_t
*sc
);
25 static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t
*e
);
26 static void ngx_http_script_full_name_code(ngx_http_script_engine_t
*e
);
29 #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
31 static uintptr_t ngx_http_script_exit_code
= (uintptr_t) NULL
;
35 ngx_http_script_flush_complex_value(ngx_http_request_t
*r
,
36 ngx_http_complex_value_t
*val
)
43 while (*index
!= (ngx_uint_t
) -1) {
45 if (r
->variables
[*index
].no_cacheable
) {
46 r
->variables
[*index
].valid
= 0;
47 r
->variables
[*index
].not_found
= 0;
57 ngx_http_complex_value(ngx_http_request_t
*r
, ngx_http_complex_value_t
*val
,
61 ngx_http_script_code_pt code
;
62 ngx_http_script_len_code_pt lcode
;
63 ngx_http_script_engine_t e
;
65 if (val
->lengths
== NULL
) {
70 ngx_http_script_flush_complex_value(r
, val
);
72 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
80 while (*(uintptr_t *) e
.ip
) {
81 lcode
= *(ngx_http_script_len_code_pt
*) e
.ip
;
86 value
->data
= ngx_pnalloc(r
->pool
, len
);
87 if (value
->data
== NULL
) {
95 while (*(uintptr_t *) e
.ip
) {
96 code
= *(ngx_http_script_code_pt
*) e
.ip
;
97 code((ngx_http_script_engine_t
*) &e
);
107 ngx_http_compile_complex_value(ngx_http_compile_complex_value_t
*ccv
)
110 ngx_uint_t i
, n
, nv
, nc
;
111 ngx_array_t flushes
, lengths
, values
, *pf
, *pl
, *pv
;
112 ngx_http_script_compile_t sc
;
117 ngx_conf_log_error(NGX_LOG_EMERG
, ccv
->cf
, 0, "empty parameter");
124 for (i
= 0; i
< v
->len
; i
++) {
125 if (v
->data
[i
] == '$') {
126 if (v
->data
[i
+ 1] >= '1' && v
->data
[i
+ 1] <= '9') {
135 if (v
->data
[0] != '$' && (ccv
->conf_prefix
|| ccv
->root_prefix
)) {
137 if (ngx_conf_full_name(ccv
->cf
->cycle
, v
, ccv
->conf_prefix
) != NGX_OK
) {
141 ccv
->conf_prefix
= 0;
142 ccv
->root_prefix
= 0;
145 ccv
->complex_value
->value
= *v
;
146 ccv
->complex_value
->flushes
= NULL
;
147 ccv
->complex_value
->lengths
= NULL
;
148 ccv
->complex_value
->values
= NULL
;
150 if (nv
== 0 && nc
== 0) {
156 if (ngx_array_init(&flushes
, ccv
->cf
->pool
, n
, sizeof(ngx_uint_t
))
162 n
= nv
* (2 * sizeof(ngx_http_script_copy_code_t
)
163 + sizeof(ngx_http_script_var_code_t
))
166 if (ngx_array_init(&lengths
, ccv
->cf
->pool
, n
, 1) != NGX_OK
) {
170 n
= (nv
* (2 * sizeof(ngx_http_script_copy_code_t
)
171 + sizeof(ngx_http_script_var_code_t
))
174 + sizeof(uintptr_t) - 1)
175 & ~(sizeof(uintptr_t) - 1);
177 if (ngx_array_init(&values
, ccv
->cf
->pool
, n
, 1) != NGX_OK
) {
185 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
192 sc
.complete_lengths
= 1;
193 sc
.complete_values
= 1;
195 sc
.conf_prefix
= ccv
->conf_prefix
;
196 sc
.root_prefix
= ccv
->root_prefix
;
198 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
203 ccv
->complex_value
->flushes
= flushes
.elts
;
204 ccv
->complex_value
->flushes
[flushes
.nelts
] = (ngx_uint_t
) -1;
207 ccv
->complex_value
->lengths
= lengths
.elts
;
208 ccv
->complex_value
->values
= values
.elts
;
215 ngx_http_script_variables_count(ngx_str_t
*value
)
219 for (n
= 0, i
= 0; i
< value
->len
; i
++) {
220 if (value
->data
[i
] == '$') {
230 ngx_http_script_compile(ngx_http_script_compile_t
*sc
)
234 ngx_uint_t i
, bracket
;
236 if (ngx_http_script_init_arrays(sc
) != NGX_OK
) {
240 for (i
= 0; i
< sc
->source
->len
; /* void */ ) {
244 if (sc
->source
->data
[i
] == '$') {
246 if (++i
== sc
->source
->len
) {
247 goto invalid_variable
;
254 if (sc
->source
->data
[i
] >= '1' && sc
->source
->data
[i
] <= '9') {
256 n
= sc
->source
->data
[i
] - '0';
258 if (sc
->captures_mask
& (1 << n
)) {
262 sc
->captures_mask
|= 1 << n
;
264 if (ngx_http_script_add_capture_code(sc
, n
) != NGX_OK
) {
275 if (sc
->source
->data
[i
] == '{') {
278 if (++i
== sc
->source
->len
) {
279 goto invalid_variable
;
282 name
.data
= &sc
->source
->data
[i
];
286 name
.data
= &sc
->source
->data
[i
];
289 for ( /* void */ ; i
< sc
->source
->len
; i
++, name
.len
++) {
290 ch
= sc
->source
->data
[i
];
292 if (ch
== '}' && bracket
) {
298 if ((ch
>= 'A' && ch
<= 'Z')
299 || (ch
>= 'a' && ch
<= 'z')
300 || (ch
>= '0' && ch
<= '9')
310 ngx_conf_log_error(NGX_LOG_EMERG
, sc
->cf
, 0,
311 "the closing bracket in \"%V\" "
312 "variable is missing", &name
);
317 goto invalid_variable
;
322 if (ngx_http_script_add_var_code(sc
, &name
) != NGX_OK
) {
329 if (sc
->source
->data
[i
] == '?' && sc
->compile_args
) {
331 sc
->compile_args
= 0;
333 if (ngx_http_script_add_args_code(sc
) != NGX_OK
) {
342 name
.data
= &sc
->source
->data
[i
];
344 while (i
< sc
->source
->len
) {
346 if (sc
->source
->data
[i
] == '$') {
350 if (sc
->source
->data
[i
] == '?') {
354 if (sc
->compile_args
) {
363 sc
->size
+= name
.len
;
365 if (ngx_http_script_add_copy_code(sc
, &name
, (i
== sc
->source
->len
))
372 return ngx_http_script_done(sc
);
376 ngx_conf_log_error(NGX_LOG_EMERG
, sc
->cf
, 0, "invalid variable name");
383 ngx_http_script_run(ngx_http_request_t
*r
, ngx_str_t
*value
,
384 void *code_lengths
, size_t len
, void *code_values
)
387 ngx_http_script_code_pt code
;
388 ngx_http_script_len_code_pt lcode
;
389 ngx_http_script_engine_t e
;
390 ngx_http_core_main_conf_t
*cmcf
;
392 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
394 for (i
= 0; i
< cmcf
->variables
.nelts
; i
++) {
395 if (r
->variables
[i
].no_cacheable
) {
396 r
->variables
[i
].valid
= 0;
397 r
->variables
[i
].not_found
= 0;
401 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
407 while (*(uintptr_t *) e
.ip
) {
408 lcode
= *(ngx_http_script_len_code_pt
*) e
.ip
;
414 value
->data
= ngx_pnalloc(r
->pool
, len
);
415 if (value
->data
== NULL
) {
422 while (*(uintptr_t *) e
.ip
) {
423 code
= *(ngx_http_script_code_pt
*) e
.ip
;
424 code((ngx_http_script_engine_t
*) &e
);
432 ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t
*r
,
433 ngx_array_t
*indices
)
435 ngx_uint_t n
, *index
;
438 index
= indices
->elts
;
439 for (n
= 0; n
< indices
->nelts
; n
++) {
440 if (r
->variables
[index
[n
]].no_cacheable
) {
441 r
->variables
[index
[n
]].valid
= 0;
442 r
->variables
[index
[n
]].not_found
= 0;
450 ngx_http_script_init_arrays(ngx_http_script_compile_t
*sc
)
454 if (sc
->flushes
&& *sc
->flushes
== NULL
) {
455 n
= sc
->variables
? sc
->variables
: 1;
456 *sc
->flushes
= ngx_array_create(sc
->cf
->pool
, n
, sizeof(ngx_uint_t
));
457 if (*sc
->flushes
== NULL
) {
462 if (*sc
->lengths
== NULL
) {
463 n
= sc
->variables
* (2 * sizeof(ngx_http_script_copy_code_t
)
464 + sizeof(ngx_http_script_var_code_t
))
467 *sc
->lengths
= ngx_array_create(sc
->cf
->pool
, n
, 1);
468 if (*sc
->lengths
== NULL
) {
473 if (*sc
->values
== NULL
) {
474 n
= (sc
->variables
* (2 * sizeof(ngx_http_script_copy_code_t
)
475 + sizeof(ngx_http_script_var_code_t
))
478 + sizeof(uintptr_t) - 1)
479 & ~(sizeof(uintptr_t) - 1);
481 *sc
->values
= ngx_array_create(sc
->cf
->pool
, n
, 1);
482 if (*sc
->values
== NULL
) {
494 ngx_http_script_done(ngx_http_script_compile_t
*sc
)
502 zero
.data
= (u_char
*) "\0";
504 if (ngx_http_script_add_copy_code(sc
, &zero
, 0) != NGX_OK
) {
509 if (sc
->conf_prefix
|| sc
->root_prefix
) {
510 if (ngx_http_script_add_full_name_code(sc
) != NGX_OK
) {
515 if (sc
->complete_lengths
) {
516 code
= ngx_http_script_add_code(*sc
->lengths
, sizeof(uintptr_t), NULL
);
521 *code
= (uintptr_t) NULL
;
524 if (sc
->complete_values
) {
525 code
= ngx_http_script_add_code(*sc
->values
, sizeof(uintptr_t),
531 *code
= (uintptr_t) NULL
;
539 ngx_http_script_start_code(ngx_pool_t
*pool
, ngx_array_t
**codes
, size_t size
)
541 if (*codes
== NULL
) {
542 *codes
= ngx_array_create(pool
, 256, 1);
543 if (*codes
== NULL
) {
548 return ngx_array_push_n(*codes
, size
);
553 ngx_http_script_add_code(ngx_array_t
*codes
, size_t size
, void *code
)
560 new = ngx_array_push_n(codes
, size
);
566 if (elts
!= codes
->elts
) {
568 *p
+= (u_char
*) codes
->elts
- elts
;
577 ngx_http_script_add_copy_code(ngx_http_script_compile_t
*sc
, ngx_str_t
*value
,
581 size_t size
, len
, zero
;
582 ngx_http_script_copy_code_t
*code
;
584 zero
= (sc
->zero
&& last
);
585 len
= value
->len
+ zero
;
587 code
= ngx_http_script_add_code(*sc
->lengths
,
588 sizeof(ngx_http_script_copy_code_t
), NULL
);
593 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_len_code
;
596 size
= (sizeof(ngx_http_script_copy_code_t
) + len
+ sizeof(uintptr_t) - 1)
597 & ~(sizeof(uintptr_t) - 1);
599 code
= ngx_http_script_add_code(*sc
->values
, size
, &sc
->main
);
604 code
->code
= ngx_http_script_copy_code
;
607 p
= ngx_cpymem((u_char
*) code
+ sizeof(ngx_http_script_copy_code_t
),
608 value
->data
, value
->len
);
620 ngx_http_script_copy_len_code(ngx_http_script_engine_t
*e
)
622 ngx_http_script_copy_code_t
*code
;
624 code
= (ngx_http_script_copy_code_t
*) e
->ip
;
626 e
->ip
+= sizeof(ngx_http_script_copy_code_t
);
633 ngx_http_script_copy_code(ngx_http_script_engine_t
*e
)
636 ngx_http_script_copy_code_t
*code
;
638 code
= (ngx_http_script_copy_code_t
*) e
->ip
;
643 e
->pos
= ngx_copy(p
, e
->ip
+ sizeof(ngx_http_script_copy_code_t
),
647 e
->ip
+= sizeof(ngx_http_script_copy_code_t
)
648 + ((code
->len
+ sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
650 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
651 "http script copy: \"%*s\"", e
->pos
- p
, p
);
656 ngx_http_script_add_var_code(ngx_http_script_compile_t
*sc
, ngx_str_t
*name
)
659 ngx_http_script_var_code_t
*code
;
661 index
= ngx_http_get_variable_index(sc
->cf
, name
);
663 if (index
== NGX_ERROR
) {
668 p
= ngx_array_push(*sc
->flushes
);
676 code
= ngx_http_script_add_code(*sc
->lengths
,
677 sizeof(ngx_http_script_var_code_t
), NULL
);
682 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_var_len_code
;
683 code
->index
= (uintptr_t) index
;
685 code
= ngx_http_script_add_code(*sc
->values
,
686 sizeof(ngx_http_script_var_code_t
),
692 code
->code
= ngx_http_script_copy_var_code
;
693 code
->index
= (uintptr_t) index
;
700 ngx_http_script_copy_var_len_code(ngx_http_script_engine_t
*e
)
702 ngx_http_variable_value_t
*value
;
703 ngx_http_script_var_code_t
*code
;
705 code
= (ngx_http_script_var_code_t
*) e
->ip
;
707 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
710 value
= ngx_http_get_indexed_variable(e
->request
, code
->index
);
713 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
716 if (value
&& !value
->not_found
) {
725 ngx_http_script_copy_var_code(ngx_http_script_engine_t
*e
)
728 ngx_http_variable_value_t
*value
;
729 ngx_http_script_var_code_t
*code
;
731 code
= (ngx_http_script_var_code_t
*) e
->ip
;
733 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
738 value
= ngx_http_get_indexed_variable(e
->request
, code
->index
);
741 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
744 if (value
&& !value
->not_found
) {
746 e
->pos
= ngx_copy(p
, value
->data
, value
->len
);
748 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
,
749 e
->request
->connection
->log
, 0,
750 "http script var: \"%*s\"", e
->pos
- p
, p
);
757 ngx_http_script_add_args_code(ngx_http_script_compile_t
*sc
)
761 code
= ngx_http_script_add_code(*sc
->lengths
, sizeof(uintptr_t), NULL
);
766 *code
= (uintptr_t) ngx_http_script_mark_args_code
;
768 code
= ngx_http_script_add_code(*sc
->values
, sizeof(uintptr_t), &sc
->main
);
773 *code
= (uintptr_t) ngx_http_script_start_args_code
;
780 ngx_http_script_mark_args_code(ngx_http_script_engine_t
*e
)
783 e
->ip
+= sizeof(uintptr_t);
790 ngx_http_script_start_args_code(ngx_http_script_engine_t
*e
)
792 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
797 e
->ip
+= sizeof(uintptr_t);
804 ngx_http_script_regex_start_code(ngx_http_script_engine_t
*e
)
809 ngx_http_request_t
*r
;
810 ngx_http_script_engine_t le
;
811 ngx_http_script_len_code_pt lcode
;
812 ngx_http_script_regex_code_t
*code
;
814 code
= (ngx_http_script_regex_code_t
*) e
->ip
;
818 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
819 "http script regex: \"%V\"", &code
->name
);
825 e
->line
.len
= e
->sp
->len
;
826 e
->line
.data
= e
->sp
->data
;
829 rc
= ngx_http_regex_exec(r
, code
->regex
, &e
->line
);
831 if (rc
== NGX_DECLINED
) {
832 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
833 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
834 "\"%V\" does not match \"%V\"",
835 &code
->name
, &e
->line
);
841 if (code
->negative_test
) {
843 e
->sp
->data
= (u_char
*) "1";
847 e
->sp
->data
= (u_char
*) "";
852 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
860 if (rc
== NGX_ERROR
) {
861 e
->ip
= ngx_http_script_exit
;
862 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
866 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
867 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
868 "\"%V\" matches \"%V\"", &code
->name
, &e
->line
);
872 if (code
->negative_test
) {
874 e
->sp
->data
= (u_char
*) "";
878 e
->sp
->data
= (u_char
*) "1";
883 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
888 e
->status
= code
->status
;
890 if (!code
->redirect
) {
891 e
->ip
= ngx_http_script_exit
;
898 r
->valid_unparsed_uri
= 0;
900 if (code
->break_cycle
) {
901 r
->valid_location
= 0;
909 if (code
->lengths
== NULL
) {
910 e
->buf
.len
= code
->size
;
913 if (r
->ncaptures
&& (r
->quoted_uri
|| r
->plus_in_uri
)) {
914 e
->buf
.len
+= 2 * ngx_escape_uri(NULL
, r
->uri
.data
, r
->uri
.len
,
919 for (n
= 2; n
< r
->ncaptures
; n
+= 2) {
920 e
->buf
.len
+= r
->captures
[n
+ 1] - r
->captures
[n
];
924 ngx_memzero(&le
, sizeof(ngx_http_script_engine_t
));
926 le
.ip
= code
->lengths
->elts
;
929 le
.quote
= code
->redirect
;
933 while (*(uintptr_t *) le
.ip
) {
934 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
939 e
->is_args
= le
.is_args
;
942 if (code
->add_args
&& r
->args
.len
) {
943 e
->buf
.len
+= r
->args
.len
+ 1;
946 e
->buf
.data
= ngx_pnalloc(r
->pool
, e
->buf
.len
);
947 if (e
->buf
.data
== NULL
) {
948 e
->ip
= ngx_http_script_exit
;
949 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
953 e
->quote
= code
->redirect
;
955 e
->pos
= e
->buf
.data
;
957 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
962 ngx_http_script_regex_end_code(ngx_http_script_engine_t
*e
)
965 ngx_http_request_t
*r
;
966 ngx_http_script_regex_end_code_t
*code
;
968 code
= (ngx_http_script_regex_end_code_t
*) e
->ip
;
974 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
975 "http script regex end");
977 if (code
->redirect
) {
982 ngx_unescape_uri(&dst
, &src
, e
->pos
- e
->buf
.data
,
983 NGX_UNESCAPE_REDIRECT
);
986 dst
= ngx_copy(dst
, src
, e
->pos
- src
);
991 if (code
->add_args
&& r
->args
.len
) {
992 *e
->pos
++ = (u_char
) (code
->args
? '&' : '?');
993 e
->pos
= ngx_copy(e
->pos
, r
->args
.data
, r
->args
.len
);
996 e
->buf
.len
= e
->pos
- e
->buf
.data
;
998 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
999 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
1000 "rewritten redirect: \"%V\"", &e
->buf
);
1003 r
->headers_out
.location
= ngx_list_push(&r
->headers_out
.headers
);
1004 if (r
->headers_out
.location
== NULL
) {
1005 e
->ip
= ngx_http_script_exit
;
1006 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1010 r
->headers_out
.location
->hash
= 1;
1011 r
->headers_out
.location
->key
.len
= sizeof("Location") - 1;
1012 r
->headers_out
.location
->key
.data
= (u_char
*) "Location";
1013 r
->headers_out
.location
->value
= e
->buf
;
1015 e
->ip
+= sizeof(ngx_http_script_regex_end_code_t
);
1020 e
->buf
.len
= e
->args
- e
->buf
.data
;
1022 if (code
->add_args
&& r
->args
.len
) {
1024 e
->pos
= ngx_copy(e
->pos
, r
->args
.data
, r
->args
.len
);
1027 r
->args
.len
= e
->pos
- e
->args
;
1028 r
->args
.data
= e
->args
;
1033 e
->buf
.len
= e
->pos
- e
->buf
.data
;
1035 if (!code
->add_args
) {
1040 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
1041 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
1042 "rewritten data: \"%V\", args: \"%V\"",
1049 if (r
->uri
.len
== 0) {
1050 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1051 "the rewritten URI has a zero length");
1052 e
->ip
= ngx_http_script_exit
;
1053 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1057 ngx_http_set_exten(r
);
1060 e
->ip
+= sizeof(ngx_http_script_regex_end_code_t
);
1065 ngx_http_script_add_capture_code(ngx_http_script_compile_t
*sc
, ngx_uint_t n
)
1067 ngx_http_script_copy_capture_code_t
*code
;
1069 code
= ngx_http_script_add_code(*sc
->lengths
,
1070 sizeof(ngx_http_script_copy_capture_code_t
),
1076 code
->code
= (ngx_http_script_code_pt
)
1077 ngx_http_script_copy_capture_len_code
;
1081 code
= ngx_http_script_add_code(*sc
->values
,
1082 sizeof(ngx_http_script_copy_capture_code_t
),
1088 code
->code
= ngx_http_script_copy_capture_code
;
1091 if (sc
->ncaptures
< n
) {
1100 ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t
*e
)
1105 ngx_http_request_t
*r
;
1106 ngx_http_script_copy_capture_code_t
*code
;
1110 code
= (ngx_http_script_copy_capture_code_t
*) e
->ip
;
1112 e
->ip
+= sizeof(ngx_http_script_copy_capture_code_t
);
1116 if (n
< r
->ncaptures
) {
1120 if ((e
->is_args
|| e
->quote
)
1121 && (e
->request
->quoted_uri
|| e
->request
->plus_in_uri
))
1123 p
= r
->captures_data
;
1125 return cap
[n
+ 1] - cap
[n
]
1126 + 2 * ngx_escape_uri(NULL
, &p
[cap
[n
]], cap
[n
+ 1] - cap
[n
],
1129 return cap
[n
+ 1] - cap
[n
];
1138 ngx_http_script_copy_capture_code(ngx_http_script_engine_t
*e
)
1143 ngx_http_request_t
*r
;
1144 ngx_http_script_copy_capture_code_t
*code
;
1148 code
= (ngx_http_script_copy_capture_code_t
*) e
->ip
;
1150 e
->ip
+= sizeof(ngx_http_script_copy_capture_code_t
);
1156 if (n
< r
->ncaptures
) {
1159 p
= r
->captures_data
;
1161 if ((e
->is_args
|| e
->quote
)
1162 && (e
->request
->quoted_uri
|| e
->request
->plus_in_uri
))
1164 e
->pos
= (u_char
*) ngx_escape_uri(pos
, &p
[cap
[n
]],
1165 cap
[n
+ 1] - cap
[n
],
1168 e
->pos
= ngx_copy(pos
, &p
[cap
[n
]], cap
[n
+ 1] - cap
[n
]);
1172 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1173 "http script capture: \"%*s\"", e
->pos
- pos
, pos
);
1180 ngx_http_script_add_full_name_code(ngx_http_script_compile_t
*sc
)
1182 ngx_http_script_full_name_code_t
*code
;
1184 code
= ngx_http_script_add_code(*sc
->lengths
,
1185 sizeof(ngx_http_script_full_name_code_t
),
1191 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_full_name_len_code
;
1192 code
->conf_prefix
= sc
->conf_prefix
;
1194 code
= ngx_http_script_add_code(*sc
->values
,
1195 sizeof(ngx_http_script_full_name_code_t
),
1201 code
->code
= ngx_http_script_full_name_code
;
1202 code
->conf_prefix
= sc
->conf_prefix
;
1209 ngx_http_script_full_name_len_code(ngx_http_script_engine_t
*e
)
1211 ngx_http_script_full_name_code_t
*code
;
1213 code
= (ngx_http_script_full_name_code_t
*) e
->ip
;
1215 e
->ip
+= sizeof(ngx_http_script_full_name_code_t
);
1217 return code
->conf_prefix
? ngx_cycle
->conf_prefix
.len
:
1218 ngx_cycle
->prefix
.len
;
1223 ngx_http_script_full_name_code(ngx_http_script_engine_t
*e
)
1225 ngx_http_script_full_name_code_t
*code
;
1229 code
= (ngx_http_script_full_name_code_t
*) e
->ip
;
1231 value
.data
= e
->buf
.data
;
1232 value
.len
= e
->pos
- e
->buf
.data
;
1234 if (ngx_conf_full_name((ngx_cycle_t
*) ngx_cycle
, &value
, code
->conf_prefix
)
1237 e
->ip
= ngx_http_script_exit
;
1238 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1244 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1245 "http script fullname: \"%V\"", &value
);
1247 e
->ip
+= sizeof(ngx_http_script_full_name_code_t
);
1252 ngx_http_script_return_code(ngx_http_script_engine_t
*e
)
1254 ngx_http_script_return_code_t
*code
;
1256 code
= (ngx_http_script_return_code_t
*) e
->ip
;
1258 e
->status
= code
->status
;
1260 if (code
->status
== NGX_HTTP_NO_CONTENT
) {
1261 e
->request
->header_only
= 1;
1262 e
->request
->zero_body
= 1;
1265 e
->ip
+= sizeof(ngx_http_script_return_code_t
) - sizeof(uintptr_t);
1270 ngx_http_script_break_code(ngx_http_script_engine_t
*e
)
1272 e
->request
->uri_changed
= 0;
1274 e
->ip
= ngx_http_script_exit
;
1279 ngx_http_script_if_code(ngx_http_script_engine_t
*e
)
1281 ngx_http_script_if_code_t
*code
;
1283 code
= (ngx_http_script_if_code_t
*) e
->ip
;
1285 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1290 if (e
->sp
->len
&& e
->sp
->data
[0] != '0') {
1291 if (code
->loc_conf
) {
1292 e
->request
->loc_conf
= code
->loc_conf
;
1293 ngx_http_update_location_config(e
->request
);
1296 e
->ip
+= sizeof(ngx_http_script_if_code_t
);
1300 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1301 "http script if: false");
1303 e
->ip
+= code
->next
;
1308 ngx_http_script_equal_code(ngx_http_script_engine_t
*e
)
1310 ngx_http_variable_value_t
*val
, *res
;
1312 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1313 "http script equal");
1319 e
->ip
+= sizeof(uintptr_t);
1321 if (val
->len
== res
->len
1322 && ngx_strncmp(val
->data
, res
->data
, res
->len
) == 0)
1324 *res
= ngx_http_variable_true_value
;
1328 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1329 "http script equal: no");
1331 *res
= ngx_http_variable_null_value
;
1336 ngx_http_script_not_equal_code(ngx_http_script_engine_t
*e
)
1338 ngx_http_variable_value_t
*val
, *res
;
1340 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1341 "http script not equal");
1347 e
->ip
+= sizeof(uintptr_t);
1349 if (val
->len
== res
->len
1350 && ngx_strncmp(val
->data
, res
->data
, res
->len
) == 0)
1352 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1353 "http script not equal: no");
1355 *res
= ngx_http_variable_null_value
;
1359 *res
= ngx_http_variable_true_value
;
1364 ngx_http_script_file_code(ngx_http_script_engine_t
*e
)
1367 ngx_http_request_t
*r
;
1368 ngx_open_file_info_t of
;
1369 ngx_http_core_loc_conf_t
*clcf
;
1370 ngx_http_variable_value_t
*value
;
1371 ngx_http_script_file_code_t
*code
;
1375 code
= (ngx_http_script_file_code_t
*) e
->ip
;
1376 e
->ip
+= sizeof(ngx_http_script_file_code_t
);
1378 path
.len
= value
->len
- 1;
1379 path
.data
= value
->data
;
1383 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1384 "http script file op %p \"%V\"", code
->op
, &path
);
1386 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1388 ngx_memzero(&of
, sizeof(ngx_open_file_info_t
));
1390 of
.read_ahead
= clcf
->read_ahead
;
1391 of
.directio
= clcf
->directio
;
1392 of
.valid
= clcf
->open_file_cache_valid
;
1393 of
.min_uses
= clcf
->open_file_cache_min_uses
;
1395 of
.errors
= clcf
->open_file_cache_errors
;
1396 of
.events
= clcf
->open_file_cache_events
;
1398 if (ngx_open_cached_file(clcf
->open_file_cache
, &path
, &of
, r
->pool
)
1401 if (of
.err
!= NGX_ENOENT
1402 && of
.err
!= NGX_ENOTDIR
1403 && of
.err
!= NGX_ENAMETOOLONG
)
1405 ngx_log_error(NGX_LOG_CRIT
, r
->connection
->log
, of
.err
,
1406 "%s \"%s\" failed", of
.failed
, value
->data
);
1411 case ngx_http_script_file_plain
:
1412 case ngx_http_script_file_dir
:
1413 case ngx_http_script_file_exists
:
1414 case ngx_http_script_file_exec
:
1417 case ngx_http_script_file_not_plain
:
1418 case ngx_http_script_file_not_dir
:
1419 case ngx_http_script_file_not_exists
:
1420 case ngx_http_script_file_not_exec
:
1428 case ngx_http_script_file_plain
:
1434 case ngx_http_script_file_not_plain
:
1440 case ngx_http_script_file_dir
:
1446 case ngx_http_script_file_not_dir
:
1452 case ngx_http_script_file_exists
:
1453 if (of
.is_file
|| of
.is_dir
|| of
.is_link
) {
1458 case ngx_http_script_file_not_exists
:
1459 if (of
.is_file
|| of
.is_dir
|| of
.is_link
) {
1464 case ngx_http_script_file_exec
:
1470 case ngx_http_script_file_not_exec
:
1479 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1480 "http script file op false");
1482 *value
= ngx_http_variable_null_value
;
1487 *value
= ngx_http_variable_true_value
;
1493 ngx_http_script_complex_value_code(ngx_http_script_engine_t
*e
)
1496 ngx_http_script_engine_t le
;
1497 ngx_http_script_len_code_pt lcode
;
1498 ngx_http_script_complex_value_code_t
*code
;
1500 code
= (ngx_http_script_complex_value_code_t
*) e
->ip
;
1502 e
->ip
+= sizeof(ngx_http_script_complex_value_code_t
);
1504 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1505 "http script complex value");
1507 ngx_memzero(&le
, sizeof(ngx_http_script_engine_t
));
1509 le
.ip
= code
->lengths
->elts
;
1511 le
.request
= e
->request
;
1512 le
.quote
= e
->quote
;
1514 for (len
= 0; *(uintptr_t *) le
.ip
; len
+= lcode(&le
)) {
1515 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
1519 e
->buf
.data
= ngx_pnalloc(e
->request
->pool
, len
);
1520 if (e
->buf
.data
== NULL
) {
1521 e
->ip
= ngx_http_script_exit
;
1522 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1526 e
->pos
= e
->buf
.data
;
1528 e
->sp
->len
= e
->buf
.len
;
1529 e
->sp
->data
= e
->buf
.data
;
1535 ngx_http_script_value_code(ngx_http_script_engine_t
*e
)
1537 ngx_http_script_value_code_t
*code
;
1539 code
= (ngx_http_script_value_code_t
*) e
->ip
;
1541 e
->ip
+= sizeof(ngx_http_script_value_code_t
);
1543 e
->sp
->len
= code
->text_len
;
1544 e
->sp
->data
= (u_char
*) code
->text_data
;
1546 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1547 "http script value: \"%v\"", e
->sp
);
1554 ngx_http_script_set_var_code(ngx_http_script_engine_t
*e
)
1556 ngx_http_request_t
*r
;
1557 ngx_http_script_var_code_t
*code
;
1559 code
= (ngx_http_script_var_code_t
*) e
->ip
;
1561 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
1567 r
->variables
[code
->index
].len
= e
->sp
->len
;
1568 r
->variables
[code
->index
].valid
= 1;
1569 r
->variables
[code
->index
].no_cacheable
= 0;
1570 r
->variables
[code
->index
].not_found
= 0;
1571 r
->variables
[code
->index
].data
= e
->sp
->data
;
1575 ngx_http_variable_t
*v
;
1576 ngx_http_core_main_conf_t
*cmcf
;
1578 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
1580 v
= cmcf
->variables
.elts
;
1582 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1583 "http script set $%V", &v
[code
->index
].name
);
1590 ngx_http_script_var_set_handler_code(ngx_http_script_engine_t
*e
)
1592 ngx_http_script_var_handler_code_t
*code
;
1594 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1595 "http script set var handler");
1597 code
= (ngx_http_script_var_handler_code_t
*) e
->ip
;
1599 e
->ip
+= sizeof(ngx_http_script_var_handler_code_t
);
1603 code
->handler(e
->request
, e
->sp
, code
->data
);
1608 ngx_http_script_var_code(ngx_http_script_engine_t
*e
)
1610 ngx_http_variable_value_t
*value
;
1611 ngx_http_script_var_code_t
*code
;
1613 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1616 code
= (ngx_http_script_var_code_t
*) e
->ip
;
1618 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
1620 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
1622 if (value
&& !value
->not_found
) {
1623 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1624 "http script var: \"%v\"", value
);
1632 *e
->sp
= ngx_http_variable_null_value
;
1638 ngx_http_script_nop_code(ngx_http_script_engine_t
*e
)
1640 e
->ip
+= sizeof(uintptr_t);