3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
13 static ngx_int_t
ngx_http_script_init_arrays(ngx_http_script_compile_t
*sc
);
14 static ngx_int_t
ngx_http_script_done(ngx_http_script_compile_t
*sc
);
15 static ngx_int_t
ngx_http_script_add_copy_code(ngx_http_script_compile_t
*sc
,
16 ngx_str_t
*value
, ngx_uint_t last
);
17 static ngx_int_t
ngx_http_script_add_var_code(ngx_http_script_compile_t
*sc
,
19 static ngx_int_t
ngx_http_script_add_args_code(ngx_http_script_compile_t
*sc
);
21 static ngx_int_t
ngx_http_script_add_capture_code(ngx_http_script_compile_t
*sc
,
25 ngx_http_script_add_full_name_code(ngx_http_script_compile_t
*sc
);
26 static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t
*e
);
27 static void ngx_http_script_full_name_code(ngx_http_script_engine_t
*e
);
30 #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
32 static uintptr_t ngx_http_script_exit_code
= (uintptr_t) NULL
;
36 ngx_http_script_flush_complex_value(ngx_http_request_t
*r
,
37 ngx_http_complex_value_t
*val
)
44 while (*index
!= (ngx_uint_t
) -1) {
46 if (r
->variables
[*index
].no_cacheable
) {
47 r
->variables
[*index
].valid
= 0;
48 r
->variables
[*index
].not_found
= 0;
58 ngx_http_complex_value(ngx_http_request_t
*r
, ngx_http_complex_value_t
*val
,
62 ngx_http_script_code_pt code
;
63 ngx_http_script_len_code_pt lcode
;
64 ngx_http_script_engine_t e
;
66 if (val
->lengths
== NULL
) {
71 ngx_http_script_flush_complex_value(r
, val
);
73 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
81 while (*(uintptr_t *) e
.ip
) {
82 lcode
= *(ngx_http_script_len_code_pt
*) e
.ip
;
87 value
->data
= ngx_pnalloc(r
->pool
, len
);
88 if (value
->data
== NULL
) {
96 while (*(uintptr_t *) e
.ip
) {
97 code
= *(ngx_http_script_code_pt
*) e
.ip
;
98 code((ngx_http_script_engine_t
*) &e
);
108 ngx_http_compile_complex_value(ngx_http_compile_complex_value_t
*ccv
)
111 ngx_uint_t i
, n
, nv
, nc
;
112 ngx_array_t flushes
, lengths
, values
, *pf
, *pl
, *pv
;
113 ngx_http_script_compile_t sc
;
120 for (i
= 0; i
< v
->len
; i
++) {
121 if (v
->data
[i
] == '$') {
122 if (v
->data
[i
+ 1] >= '1' && v
->data
[i
+ 1] <= '9') {
131 if ((v
->len
== 0 || v
->data
[0] != '$')
132 && (ccv
->conf_prefix
|| ccv
->root_prefix
))
134 if (ngx_conf_full_name(ccv
->cf
->cycle
, v
, ccv
->conf_prefix
) != NGX_OK
) {
138 ccv
->conf_prefix
= 0;
139 ccv
->root_prefix
= 0;
142 ccv
->complex_value
->value
= *v
;
143 ccv
->complex_value
->flushes
= NULL
;
144 ccv
->complex_value
->lengths
= NULL
;
145 ccv
->complex_value
->values
= NULL
;
147 if (nv
== 0 && nc
== 0) {
153 if (ngx_array_init(&flushes
, ccv
->cf
->pool
, n
, sizeof(ngx_uint_t
))
159 n
= nv
* (2 * sizeof(ngx_http_script_copy_code_t
)
160 + sizeof(ngx_http_script_var_code_t
))
163 if (ngx_array_init(&lengths
, ccv
->cf
->pool
, n
, 1) != NGX_OK
) {
167 n
= (nv
* (2 * sizeof(ngx_http_script_copy_code_t
)
168 + sizeof(ngx_http_script_var_code_t
))
171 + sizeof(uintptr_t) - 1)
172 & ~(sizeof(uintptr_t) - 1);
174 if (ngx_array_init(&values
, ccv
->cf
->pool
, n
, 1) != NGX_OK
) {
182 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
189 sc
.complete_lengths
= 1;
190 sc
.complete_values
= 1;
192 sc
.conf_prefix
= ccv
->conf_prefix
;
193 sc
.root_prefix
= ccv
->root_prefix
;
195 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
200 ccv
->complex_value
->flushes
= flushes
.elts
;
201 ccv
->complex_value
->flushes
[flushes
.nelts
] = (ngx_uint_t
) -1;
204 ccv
->complex_value
->lengths
= lengths
.elts
;
205 ccv
->complex_value
->values
= values
.elts
;
212 ngx_http_set_complex_value_slot(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
217 ngx_http_complex_value_t
**cv
;
218 ngx_http_compile_complex_value_t ccv
;
220 cv
= (ngx_http_complex_value_t
**) (p
+ cmd
->offset
);
226 *cv
= ngx_palloc(cf
->pool
, sizeof(ngx_http_complex_value_t
));
228 return NGX_CONF_ERROR
;
231 value
= cf
->args
->elts
;
233 ngx_memzero(&ccv
, sizeof(ngx_http_compile_complex_value_t
));
236 ccv
.value
= &value
[1];
237 ccv
.complex_value
= *cv
;
239 if (ngx_http_compile_complex_value(&ccv
) != NGX_OK
) {
240 return NGX_CONF_ERROR
;
248 ngx_http_test_predicates(ngx_http_request_t
*r
, ngx_array_t
*predicates
)
252 ngx_http_complex_value_t
*cv
;
254 if (predicates
== NULL
) {
258 cv
= predicates
->elts
;
260 for (i
= 0; i
< predicates
->nelts
; i
++) {
261 if (ngx_http_complex_value(r
, &cv
[i
], &val
) != NGX_OK
) {
265 if (val
.len
&& (val
.len
!= 1 || val
.data
[0] != '0')) {
275 ngx_http_set_predicate_slot(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
282 ngx_http_complex_value_t
*cv
;
283 ngx_http_compile_complex_value_t ccv
;
285 a
= (ngx_array_t
**) (p
+ cmd
->offset
);
287 if (*a
== NGX_CONF_UNSET_PTR
) {
288 *a
= ngx_array_create(cf
->pool
, 1, sizeof(ngx_http_complex_value_t
));
290 return NGX_CONF_ERROR
;
294 value
= cf
->args
->elts
;
296 for (i
= 1; i
< cf
->args
->nelts
; i
++) {
297 cv
= ngx_array_push(*a
);
299 return NGX_CONF_ERROR
;
302 ngx_memzero(&ccv
, sizeof(ngx_http_compile_complex_value_t
));
305 ccv
.value
= &value
[i
];
306 ccv
.complex_value
= cv
;
308 if (ngx_http_compile_complex_value(&ccv
) != NGX_OK
) {
309 return NGX_CONF_ERROR
;
318 ngx_http_script_variables_count(ngx_str_t
*value
)
322 for (n
= 0, i
= 0; i
< value
->len
; i
++) {
323 if (value
->data
[i
] == '$') {
333 ngx_http_script_compile(ngx_http_script_compile_t
*sc
)
337 ngx_uint_t i
, bracket
;
339 if (ngx_http_script_init_arrays(sc
) != NGX_OK
) {
343 for (i
= 0; i
< sc
->source
->len
; /* void */ ) {
347 if (sc
->source
->data
[i
] == '$') {
349 if (++i
== sc
->source
->len
) {
350 goto invalid_variable
;
357 if (sc
->source
->data
[i
] >= '1' && sc
->source
->data
[i
] <= '9') {
359 n
= sc
->source
->data
[i
] - '0';
361 if (sc
->captures_mask
& (1 << n
)) {
365 sc
->captures_mask
|= 1 << n
;
367 if (ngx_http_script_add_capture_code(sc
, n
) != NGX_OK
) {
378 if (sc
->source
->data
[i
] == '{') {
381 if (++i
== sc
->source
->len
) {
382 goto invalid_variable
;
385 name
.data
= &sc
->source
->data
[i
];
389 name
.data
= &sc
->source
->data
[i
];
392 for ( /* void */ ; i
< sc
->source
->len
; i
++, name
.len
++) {
393 ch
= sc
->source
->data
[i
];
395 if (ch
== '}' && bracket
) {
401 if ((ch
>= 'A' && ch
<= 'Z')
402 || (ch
>= 'a' && ch
<= 'z')
403 || (ch
>= '0' && ch
<= '9')
413 ngx_conf_log_error(NGX_LOG_EMERG
, sc
->cf
, 0,
414 "the closing bracket in \"%V\" "
415 "variable is missing", &name
);
420 goto invalid_variable
;
425 if (ngx_http_script_add_var_code(sc
, &name
) != NGX_OK
) {
432 if (sc
->source
->data
[i
] == '?' && sc
->compile_args
) {
434 sc
->compile_args
= 0;
436 if (ngx_http_script_add_args_code(sc
) != NGX_OK
) {
445 name
.data
= &sc
->source
->data
[i
];
447 while (i
< sc
->source
->len
) {
449 if (sc
->source
->data
[i
] == '$') {
453 if (sc
->source
->data
[i
] == '?') {
457 if (sc
->compile_args
) {
466 sc
->size
+= name
.len
;
468 if (ngx_http_script_add_copy_code(sc
, &name
, (i
== sc
->source
->len
))
475 return ngx_http_script_done(sc
);
479 ngx_conf_log_error(NGX_LOG_EMERG
, sc
->cf
, 0, "invalid variable name");
486 ngx_http_script_run(ngx_http_request_t
*r
, ngx_str_t
*value
,
487 void *code_lengths
, size_t len
, void *code_values
)
490 ngx_http_script_code_pt code
;
491 ngx_http_script_len_code_pt lcode
;
492 ngx_http_script_engine_t e
;
493 ngx_http_core_main_conf_t
*cmcf
;
495 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
497 for (i
= 0; i
< cmcf
->variables
.nelts
; i
++) {
498 if (r
->variables
[i
].no_cacheable
) {
499 r
->variables
[i
].valid
= 0;
500 r
->variables
[i
].not_found
= 0;
504 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
510 while (*(uintptr_t *) e
.ip
) {
511 lcode
= *(ngx_http_script_len_code_pt
*) e
.ip
;
517 value
->data
= ngx_pnalloc(r
->pool
, len
);
518 if (value
->data
== NULL
) {
525 while (*(uintptr_t *) e
.ip
) {
526 code
= *(ngx_http_script_code_pt
*) e
.ip
;
527 code((ngx_http_script_engine_t
*) &e
);
535 ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t
*r
,
536 ngx_array_t
*indices
)
538 ngx_uint_t n
, *index
;
541 index
= indices
->elts
;
542 for (n
= 0; n
< indices
->nelts
; n
++) {
543 if (r
->variables
[index
[n
]].no_cacheable
) {
544 r
->variables
[index
[n
]].valid
= 0;
545 r
->variables
[index
[n
]].not_found
= 0;
553 ngx_http_script_init_arrays(ngx_http_script_compile_t
*sc
)
557 if (sc
->flushes
&& *sc
->flushes
== NULL
) {
558 n
= sc
->variables
? sc
->variables
: 1;
559 *sc
->flushes
= ngx_array_create(sc
->cf
->pool
, n
, sizeof(ngx_uint_t
));
560 if (*sc
->flushes
== NULL
) {
565 if (*sc
->lengths
== NULL
) {
566 n
= sc
->variables
* (2 * sizeof(ngx_http_script_copy_code_t
)
567 + sizeof(ngx_http_script_var_code_t
))
570 *sc
->lengths
= ngx_array_create(sc
->cf
->pool
, n
, 1);
571 if (*sc
->lengths
== NULL
) {
576 if (*sc
->values
== NULL
) {
577 n
= (sc
->variables
* (2 * sizeof(ngx_http_script_copy_code_t
)
578 + sizeof(ngx_http_script_var_code_t
))
581 + sizeof(uintptr_t) - 1)
582 & ~(sizeof(uintptr_t) - 1);
584 *sc
->values
= ngx_array_create(sc
->cf
->pool
, n
, 1);
585 if (*sc
->values
== NULL
) {
597 ngx_http_script_done(ngx_http_script_compile_t
*sc
)
605 zero
.data
= (u_char
*) "\0";
607 if (ngx_http_script_add_copy_code(sc
, &zero
, 0) != NGX_OK
) {
612 if (sc
->conf_prefix
|| sc
->root_prefix
) {
613 if (ngx_http_script_add_full_name_code(sc
) != NGX_OK
) {
618 if (sc
->complete_lengths
) {
619 code
= ngx_http_script_add_code(*sc
->lengths
, sizeof(uintptr_t), NULL
);
624 *code
= (uintptr_t) NULL
;
627 if (sc
->complete_values
) {
628 code
= ngx_http_script_add_code(*sc
->values
, sizeof(uintptr_t),
634 *code
= (uintptr_t) NULL
;
642 ngx_http_script_start_code(ngx_pool_t
*pool
, ngx_array_t
**codes
, size_t size
)
644 if (*codes
== NULL
) {
645 *codes
= ngx_array_create(pool
, 256, 1);
646 if (*codes
== NULL
) {
651 return ngx_array_push_n(*codes
, size
);
656 ngx_http_script_add_code(ngx_array_t
*codes
, size_t size
, void *code
)
663 new = ngx_array_push_n(codes
, size
);
669 if (elts
!= codes
->elts
) {
671 *p
+= (u_char
*) codes
->elts
- elts
;
680 ngx_http_script_add_copy_code(ngx_http_script_compile_t
*sc
, ngx_str_t
*value
,
684 size_t size
, len
, zero
;
685 ngx_http_script_copy_code_t
*code
;
687 zero
= (sc
->zero
&& last
);
688 len
= value
->len
+ zero
;
690 code
= ngx_http_script_add_code(*sc
->lengths
,
691 sizeof(ngx_http_script_copy_code_t
), NULL
);
696 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_len_code
;
699 size
= (sizeof(ngx_http_script_copy_code_t
) + len
+ sizeof(uintptr_t) - 1)
700 & ~(sizeof(uintptr_t) - 1);
702 code
= ngx_http_script_add_code(*sc
->values
, size
, &sc
->main
);
707 code
->code
= ngx_http_script_copy_code
;
710 p
= ngx_cpymem((u_char
*) code
+ sizeof(ngx_http_script_copy_code_t
),
711 value
->data
, value
->len
);
723 ngx_http_script_copy_len_code(ngx_http_script_engine_t
*e
)
725 ngx_http_script_copy_code_t
*code
;
727 code
= (ngx_http_script_copy_code_t
*) e
->ip
;
729 e
->ip
+= sizeof(ngx_http_script_copy_code_t
);
736 ngx_http_script_copy_code(ngx_http_script_engine_t
*e
)
739 ngx_http_script_copy_code_t
*code
;
741 code
= (ngx_http_script_copy_code_t
*) e
->ip
;
746 e
->pos
= ngx_copy(p
, e
->ip
+ sizeof(ngx_http_script_copy_code_t
),
750 e
->ip
+= sizeof(ngx_http_script_copy_code_t
)
751 + ((code
->len
+ sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
753 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
754 "http script copy: \"%*s\"", e
->pos
- p
, p
);
759 ngx_http_script_add_var_code(ngx_http_script_compile_t
*sc
, ngx_str_t
*name
)
762 ngx_http_script_var_code_t
*code
;
764 index
= ngx_http_get_variable_index(sc
->cf
, name
);
766 if (index
== NGX_ERROR
) {
771 p
= ngx_array_push(*sc
->flushes
);
779 code
= ngx_http_script_add_code(*sc
->lengths
,
780 sizeof(ngx_http_script_var_code_t
), NULL
);
785 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_var_len_code
;
786 code
->index
= (uintptr_t) index
;
788 code
= ngx_http_script_add_code(*sc
->values
,
789 sizeof(ngx_http_script_var_code_t
),
795 code
->code
= ngx_http_script_copy_var_code
;
796 code
->index
= (uintptr_t) index
;
803 ngx_http_script_copy_var_len_code(ngx_http_script_engine_t
*e
)
805 ngx_http_variable_value_t
*value
;
806 ngx_http_script_var_code_t
*code
;
808 code
= (ngx_http_script_var_code_t
*) e
->ip
;
810 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
813 value
= ngx_http_get_indexed_variable(e
->request
, code
->index
);
816 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
819 if (value
&& !value
->not_found
) {
828 ngx_http_script_copy_var_code(ngx_http_script_engine_t
*e
)
831 ngx_http_variable_value_t
*value
;
832 ngx_http_script_var_code_t
*code
;
834 code
= (ngx_http_script_var_code_t
*) e
->ip
;
836 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
841 value
= ngx_http_get_indexed_variable(e
->request
, code
->index
);
844 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
847 if (value
&& !value
->not_found
) {
849 e
->pos
= ngx_copy(p
, value
->data
, value
->len
);
851 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
,
852 e
->request
->connection
->log
, 0,
853 "http script var: \"%*s\"", e
->pos
- p
, p
);
860 ngx_http_script_add_args_code(ngx_http_script_compile_t
*sc
)
864 code
= ngx_http_script_add_code(*sc
->lengths
, sizeof(uintptr_t), NULL
);
869 *code
= (uintptr_t) ngx_http_script_mark_args_code
;
871 code
= ngx_http_script_add_code(*sc
->values
, sizeof(uintptr_t), &sc
->main
);
876 *code
= (uintptr_t) ngx_http_script_start_args_code
;
883 ngx_http_script_mark_args_code(ngx_http_script_engine_t
*e
)
886 e
->ip
+= sizeof(uintptr_t);
893 ngx_http_script_start_args_code(ngx_http_script_engine_t
*e
)
895 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
900 e
->ip
+= sizeof(uintptr_t);
907 ngx_http_script_regex_start_code(ngx_http_script_engine_t
*e
)
912 ngx_http_request_t
*r
;
913 ngx_http_script_engine_t le
;
914 ngx_http_script_len_code_pt lcode
;
915 ngx_http_script_regex_code_t
*code
;
917 code
= (ngx_http_script_regex_code_t
*) e
->ip
;
921 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
922 "http script regex: \"%V\"", &code
->name
);
928 e
->line
.len
= e
->sp
->len
;
929 e
->line
.data
= e
->sp
->data
;
932 rc
= ngx_http_regex_exec(r
, code
->regex
, &e
->line
);
934 if (rc
== NGX_DECLINED
) {
935 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
936 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
937 "\"%V\" does not match \"%V\"",
938 &code
->name
, &e
->line
);
944 if (code
->negative_test
) {
946 e
->sp
->data
= (u_char
*) "1";
950 e
->sp
->data
= (u_char
*) "";
955 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
963 if (rc
== NGX_ERROR
) {
964 e
->ip
= ngx_http_script_exit
;
965 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
969 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
970 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
971 "\"%V\" matches \"%V\"", &code
->name
, &e
->line
);
975 if (code
->negative_test
) {
977 e
->sp
->data
= (u_char
*) "";
981 e
->sp
->data
= (u_char
*) "1";
986 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
991 e
->status
= code
->status
;
993 if (!code
->redirect
) {
994 e
->ip
= ngx_http_script_exit
;
1001 r
->valid_unparsed_uri
= 0;
1003 if (code
->break_cycle
) {
1004 r
->valid_location
= 0;
1012 if (code
->lengths
== NULL
) {
1013 e
->buf
.len
= code
->size
;
1016 if (r
->ncaptures
&& (r
->quoted_uri
|| r
->plus_in_uri
)) {
1017 e
->buf
.len
+= 2 * ngx_escape_uri(NULL
, r
->uri
.data
, r
->uri
.len
,
1022 for (n
= 2; n
< r
->ncaptures
; n
+= 2) {
1023 e
->buf
.len
+= r
->captures
[n
+ 1] - r
->captures
[n
];
1027 ngx_memzero(&le
, sizeof(ngx_http_script_engine_t
));
1029 le
.ip
= code
->lengths
->elts
;
1032 le
.quote
= code
->redirect
;
1036 while (*(uintptr_t *) le
.ip
) {
1037 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
1044 if (code
->add_args
&& r
->args
.len
) {
1045 e
->buf
.len
+= r
->args
.len
+ 1;
1048 e
->buf
.data
= ngx_pnalloc(r
->pool
, e
->buf
.len
);
1049 if (e
->buf
.data
== NULL
) {
1050 e
->ip
= ngx_http_script_exit
;
1051 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1055 e
->quote
= code
->redirect
;
1057 e
->pos
= e
->buf
.data
;
1059 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
1064 ngx_http_script_regex_end_code(ngx_http_script_engine_t
*e
)
1067 ngx_http_request_t
*r
;
1068 ngx_http_script_regex_end_code_t
*code
;
1070 code
= (ngx_http_script_regex_end_code_t
*) e
->ip
;
1076 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1077 "http script regex end");
1079 if (code
->redirect
) {
1084 ngx_unescape_uri(&dst
, &src
, e
->pos
- e
->buf
.data
,
1085 NGX_UNESCAPE_REDIRECT
);
1088 dst
= ngx_movemem(dst
, src
, e
->pos
- src
);
1093 if (code
->add_args
&& r
->args
.len
) {
1094 *e
->pos
++ = (u_char
) (code
->args
? '&' : '?');
1095 e
->pos
= ngx_copy(e
->pos
, r
->args
.data
, r
->args
.len
);
1098 e
->buf
.len
= e
->pos
- e
->buf
.data
;
1100 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
1101 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
1102 "rewritten redirect: \"%V\"", &e
->buf
);
1105 ngx_http_clear_location(r
);
1107 r
->headers_out
.location
= ngx_list_push(&r
->headers_out
.headers
);
1108 if (r
->headers_out
.location
== NULL
) {
1109 e
->ip
= ngx_http_script_exit
;
1110 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1114 r
->headers_out
.location
->hash
= 1;
1115 ngx_str_set(&r
->headers_out
.location
->key
, "Location");
1116 r
->headers_out
.location
->value
= e
->buf
;
1118 e
->ip
+= sizeof(ngx_http_script_regex_end_code_t
);
1123 e
->buf
.len
= e
->args
- e
->buf
.data
;
1125 if (code
->add_args
&& r
->args
.len
) {
1127 e
->pos
= ngx_copy(e
->pos
, r
->args
.data
, r
->args
.len
);
1130 r
->args
.len
= e
->pos
- e
->args
;
1131 r
->args
.data
= e
->args
;
1136 e
->buf
.len
= e
->pos
- e
->buf
.data
;
1138 if (!code
->add_args
) {
1143 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
1144 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
1145 "rewritten data: \"%V\", args: \"%V\"",
1152 if (r
->uri
.len
== 0) {
1153 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1154 "the rewritten URI has a zero length");
1155 e
->ip
= ngx_http_script_exit
;
1156 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1160 ngx_http_set_exten(r
);
1163 e
->ip
+= sizeof(ngx_http_script_regex_end_code_t
);
1168 ngx_http_script_add_capture_code(ngx_http_script_compile_t
*sc
, ngx_uint_t n
)
1170 ngx_http_script_copy_capture_code_t
*code
;
1172 code
= ngx_http_script_add_code(*sc
->lengths
,
1173 sizeof(ngx_http_script_copy_capture_code_t
),
1179 code
->code
= (ngx_http_script_code_pt
)
1180 ngx_http_script_copy_capture_len_code
;
1184 code
= ngx_http_script_add_code(*sc
->values
,
1185 sizeof(ngx_http_script_copy_capture_code_t
),
1191 code
->code
= ngx_http_script_copy_capture_code
;
1194 if (sc
->ncaptures
< n
) {
1203 ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t
*e
)
1208 ngx_http_request_t
*r
;
1209 ngx_http_script_copy_capture_code_t
*code
;
1213 code
= (ngx_http_script_copy_capture_code_t
*) e
->ip
;
1215 e
->ip
+= sizeof(ngx_http_script_copy_capture_code_t
);
1219 if (n
< r
->ncaptures
) {
1223 if ((e
->is_args
|| e
->quote
)
1224 && (e
->request
->quoted_uri
|| e
->request
->plus_in_uri
))
1226 p
= r
->captures_data
;
1228 return cap
[n
+ 1] - cap
[n
]
1229 + 2 * ngx_escape_uri(NULL
, &p
[cap
[n
]], cap
[n
+ 1] - cap
[n
],
1232 return cap
[n
+ 1] - cap
[n
];
1241 ngx_http_script_copy_capture_code(ngx_http_script_engine_t
*e
)
1246 ngx_http_request_t
*r
;
1247 ngx_http_script_copy_capture_code_t
*code
;
1251 code
= (ngx_http_script_copy_capture_code_t
*) e
->ip
;
1253 e
->ip
+= sizeof(ngx_http_script_copy_capture_code_t
);
1259 if (n
< r
->ncaptures
) {
1262 p
= r
->captures_data
;
1264 if ((e
->is_args
|| e
->quote
)
1265 && (e
->request
->quoted_uri
|| e
->request
->plus_in_uri
))
1267 e
->pos
= (u_char
*) ngx_escape_uri(pos
, &p
[cap
[n
]],
1268 cap
[n
+ 1] - cap
[n
],
1271 e
->pos
= ngx_copy(pos
, &p
[cap
[n
]], cap
[n
+ 1] - cap
[n
]);
1275 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1276 "http script capture: \"%*s\"", e
->pos
- pos
, pos
);
1283 ngx_http_script_add_full_name_code(ngx_http_script_compile_t
*sc
)
1285 ngx_http_script_full_name_code_t
*code
;
1287 code
= ngx_http_script_add_code(*sc
->lengths
,
1288 sizeof(ngx_http_script_full_name_code_t
),
1294 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_full_name_len_code
;
1295 code
->conf_prefix
= sc
->conf_prefix
;
1297 code
= ngx_http_script_add_code(*sc
->values
,
1298 sizeof(ngx_http_script_full_name_code_t
),
1304 code
->code
= ngx_http_script_full_name_code
;
1305 code
->conf_prefix
= sc
->conf_prefix
;
1312 ngx_http_script_full_name_len_code(ngx_http_script_engine_t
*e
)
1314 ngx_http_script_full_name_code_t
*code
;
1316 code
= (ngx_http_script_full_name_code_t
*) e
->ip
;
1318 e
->ip
+= sizeof(ngx_http_script_full_name_code_t
);
1320 return code
->conf_prefix
? ngx_cycle
->conf_prefix
.len
:
1321 ngx_cycle
->prefix
.len
;
1326 ngx_http_script_full_name_code(ngx_http_script_engine_t
*e
)
1328 ngx_http_script_full_name_code_t
*code
;
1332 code
= (ngx_http_script_full_name_code_t
*) e
->ip
;
1334 value
.data
= e
->buf
.data
;
1335 value
.len
= e
->pos
- e
->buf
.data
;
1337 if (ngx_conf_full_name((ngx_cycle_t
*) ngx_cycle
, &value
, code
->conf_prefix
)
1340 e
->ip
= ngx_http_script_exit
;
1341 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1347 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1348 "http script fullname: \"%V\"", &value
);
1350 e
->ip
+= sizeof(ngx_http_script_full_name_code_t
);
1355 ngx_http_script_return_code(ngx_http_script_engine_t
*e
)
1357 ngx_http_script_return_code_t
*code
;
1359 code
= (ngx_http_script_return_code_t
*) e
->ip
;
1361 if (code
->status
< NGX_HTTP_BAD_REQUEST
1362 || code
->text
.value
.len
1363 || code
->text
.lengths
)
1365 e
->status
= ngx_http_send_response(e
->request
, code
->status
, NULL
,
1368 e
->status
= code
->status
;
1371 e
->ip
= ngx_http_script_exit
;
1376 ngx_http_script_break_code(ngx_http_script_engine_t
*e
)
1378 e
->request
->uri_changed
= 0;
1380 e
->ip
= ngx_http_script_exit
;
1385 ngx_http_script_if_code(ngx_http_script_engine_t
*e
)
1387 ngx_http_script_if_code_t
*code
;
1389 code
= (ngx_http_script_if_code_t
*) e
->ip
;
1391 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1396 if (e
->sp
->len
&& (e
->sp
->len
!=1 || e
->sp
->data
[0] != '0')) {
1397 if (code
->loc_conf
) {
1398 e
->request
->loc_conf
= code
->loc_conf
;
1399 ngx_http_update_location_config(e
->request
);
1402 e
->ip
+= sizeof(ngx_http_script_if_code_t
);
1406 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1407 "http script if: false");
1409 e
->ip
+= code
->next
;
1414 ngx_http_script_equal_code(ngx_http_script_engine_t
*e
)
1416 ngx_http_variable_value_t
*val
, *res
;
1418 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1419 "http script equal");
1425 e
->ip
+= sizeof(uintptr_t);
1427 if (val
->len
== res
->len
1428 && ngx_strncmp(val
->data
, res
->data
, res
->len
) == 0)
1430 *res
= ngx_http_variable_true_value
;
1434 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1435 "http script equal: no");
1437 *res
= ngx_http_variable_null_value
;
1442 ngx_http_script_not_equal_code(ngx_http_script_engine_t
*e
)
1444 ngx_http_variable_value_t
*val
, *res
;
1446 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1447 "http script not equal");
1453 e
->ip
+= sizeof(uintptr_t);
1455 if (val
->len
== res
->len
1456 && ngx_strncmp(val
->data
, res
->data
, res
->len
) == 0)
1458 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1459 "http script not equal: no");
1461 *res
= ngx_http_variable_null_value
;
1465 *res
= ngx_http_variable_true_value
;
1470 ngx_http_script_file_code(ngx_http_script_engine_t
*e
)
1473 ngx_http_request_t
*r
;
1474 ngx_open_file_info_t of
;
1475 ngx_http_core_loc_conf_t
*clcf
;
1476 ngx_http_variable_value_t
*value
;
1477 ngx_http_script_file_code_t
*code
;
1481 code
= (ngx_http_script_file_code_t
*) e
->ip
;
1482 e
->ip
+= sizeof(ngx_http_script_file_code_t
);
1484 path
.len
= value
->len
- 1;
1485 path
.data
= value
->data
;
1489 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1490 "http script file op %p \"%V\"", code
->op
, &path
);
1492 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1494 ngx_memzero(&of
, sizeof(ngx_open_file_info_t
));
1496 of
.read_ahead
= clcf
->read_ahead
;
1497 of
.directio
= clcf
->directio
;
1498 of
.valid
= clcf
->open_file_cache_valid
;
1499 of
.min_uses
= clcf
->open_file_cache_min_uses
;
1501 of
.errors
= clcf
->open_file_cache_errors
;
1502 of
.events
= clcf
->open_file_cache_events
;
1504 if (ngx_http_set_disable_symlinks(r
, clcf
, &path
, &of
) != NGX_OK
) {
1505 e
->ip
= ngx_http_script_exit
;
1506 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1510 if (ngx_open_cached_file(clcf
->open_file_cache
, &path
, &of
, r
->pool
)
1513 if (of
.err
!= NGX_ENOENT
1514 && of
.err
!= NGX_ENOTDIR
1515 && of
.err
!= NGX_ENAMETOOLONG
)
1517 ngx_log_error(NGX_LOG_CRIT
, r
->connection
->log
, of
.err
,
1518 "%s \"%s\" failed", of
.failed
, value
->data
);
1523 case ngx_http_script_file_plain
:
1524 case ngx_http_script_file_dir
:
1525 case ngx_http_script_file_exists
:
1526 case ngx_http_script_file_exec
:
1529 case ngx_http_script_file_not_plain
:
1530 case ngx_http_script_file_not_dir
:
1531 case ngx_http_script_file_not_exists
:
1532 case ngx_http_script_file_not_exec
:
1540 case ngx_http_script_file_plain
:
1546 case ngx_http_script_file_not_plain
:
1552 case ngx_http_script_file_dir
:
1558 case ngx_http_script_file_not_dir
:
1564 case ngx_http_script_file_exists
:
1565 if (of
.is_file
|| of
.is_dir
|| of
.is_link
) {
1570 case ngx_http_script_file_not_exists
:
1571 if (of
.is_file
|| of
.is_dir
|| of
.is_link
) {
1576 case ngx_http_script_file_exec
:
1582 case ngx_http_script_file_not_exec
:
1591 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1592 "http script file op false");
1594 *value
= ngx_http_variable_null_value
;
1599 *value
= ngx_http_variable_true_value
;
1605 ngx_http_script_complex_value_code(ngx_http_script_engine_t
*e
)
1608 ngx_http_script_engine_t le
;
1609 ngx_http_script_len_code_pt lcode
;
1610 ngx_http_script_complex_value_code_t
*code
;
1612 code
= (ngx_http_script_complex_value_code_t
*) e
->ip
;
1614 e
->ip
+= sizeof(ngx_http_script_complex_value_code_t
);
1616 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1617 "http script complex value");
1619 ngx_memzero(&le
, sizeof(ngx_http_script_engine_t
));
1621 le
.ip
= code
->lengths
->elts
;
1623 le
.request
= e
->request
;
1624 le
.quote
= e
->quote
;
1626 for (len
= 0; *(uintptr_t *) le
.ip
; len
+= lcode(&le
)) {
1627 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
1631 e
->buf
.data
= ngx_pnalloc(e
->request
->pool
, len
);
1632 if (e
->buf
.data
== NULL
) {
1633 e
->ip
= ngx_http_script_exit
;
1634 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1638 e
->pos
= e
->buf
.data
;
1640 e
->sp
->len
= e
->buf
.len
;
1641 e
->sp
->data
= e
->buf
.data
;
1647 ngx_http_script_value_code(ngx_http_script_engine_t
*e
)
1649 ngx_http_script_value_code_t
*code
;
1651 code
= (ngx_http_script_value_code_t
*) e
->ip
;
1653 e
->ip
+= sizeof(ngx_http_script_value_code_t
);
1655 e
->sp
->len
= code
->text_len
;
1656 e
->sp
->data
= (u_char
*) code
->text_data
;
1658 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1659 "http script value: \"%v\"", e
->sp
);
1666 ngx_http_script_set_var_code(ngx_http_script_engine_t
*e
)
1668 ngx_http_request_t
*r
;
1669 ngx_http_script_var_code_t
*code
;
1671 code
= (ngx_http_script_var_code_t
*) e
->ip
;
1673 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
1679 r
->variables
[code
->index
].len
= e
->sp
->len
;
1680 r
->variables
[code
->index
].valid
= 1;
1681 r
->variables
[code
->index
].no_cacheable
= 0;
1682 r
->variables
[code
->index
].not_found
= 0;
1683 r
->variables
[code
->index
].data
= e
->sp
->data
;
1687 ngx_http_variable_t
*v
;
1688 ngx_http_core_main_conf_t
*cmcf
;
1690 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
1692 v
= cmcf
->variables
.elts
;
1694 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1695 "http script set $%V", &v
[code
->index
].name
);
1702 ngx_http_script_var_set_handler_code(ngx_http_script_engine_t
*e
)
1704 ngx_http_script_var_handler_code_t
*code
;
1706 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1707 "http script set var handler");
1709 code
= (ngx_http_script_var_handler_code_t
*) e
->ip
;
1711 e
->ip
+= sizeof(ngx_http_script_var_handler_code_t
);
1715 code
->handler(e
->request
, e
->sp
, code
->data
);
1720 ngx_http_script_var_code(ngx_http_script_engine_t
*e
)
1722 ngx_http_variable_value_t
*value
;
1723 ngx_http_script_var_code_t
*code
;
1725 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1728 code
= (ngx_http_script_var_code_t
*) e
->ip
;
1730 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
1732 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
1734 if (value
&& !value
->not_found
) {
1735 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1736 "http script var: \"%v\"", value
);
1744 *e
->sp
= ngx_http_variable_null_value
;
1750 ngx_http_script_nop_code(ngx_http_script_engine_t
*e
)
1752 e
->ip
+= sizeof(uintptr_t);