blob: 879c63cbb1aca9f4cbc11ab2b77a04158fac594f [file] [log] [blame]
Igor Sysoev7578ec92003-06-02 15:24:30 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Maxim Konovalovf8d59e32012-01-18 15:07:43 +00004 * Copyright (C) Nginx, Inc.
Igor Sysoevd90282d2004-09-28 08:34:51 +00005 */
6
7
Igor Sysoev7578ec92003-06-02 15:24:30 +00008#include <ngx_config.h>
9#include <ngx_core.h>
10#include <ngx_http.h>
11
12
Igor Sysoev165b3c02009-03-18 14:42:06 +000013static ngx_int_t ngx_http_script_init_arrays(ngx_http_script_compile_t *sc);
14static ngx_int_t ngx_http_script_done(ngx_http_script_compile_t *sc);
15static ngx_int_t ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc,
Igor Sysoev8508c102009-03-22 09:36:51 +000016 ngx_str_t *value, ngx_uint_t last);
Igor Sysoev165b3c02009-03-18 14:42:06 +000017static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc,
18 ngx_str_t *name);
19static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc);
20#if (NGX_PCRE)
21static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc,
Ruslan Ermilov2161d8a2016-03-30 11:52:16 +030022 ngx_uint_t n);
Igor Sysoev165b3c02009-03-18 14:42:06 +000023#endif
Igor Sysoev8508c102009-03-22 09:36:51 +000024static ngx_int_t
Ruslan Ermilov2161d8a2016-03-30 11:52:16 +030025 ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc);
Igor Sysoev8508c102009-03-22 09:36:51 +000026static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e);
27static void ngx_http_script_full_name_code(ngx_http_script_engine_t *e);
Igor Sysoev165b3c02009-03-18 14:42:06 +000028
29
Igor Sysoev899b44e2005-05-12 14:58:06 +000030#define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
31
32static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL;
33
34
Igor Sysoev8508c102009-03-22 09:36:51 +000035void
Igor Sysoev766f3a92009-03-27 14:59:47 +000036ngx_http_script_flush_complex_value(ngx_http_request_t *r,
Igor Sysoev8508c102009-03-22 09:36:51 +000037 ngx_http_complex_value_t *val)
38{
39 ngx_uint_t *index;
40
41 index = val->flushes;
42
43 if (index) {
44 while (*index != (ngx_uint_t) -1) {
45
46 if (r->variables[*index].no_cacheable) {
47 r->variables[*index].valid = 0;
48 r->variables[*index].not_found = 0;
49 }
50
51 index++;
52 }
53 }
54}
55
56
57ngx_int_t
58ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val,
59 ngx_str_t *value)
60{
61 size_t len;
62 ngx_http_script_code_pt code;
63 ngx_http_script_len_code_pt lcode;
64 ngx_http_script_engine_t e;
65
66 if (val->lengths == NULL) {
67 *value = val->value;
68 return NGX_OK;
69 }
70
Igor Sysoev766f3a92009-03-27 14:59:47 +000071 ngx_http_script_flush_complex_value(r, val);
Igor Sysoev8508c102009-03-22 09:36:51 +000072
73 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
74
75 e.ip = val->lengths;
76 e.request = r;
77 e.flushed = 1;
78
79 len = 0;
80
81 while (*(uintptr_t *) e.ip) {
82 lcode = *(ngx_http_script_len_code_pt *) e.ip;
83 len += lcode(&e);
84 }
85
86 value->len = len;
87 value->data = ngx_pnalloc(r->pool, len);
88 if (value->data == NULL) {
89 return NGX_ERROR;
90 }
91
92 e.ip = val->values;
93 e.pos = value->data;
94 e.buf = *value;
95
96 while (*(uintptr_t *) e.ip) {
97 code = *(ngx_http_script_code_pt *) e.ip;
98 code((ngx_http_script_engine_t *) &e);
99 }
100
101 *value = e.buf;
102
103 return NGX_OK;
104}
105
106
107ngx_int_t
108ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
109{
110 ngx_str_t *v;
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;
114
115 v = ccv->value;
116
Igor Sysoev8508c102009-03-22 09:36:51 +0000117 nv = 0;
118 nc = 0;
119
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') {
123 nc++;
124
125 } else {
126 nv++;
127 }
128 }
129 }
130
Ruslan Ermilov73fb7e82012-12-06 23:03:53 +0000131 if ((v->len == 0 || v->data[0] != '$')
132 && (ccv->conf_prefix || ccv->root_prefix))
133 {
Maxim Dounine3cab762013-08-20 21:11:19 +0400134 if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
Igor Sysoev8508c102009-03-22 09:36:51 +0000135 return NGX_ERROR;
136 }
137
138 ccv->conf_prefix = 0;
139 ccv->root_prefix = 0;
140 }
141
Igor Sysoev22d381e2009-03-27 06:34:31 +0000142 ccv->complex_value->value = *v;
143 ccv->complex_value->flushes = NULL;
144 ccv->complex_value->lengths = NULL;
145 ccv->complex_value->values = NULL;
146
Igor Sysoev8508c102009-03-22 09:36:51 +0000147 if (nv == 0 && nc == 0) {
148 return NGX_OK;
149 }
150
151 n = nv + 1;
152
153 if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
154 != NGX_OK)
155 {
156 return NGX_ERROR;
157 }
158
159 n = nv * (2 * sizeof(ngx_http_script_copy_code_t)
160 + sizeof(ngx_http_script_var_code_t))
161 + sizeof(uintptr_t);
162
163 if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
164 return NGX_ERROR;
165 }
166
167 n = (nv * (2 * sizeof(ngx_http_script_copy_code_t)
168 + sizeof(ngx_http_script_var_code_t))
169 + sizeof(uintptr_t)
170 + v->len
171 + sizeof(uintptr_t) - 1)
172 & ~(sizeof(uintptr_t) - 1);
173
174 if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
175 return NGX_ERROR;
176 }
177
178 pf = &flushes;
179 pl = &lengths;
180 pv = &values;
181
182 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
183
184 sc.cf = ccv->cf;
185 sc.source = v;
186 sc.flushes = &pf;
187 sc.lengths = &pl;
188 sc.values = &pv;
189 sc.complete_lengths = 1;
190 sc.complete_values = 1;
191 sc.zero = ccv->zero;
192 sc.conf_prefix = ccv->conf_prefix;
193 sc.root_prefix = ccv->root_prefix;
194
195 if (ngx_http_script_compile(&sc) != NGX_OK) {
196 return NGX_ERROR;
197 }
198
199 if (flushes.nelts) {
200 ccv->complex_value->flushes = flushes.elts;
201 ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
202 }
203
204 ccv->complex_value->lengths = lengths.elts;
205 ccv->complex_value->values = values.elts;
206
207 return NGX_OK;
208}
209
210
Igor Sysoev94e9aaa2010-09-02 14:37:16 +0000211char *
Igor Sysoev9a626482010-09-13 12:44:43 +0000212ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
Igor Sysoev94e9aaa2010-09-02 14:37:16 +0000213{
214 char *p = conf;
215
216 ngx_str_t *value;
217 ngx_http_complex_value_t **cv;
218 ngx_http_compile_complex_value_t ccv;
219
220 cv = (ngx_http_complex_value_t **) (p + cmd->offset);
221
222 if (*cv != NULL) {
223 return "duplicate";
224 }
225
226 *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
227 if (*cv == NULL) {
228 return NGX_CONF_ERROR;
229 }
230
231 value = cf->args->elts;
232
233 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
234
235 ccv.cf = cf;
236 ccv.value = &value[1];
237 ccv.complex_value = *cv;
238
239 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
240 return NGX_CONF_ERROR;
241 }
242
243 return NGX_CONF_OK;
244}
245
246
Igor Sysoev7fc29052010-07-14 11:13:59 +0000247ngx_int_t
248ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates)
249{
250 ngx_str_t val;
251 ngx_uint_t i;
252 ngx_http_complex_value_t *cv;
253
254 if (predicates == NULL) {
255 return NGX_OK;
256 }
257
258 cv = predicates->elts;
259
260 for (i = 0; i < predicates->nelts; i++) {
261 if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
262 return NGX_ERROR;
263 }
264
Igor Sysoev14fe2dd2011-04-15 12:24:18 +0000265 if (val.len && (val.len != 1 || val.data[0] != '0')) {
Igor Sysoev7fc29052010-07-14 11:13:59 +0000266 return NGX_DECLINED;
267 }
268 }
269
270 return NGX_OK;
271}
272
273
274char *
275ngx_http_set_predicate_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
276{
277 char *p = conf;
278
279 ngx_str_t *value;
280 ngx_uint_t i;
281 ngx_array_t **a;
282 ngx_http_complex_value_t *cv;
283 ngx_http_compile_complex_value_t ccv;
284
285 a = (ngx_array_t **) (p + cmd->offset);
286
287 if (*a == NGX_CONF_UNSET_PTR) {
288 *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t));
289 if (*a == NULL) {
290 return NGX_CONF_ERROR;
291 }
292 }
293
294 value = cf->args->elts;
295
296 for (i = 1; i < cf->args->nelts; i++) {
297 cv = ngx_array_push(*a);
298 if (cv == NULL) {
299 return NGX_CONF_ERROR;
300 }
301
302 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
303
304 ccv.cf = cf;
305 ccv.value = &value[i];
306 ccv.complex_value = cv;
307
308 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
309 return NGX_CONF_ERROR;
310 }
311 }
312
313 return NGX_CONF_OK;
314}
315
316
Igor Sysoev899b44e2005-05-12 14:58:06 +0000317ngx_uint_t
318ngx_http_script_variables_count(ngx_str_t *value)
Igor Sysoev7578ec92003-06-02 15:24:30 +0000319{
Igor Sysoev899b44e2005-05-12 14:58:06 +0000320 ngx_uint_t i, n;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000321
Igor Sysoev899b44e2005-05-12 14:58:06 +0000322 for (n = 0, i = 0; i < value->len; i++) {
323 if (value->data[i] == '$') {
324 n++;
325 }
Igor Sysoev02f742b2005-04-08 15:18:55 +0000326 }
Igor Sysoev02025fd2005-01-18 13:03:58 +0000327
Igor Sysoev899b44e2005-05-12 14:58:06 +0000328 return n;
329}
330
331
332ngx_int_t
333ngx_http_script_compile(ngx_http_script_compile_t *sc)
334{
Igor Sysoev165b3c02009-03-18 14:42:06 +0000335 u_char ch;
336 ngx_str_t name;
337 ngx_uint_t i, bracket;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000338
Igor Sysoev165b3c02009-03-18 14:42:06 +0000339 if (ngx_http_script_init_arrays(sc) != NGX_OK) {
340 return NGX_ERROR;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000341 }
342
Igor Sysoev899b44e2005-05-12 14:58:06 +0000343 for (i = 0; i < sc->source->len; /* void */ ) {
344
345 name.len = 0;
346
347 if (sc->source->data[i] == '$') {
348
349 if (++i == sc->source->len) {
350 goto invalid_variable;
351 }
352
Igor Sysoev1d05de42009-03-06 12:15:07 +0000353#if (NGX_PCRE)
Igor Sysoev165b3c02009-03-18 14:42:06 +0000354 {
355 ngx_uint_t n;
Igor Sysoev1d05de42009-03-06 12:15:07 +0000356
Igor Sysoev899b44e2005-05-12 14:58:06 +0000357 if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
358
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000359 n = sc->source->data[i] - '0';
360
361 if (sc->captures_mask & (1 << n)) {
362 sc->dup_capture = 1;
363 }
364
365 sc->captures_mask |= 1 << n;
366
Igor Sysoev165b3c02009-03-18 14:42:06 +0000367 if (ngx_http_script_add_capture_code(sc, n) != NGX_OK) {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000368 return NGX_ERROR;
369 }
370
Igor Sysoev899b44e2005-05-12 14:58:06 +0000371 i++;
372
373 continue;
374 }
Igor Sysoev165b3c02009-03-18 14:42:06 +0000375 }
Igor Sysoev1d05de42009-03-06 12:15:07 +0000376#endif
377
Igor Sysoev899b44e2005-05-12 14:58:06 +0000378 if (sc->source->data[i] == '{') {
379 bracket = 1;
380
381 if (++i == sc->source->len) {
382 goto invalid_variable;
383 }
384
385 name.data = &sc->source->data[i];
386
387 } else {
388 bracket = 0;
389 name.data = &sc->source->data[i];
390 }
391
392 for ( /* void */ ; i < sc->source->len; i++, name.len++) {
393 ch = sc->source->data[i];
394
395 if (ch == '}' && bracket) {
396 i++;
397 bracket = 0;
398 break;
399 }
400
401 if ((ch >= 'A' && ch <= 'Z')
402 || (ch >= 'a' && ch <= 'z')
403 || (ch >= '0' && ch <= '9')
404 || ch == '_')
405 {
406 continue;
407 }
408
409 break;
410 }
411
412 if (bracket) {
413 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
414 "the closing bracket in \"%V\" "
415 "variable is missing", &name);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000416 return NGX_ERROR;
417 }
418
Igor Sysoev899b44e2005-05-12 14:58:06 +0000419 if (name.len == 0) {
420 goto invalid_variable;
421 }
Igor Sysoev02f742b2005-04-08 15:18:55 +0000422
Igor Sysoev899b44e2005-05-12 14:58:06 +0000423 sc->variables++;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000424
Igor Sysoev165b3c02009-03-18 14:42:06 +0000425 if (ngx_http_script_add_var_code(sc, &name) != NGX_OK) {
Igor Sysoev02f742b2005-04-08 15:18:55 +0000426 return NGX_ERROR;
427 }
428
Igor Sysoev02f742b2005-04-08 15:18:55 +0000429 continue;
430 }
431
Igor Sysoev899b44e2005-05-12 14:58:06 +0000432 if (sc->source->data[i] == '?' && sc->compile_args) {
433 sc->args = 1;
434 sc->compile_args = 0;
435
Igor Sysoev165b3c02009-03-18 14:42:06 +0000436 if (ngx_http_script_add_args_code(sc) != NGX_OK) {
Igor Sysoev04610ea2008-02-12 18:05:32 +0000437 return NGX_ERROR;
438 }
439
Igor Sysoev899b44e2005-05-12 14:58:06 +0000440 i++;
441
442 continue;
443 }
444
445 name.data = &sc->source->data[i];
446
Igor Sysoev97860162009-02-10 16:03:42 +0000447 while (i < sc->source->len) {
448
449 if (sc->source->data[i] == '$') {
450 break;
451 }
452
453 if (sc->source->data[i] == '?') {
454
455 sc->args = 1;
456
457 if (sc->compile_args) {
458 break;
459 }
460 }
461
Igor Sysoev899b44e2005-05-12 14:58:06 +0000462 i++;
463 name.len++;
464 }
465
466 sc->size += name.len;
467
Igor Sysoev8508c102009-03-22 09:36:51 +0000468 if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len))
469 != NGX_OK)
470 {
Igor Sysoev02f742b2005-04-08 15:18:55 +0000471 return NGX_ERROR;
472 }
473 }
474
Igor Sysoev165b3c02009-03-18 14:42:06 +0000475 return ngx_http_script_done(sc);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000476
477invalid_variable:
478
479 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");
480
481 return NGX_ERROR;
Igor Sysoev7578ec92003-06-02 15:24:30 +0000482}
483
484
Igor Sysoev8fea8852006-03-15 09:53:04 +0000485u_char *
486ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,
487 void *code_lengths, size_t len, void *code_values)
488{
Igor Sysoev2c8f0572007-03-30 19:00:34 +0000489 ngx_uint_t i;
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;
494
495 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
496
497 for (i = 0; i < cmcf->variables.nelts; i++) {
Igor Sysoev2d3f3f62007-10-14 18:56:15 +0000498 if (r->variables[i].no_cacheable) {
Igor Sysoev2c8f0572007-03-30 19:00:34 +0000499 r->variables[i].valid = 0;
500 r->variables[i].not_found = 0;
501 }
502 }
Igor Sysoev8fea8852006-03-15 09:53:04 +0000503
504 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
505
506 e.ip = code_lengths;
507 e.request = r;
508 e.flushed = 1;
509
510 while (*(uintptr_t *) e.ip) {
511 lcode = *(ngx_http_script_len_code_pt *) e.ip;
512 len += lcode(&e);
513 }
514
515
516 value->len = len;
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +0000517 value->data = ngx_pnalloc(r->pool, len);
Igor Sysoev8fea8852006-03-15 09:53:04 +0000518 if (value->data == NULL) {
519 return NULL;
520 }
521
522 e.ip = code_values;
523 e.pos = value->data;
524
525 while (*(uintptr_t *) e.ip) {
526 code = *(ngx_http_script_code_pt *) e.ip;
527 code((ngx_http_script_engine_t *) &e);
528 }
529
530 return e.pos;
531}
532
533
Igor Sysoev09c684b2005-11-09 17:25:55 +0000534void
Igor Sysoev2d3f3f62007-10-14 18:56:15 +0000535ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r,
Igor Sysoev09c684b2005-11-09 17:25:55 +0000536 ngx_array_t *indices)
537{
538 ngx_uint_t n, *index;
539
540 if (indices) {
541 index = indices->elts;
542 for (n = 0; n < indices->nelts; n++) {
Igor Sysoev2d3f3f62007-10-14 18:56:15 +0000543 if (r->variables[index[n]].no_cacheable) {
Igor Sysoev09c684b2005-11-09 17:25:55 +0000544 r->variables[index[n]].valid = 0;
545 r->variables[index[n]].not_found = 0;
546 }
547 }
548 }
549}
550
551
Igor Sysoev165b3c02009-03-18 14:42:06 +0000552static ngx_int_t
553ngx_http_script_init_arrays(ngx_http_script_compile_t *sc)
554{
555 ngx_uint_t n;
556
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) {
561 return NGX_ERROR;
562 }
563 }
564
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))
568 + sizeof(uintptr_t);
569
570 *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
571 if (*sc->lengths == NULL) {
572 return NGX_ERROR;
573 }
574 }
575
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))
579 + sizeof(uintptr_t)
580 + sc->source->len
581 + sizeof(uintptr_t) - 1)
582 & ~(sizeof(uintptr_t) - 1);
583
584 *sc->values = ngx_array_create(sc->cf->pool, n, 1);
585 if (*sc->values == NULL) {
586 return NGX_ERROR;
587 }
588 }
589
590 sc->variables = 0;
591
592 return NGX_OK;
593}
594
595
596static ngx_int_t
597ngx_http_script_done(ngx_http_script_compile_t *sc)
598{
Igor Sysoev8508c102009-03-22 09:36:51 +0000599 ngx_str_t zero;
Igor Sysoev165b3c02009-03-18 14:42:06 +0000600 uintptr_t *code;
601
Igor Sysoev8508c102009-03-22 09:36:51 +0000602 if (sc->zero) {
603
604 zero.len = 1;
605 zero.data = (u_char *) "\0";
606
607 if (ngx_http_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
608 return NGX_ERROR;
609 }
610 }
611
612 if (sc->conf_prefix || sc->root_prefix) {
613 if (ngx_http_script_add_full_name_code(sc) != NGX_OK) {
614 return NGX_ERROR;
615 }
616 }
617
Igor Sysoev165b3c02009-03-18 14:42:06 +0000618 if (sc->complete_lengths) {
619 code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
620 if (code == NULL) {
621 return NGX_ERROR;
622 }
623
624 *code = (uintptr_t) NULL;
625 }
626
627 if (sc->complete_values) {
628 code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
629 &sc->main);
630 if (code == NULL) {
631 return NGX_ERROR;
632 }
633
634 *code = (uintptr_t) NULL;
635 }
636
637 return NGX_OK;
638}
639
640
Igor Sysoev899b44e2005-05-12 14:58:06 +0000641void *
Igor Sysoev02f742b2005-04-08 15:18:55 +0000642ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
Igor Sysoev7578ec92003-06-02 15:24:30 +0000643{
Igor Sysoev02f742b2005-04-08 15:18:55 +0000644 if (*codes == NULL) {
645 *codes = ngx_array_create(pool, 256, 1);
646 if (*codes == NULL) {
647 return NULL;
648 }
649 }
Igor Sysoev7578ec92003-06-02 15:24:30 +0000650
Igor Sysoev02f742b2005-04-08 15:18:55 +0000651 return ngx_array_push_n(*codes, size);
652}
Igor Sysoev7578ec92003-06-02 15:24:30 +0000653
Igor Sysoev899b44e2005-05-12 14:58:06 +0000654
655void *
656ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code)
657{
658 u_char *elts, **p;
659 void *new;
660
661 elts = codes->elts;
662
663 new = ngx_array_push_n(codes, size);
664 if (new == NULL) {
Igor Sysoev05822df2009-06-02 16:08:38 +0000665 return NULL;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000666 }
667
668 if (code) {
669 if (elts != codes->elts) {
670 p = code;
671 *p += (u_char *) codes->elts - elts;
672 }
673 }
674
675 return new;
676}
Igor Sysoev02025fd2005-01-18 13:03:58 +0000677
Igor Sysoev02f742b2005-04-08 15:18:55 +0000678
Igor Sysoev165b3c02009-03-18 14:42:06 +0000679static ngx_int_t
Igor Sysoev8508c102009-03-22 09:36:51 +0000680ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value,
681 ngx_uint_t last)
Igor Sysoev165b3c02009-03-18 14:42:06 +0000682{
Igor Sysoev8508c102009-03-22 09:36:51 +0000683 u_char *p;
684 size_t size, len, zero;
Igor Sysoev165b3c02009-03-18 14:42:06 +0000685 ngx_http_script_copy_code_t *code;
686
Igor Sysoev8508c102009-03-22 09:36:51 +0000687 zero = (sc->zero && last);
688 len = value->len + zero;
689
Igor Sysoev165b3c02009-03-18 14:42:06 +0000690 code = ngx_http_script_add_code(*sc->lengths,
691 sizeof(ngx_http_script_copy_code_t), NULL);
692 if (code == NULL) {
693 return NGX_ERROR;
694 }
695
696 code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
Igor Sysoev8508c102009-03-22 09:36:51 +0000697 code->len = len;
Igor Sysoev165b3c02009-03-18 14:42:06 +0000698
Igor Sysoev8508c102009-03-22 09:36:51 +0000699 size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
Igor Sysoev165b3c02009-03-18 14:42:06 +0000700 & ~(sizeof(uintptr_t) - 1);
701
702 code = ngx_http_script_add_code(*sc->values, size, &sc->main);
703 if (code == NULL) {
704 return NGX_ERROR;
705 }
706
707 code->code = ngx_http_script_copy_code;
Igor Sysoev8508c102009-03-22 09:36:51 +0000708 code->len = len;
Igor Sysoev165b3c02009-03-18 14:42:06 +0000709
Igor Sysoev8508c102009-03-22 09:36:51 +0000710 p = ngx_cpymem((u_char *) code + sizeof(ngx_http_script_copy_code_t),
711 value->data, value->len);
712
713 if (zero) {
714 *p = '\0';
715 sc->zero = 0;
716 }
Igor Sysoev165b3c02009-03-18 14:42:06 +0000717
718 return NGX_OK;
719}
720
721
Igor Sysoev02f742b2005-04-08 15:18:55 +0000722size_t
Igor Sysoev899b44e2005-05-12 14:58:06 +0000723ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
Igor Sysoev02f742b2005-04-08 15:18:55 +0000724{
725 ngx_http_script_copy_code_t *code;
726
Igor Sysoev899b44e2005-05-12 14:58:06 +0000727 code = (ngx_http_script_copy_code_t *) e->ip;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000728
Igor Sysoev899b44e2005-05-12 14:58:06 +0000729 e->ip += sizeof(ngx_http_script_copy_code_t);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000730
731 return code->len;
Igor Sysoev7578ec92003-06-02 15:24:30 +0000732}
733
734
Igor Sysoev02f742b2005-04-08 15:18:55 +0000735void
Igor Sysoev899b44e2005-05-12 14:58:06 +0000736ngx_http_script_copy_code(ngx_http_script_engine_t *e)
Igor Sysoev7578ec92003-06-02 15:24:30 +0000737{
Igor Sysoev45656b42008-12-10 14:48:04 +0000738 u_char *p;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000739 ngx_http_script_copy_code_t *code;
740
Igor Sysoev899b44e2005-05-12 14:58:06 +0000741 code = (ngx_http_script_copy_code_t *) e->ip;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000742
Igor Sysoev45656b42008-12-10 14:48:04 +0000743 p = e->pos;
744
Igor Sysoev899b44e2005-05-12 14:58:06 +0000745 if (!e->skip) {
Igor Sysoev45656b42008-12-10 14:48:04 +0000746 e->pos = ngx_copy(p, e->ip + sizeof(ngx_http_script_copy_code_t),
Igor Sysoev09c684b2005-11-09 17:25:55 +0000747 code->len);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000748 }
Igor Sysoev02f742b2005-04-08 15:18:55 +0000749
Igor Sysoev899b44e2005-05-12 14:58:06 +0000750 e->ip += sizeof(ngx_http_script_copy_code_t)
751 + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
752
Igor Sysoev45656b42008-12-10 14:48:04 +0000753 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
754 "http script copy: \"%*s\"", e->pos - p, p);
Igor Sysoev7578ec92003-06-02 15:24:30 +0000755}
756
757
Igor Sysoev165b3c02009-03-18 14:42:06 +0000758static ngx_int_t
759ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, ngx_str_t *name)
760{
761 ngx_int_t index, *p;
762 ngx_http_script_var_code_t *code;
763
764 index = ngx_http_get_variable_index(sc->cf, name);
765
766 if (index == NGX_ERROR) {
767 return NGX_ERROR;
768 }
769
770 if (sc->flushes) {
771 p = ngx_array_push(*sc->flushes);
772 if (p == NULL) {
773 return NGX_ERROR;
774 }
775
776 *p = index;
777 }
778
779 code = ngx_http_script_add_code(*sc->lengths,
780 sizeof(ngx_http_script_var_code_t), NULL);
781 if (code == NULL) {
782 return NGX_ERROR;
783 }
784
785 code->code = (ngx_http_script_code_pt) ngx_http_script_copy_var_len_code;
786 code->index = (uintptr_t) index;
787
788 code = ngx_http_script_add_code(*sc->values,
789 sizeof(ngx_http_script_var_code_t),
790 &sc->main);
791 if (code == NULL) {
792 return NGX_ERROR;
793 }
794
795 code->code = ngx_http_script_copy_var_code;
796 code->index = (uintptr_t) index;
797
798 return NGX_OK;
799}
800
801
Igor Sysoev02f742b2005-04-08 15:18:55 +0000802size_t
Igor Sysoev899b44e2005-05-12 14:58:06 +0000803ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
Igor Sysoev7578ec92003-06-02 15:24:30 +0000804{
Igor Sysoev02f742b2005-04-08 15:18:55 +0000805 ngx_http_variable_value_t *value;
806 ngx_http_script_var_code_t *code;
807
Igor Sysoev899b44e2005-05-12 14:58:06 +0000808 code = (ngx_http_script_var_code_t *) e->ip;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000809
Igor Sysoev899b44e2005-05-12 14:58:06 +0000810 e->ip += sizeof(ngx_http_script_var_code_t);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000811
Igor Sysoev09c684b2005-11-09 17:25:55 +0000812 if (e->flushed) {
813 value = ngx_http_get_indexed_variable(e->request, code->index);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000814
Igor Sysoev09c684b2005-11-09 17:25:55 +0000815 } else {
816 value = ngx_http_get_flushed_variable(e->request, code->index);
817 }
818
819 if (value && !value->not_found) {
820 return value->len;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000821 }
822
Igor Sysoevf6e1fe32005-10-04 10:38:53 +0000823 return 0;
Igor Sysoev7578ec92003-06-02 15:24:30 +0000824}
825
826
Igor Sysoev02f742b2005-04-08 15:18:55 +0000827void
Igor Sysoev899b44e2005-05-12 14:58:06 +0000828ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
Igor Sysoev7578ec92003-06-02 15:24:30 +0000829{
Igor Sysoev45656b42008-12-10 14:48:04 +0000830 u_char *p;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000831 ngx_http_variable_value_t *value;
832 ngx_http_script_var_code_t *code;
833
Igor Sysoev899b44e2005-05-12 14:58:06 +0000834 code = (ngx_http_script_var_code_t *) e->ip;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000835
Igor Sysoev899b44e2005-05-12 14:58:06 +0000836 e->ip += sizeof(ngx_http_script_var_code_t);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000837
Igor Sysoev899b44e2005-05-12 14:58:06 +0000838 if (!e->skip) {
Igor Sysoev02f742b2005-04-08 15:18:55 +0000839
Igor Sysoev09c684b2005-11-09 17:25:55 +0000840 if (e->flushed) {
841 value = ngx_http_get_indexed_variable(e->request, code->index);
842
843 } else {
844 value = ngx_http_get_flushed_variable(e->request, code->index);
845 }
846
847 if (value && !value->not_found) {
Igor Sysoev45656b42008-12-10 14:48:04 +0000848 p = e->pos;
849 e->pos = ngx_copy(p, value->data, value->len);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000850
Igor Sysoev45656b42008-12-10 14:48:04 +0000851 ngx_log_debug2(NGX_LOG_DEBUG_HTTP,
Igor Sysoev58364232006-11-14 12:45:03 +0000852 e->request->connection->log, 0,
Igor Sysoev45656b42008-12-10 14:48:04 +0000853 "http script var: \"%*s\"", e->pos - p, p);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000854 }
855 }
856}
857
858
Igor Sysoev165b3c02009-03-18 14:42:06 +0000859static ngx_int_t
860ngx_http_script_add_args_code(ngx_http_script_compile_t *sc)
861{
862 uintptr_t *code;
863
864 code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
865 if (code == NULL) {
866 return NGX_ERROR;
867 }
868
869 *code = (uintptr_t) ngx_http_script_mark_args_code;
870
871 code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t), &sc->main);
872 if (code == NULL) {
873 return NGX_ERROR;
874 }
875
876 *code = (uintptr_t) ngx_http_script_start_args_code;
877
878 return NGX_OK;
879}
880
881
Igor Sysoev899b44e2005-05-12 14:58:06 +0000882size_t
Igor Sysoev04610ea2008-02-12 18:05:32 +0000883ngx_http_script_mark_args_code(ngx_http_script_engine_t *e)
884{
885 e->is_args = 1;
886 e->ip += sizeof(uintptr_t);
887
888 return 1;
889}
890
891
Igor Sysoev899b44e2005-05-12 14:58:06 +0000892void
893ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
894{
895 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
896 "http script args");
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000897
Igor Sysoev4084b122008-09-01 14:43:38 +0000898 e->is_args = 1;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000899 e->args = e->pos;
900 e->ip += sizeof(uintptr_t);
901}
902
903
Igor Sysoev4959ec42005-05-23 12:07:45 +0000904#if (NGX_PCRE)
905
Igor Sysoev899b44e2005-05-12 14:58:06 +0000906void
907ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
908{
909 size_t len;
910 ngx_int_t rc;
911 ngx_uint_t n;
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;
916
917 code = (ngx_http_script_regex_code_t *) e->ip;
918
919 r = e->request;
920
921 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
922 "http script regex: \"%V\"", &code->name);
923
924 if (code->uri) {
Igor Sysoeve31e90b2005-05-19 13:25:22 +0000925 e->line = r->uri;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000926 } else {
927 e->sp--;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000928 e->line.len = e->sp->len;
929 e->line.data = e->sp->data;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000930 }
931
Igor Sysoevc05f20e2009-11-16 12:19:02 +0000932 rc = ngx_http_regex_exec(r, code->regex, &e->line);
Igor Sysoev1d05de42009-03-06 12:15:07 +0000933
Igor Sysoevc05f20e2009-11-16 12:19:02 +0000934 if (rc == NGX_DECLINED) {
Igor Sysoev0e179532008-12-11 06:38:14 +0000935 if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000936 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
Igor Sysoeve31e90b2005-05-19 13:25:22 +0000937 "\"%V\" does not match \"%V\"",
938 &code->name, &e->line);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000939 }
940
Igor Sysoev1d05de42009-03-06 12:15:07 +0000941 r->ncaptures = 0;
Igor Sysoeve31e90b2005-05-19 13:25:22 +0000942
Igor Sysoev899b44e2005-05-12 14:58:06 +0000943 if (code->test) {
Igor Sysoev94e32ce2006-04-07 14:08:04 +0000944 if (code->negative_test) {
945 e->sp->len = 1;
946 e->sp->data = (u_char *) "1";
947
948 } else {
949 e->sp->len = 0;
950 e->sp->data = (u_char *) "";
951 }
952
Igor Sysoev899b44e2005-05-12 14:58:06 +0000953 e->sp++;
954
955 e->ip += sizeof(ngx_http_script_regex_code_t);
956 return;
957 }
958
959 e->ip += code->next;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000960 return;
961 }
962
Igor Sysoevc05f20e2009-11-16 12:19:02 +0000963 if (rc == NGX_ERROR) {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000964 e->ip = ngx_http_script_exit;
965 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
966 return;
967 }
968
Igor Sysoev0e179532008-12-11 06:38:14 +0000969 if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000970 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
Igor Sysoeve31e90b2005-05-19 13:25:22 +0000971 "\"%V\" matches \"%V\"", &code->name, &e->line);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000972 }
973
974 if (code->test) {
Igor Sysoev94e32ce2006-04-07 14:08:04 +0000975 if (code->negative_test) {
976 e->sp->len = 0;
977 e->sp->data = (u_char *) "";
978
979 } else {
980 e->sp->len = 1;
981 e->sp->data = (u_char *) "1";
982 }
983
Igor Sysoev899b44e2005-05-12 14:58:06 +0000984 e->sp++;
985
986 e->ip += sizeof(ngx_http_script_regex_code_t);
987 return;
988 }
989
990 if (code->status) {
991 e->status = code->status;
992
993 if (!code->redirect) {
994 e->ip = ngx_http_script_exit;
995 return;
996 }
997 }
998
999 if (code->uri) {
1000 r->internal = 1;
1001 r->valid_unparsed_uri = 0;
1002
1003 if (code->break_cycle) {
1004 r->valid_location = 0;
Igor Sysoev5192b362005-07-08 14:34:20 +00001005 r->uri_changed = 0;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001006
1007 } else {
1008 r->uri_changed = 1;
1009 }
1010 }
1011
1012 if (code->lengths == NULL) {
1013 e->buf.len = code->size;
1014
1015 if (code->uri) {
Igor Sysoevd86a0bf2009-11-16 19:10:45 +00001016 if (r->ncaptures && (r->quoted_uri || r->plus_in_uri)) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001017 e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
1018 NGX_ESCAPE_ARGS);
1019 }
1020 }
1021
Igor Sysoevd86a0bf2009-11-16 19:10:45 +00001022 for (n = 2; n < r->ncaptures; n += 2) {
1023 e->buf.len += r->captures[n + 1] - r->captures[n];
Igor Sysoev899b44e2005-05-12 14:58:06 +00001024 }
1025
1026 } else {
1027 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
1028
1029 le.ip = code->lengths->elts;
Igor Sysoev3f8dc592006-08-28 16:57:48 +00001030 le.line = e->line;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001031 le.request = r;
Igor Sysoev3f8dc592006-08-28 16:57:48 +00001032 le.quote = code->redirect;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001033
Igor Sysoev04610ea2008-02-12 18:05:32 +00001034 len = 0;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001035
1036 while (*(uintptr_t *) le.ip) {
1037 lcode = *(ngx_http_script_len_code_pt *) le.ip;
1038 len += lcode(&le);
1039 }
1040
1041 e->buf.len = len;
1042 }
1043
Igor Sysoeve31e90b2005-05-19 13:25:22 +00001044 if (code->add_args && r->args.len) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001045 e->buf.len += r->args.len + 1;
1046 }
1047
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001048 e->buf.data = ngx_pnalloc(r->pool, e->buf.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001049 if (e->buf.data == NULL) {
1050 e->ip = ngx_http_script_exit;
1051 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1052 return;
1053 }
1054
1055 e->quote = code->redirect;
1056
1057 e->pos = e->buf.data;
1058
1059 e->ip += sizeof(ngx_http_script_regex_code_t);
1060}
1061
1062
1063void
1064ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
1065{
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001066 u_char *dst, *src;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001067 ngx_http_request_t *r;
1068 ngx_http_script_regex_end_code_t *code;
1069
1070 code = (ngx_http_script_regex_end_code_t *) e->ip;
1071
1072 r = e->request;
1073
1074 e->quote = 0;
1075
1076 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1077 "http script regex end");
1078
1079 if (code->redirect) {
1080
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001081 dst = e->buf.data;
1082 src = e->buf.data;
1083
Igor Sysoevf0a51cf2007-10-22 10:19:17 +00001084 ngx_unescape_uri(&dst, &src, e->pos - e->buf.data,
1085 NGX_UNESCAPE_REDIRECT);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001086
1087 if (src < e->pos) {
Igor Sysoevd63104e2011-04-12 08:02:46 +00001088 dst = ngx_movemem(dst, src, e->pos - src);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001089 }
1090
1091 e->pos = dst;
1092
1093 if (code->add_args && r->args.len) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001094 *e->pos++ = (u_char) (code->args ? '&' : '?');
Igor Sysoev09c684b2005-11-09 17:25:55 +00001095 e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001096 }
1097
1098 e->buf.len = e->pos - e->buf.data;
1099
Igor Sysoev0e179532008-12-11 06:38:14 +00001100 if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001101 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
1102 "rewritten redirect: \"%V\"", &e->buf);
1103 }
1104
Maxim Dounin72df0f42011-10-12 13:28:03 +00001105 ngx_http_clear_location(r);
1106
Igor Sysoev899b44e2005-05-12 14:58:06 +00001107 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;
1111 return;
1112 }
1113
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001114 r->headers_out.location->hash = 1;
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00001115 ngx_str_set(&r->headers_out.location->key, "Location");
Igor Sysoev899b44e2005-05-12 14:58:06 +00001116 r->headers_out.location->value = e->buf;
1117
1118 e->ip += sizeof(ngx_http_script_regex_end_code_t);
1119 return;
1120 }
1121
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001122 if (e->args) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001123 e->buf.len = e->args - e->buf.data;
1124
1125 if (code->add_args && r->args.len) {
1126 *e->pos++ = '&';
Igor Sysoev09c684b2005-11-09 17:25:55 +00001127 e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001128 }
1129
1130 r->args.len = e->pos - e->args;
1131 r->args.data = e->args;
1132
1133 e->args = NULL;
1134
1135 } else {
1136 e->buf.len = e->pos - e->buf.data;
Igor Sysoev08e63d42006-08-14 15:09:38 +00001137
1138 if (!code->add_args) {
1139 r->args.len = 0;
1140 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001141 }
1142
Igor Sysoev0e179532008-12-11 06:38:14 +00001143 if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001144 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
1145 "rewritten data: \"%V\", args: \"%V\"",
1146 &e->buf, &r->args);
1147 }
1148
1149 if (code->uri) {
1150 r->uri = e->buf;
1151
Igor Sysoevb85fd592005-08-23 15:36:54 +00001152 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;
1157 return;
1158 }
1159
Igor Sysoevc28d6322009-07-14 08:38:28 +00001160 ngx_http_set_exten(r);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001161 }
1162
1163 e->ip += sizeof(ngx_http_script_regex_end_code_t);
1164}
1165
Igor Sysoev1d05de42009-03-06 12:15:07 +00001166
Igor Sysoev165b3c02009-03-18 14:42:06 +00001167static ngx_int_t
1168ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, ngx_uint_t n)
1169{
1170 ngx_http_script_copy_capture_code_t *code;
1171
1172 code = ngx_http_script_add_code(*sc->lengths,
1173 sizeof(ngx_http_script_copy_capture_code_t),
1174 NULL);
1175 if (code == NULL) {
1176 return NGX_ERROR;
1177 }
1178
1179 code->code = (ngx_http_script_code_pt)
1180 ngx_http_script_copy_capture_len_code;
1181 code->n = 2 * n;
1182
1183
1184 code = ngx_http_script_add_code(*sc->values,
1185 sizeof(ngx_http_script_copy_capture_code_t),
1186 &sc->main);
1187 if (code == NULL) {
1188 return NGX_ERROR;
1189 }
1190
1191 code->code = ngx_http_script_copy_capture_code;
1192 code->n = 2 * n;
1193
1194 if (sc->ncaptures < n) {
1195 sc->ncaptures = n;
1196 }
1197
1198 return NGX_OK;
1199}
1200
1201
Igor Sysoev1d05de42009-03-06 12:15:07 +00001202size_t
1203ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
1204{
1205 int *cap;
1206 u_char *p;
1207 ngx_uint_t n;
1208 ngx_http_request_t *r;
1209 ngx_http_script_copy_capture_code_t *code;
1210
1211 r = e->request;
1212
1213 code = (ngx_http_script_copy_capture_code_t *) e->ip;
1214
1215 e->ip += sizeof(ngx_http_script_copy_capture_code_t);
1216
1217 n = code->n;
1218
1219 if (n < r->ncaptures) {
1220
1221 cap = r->captures;
1222
1223 if ((e->is_args || e->quote)
1224 && (e->request->quoted_uri || e->request->plus_in_uri))
1225 {
1226 p = r->captures_data;
1227
1228 return cap[n + 1] - cap[n]
1229 + 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n],
1230 NGX_ESCAPE_ARGS);
1231 } else {
1232 return cap[n + 1] - cap[n];
1233 }
1234 }
1235
1236 return 0;
1237}
1238
1239
1240void
1241ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
1242{
1243 int *cap;
1244 u_char *p, *pos;
1245 ngx_uint_t n;
1246 ngx_http_request_t *r;
1247 ngx_http_script_copy_capture_code_t *code;
1248
1249 r = e->request;
1250
1251 code = (ngx_http_script_copy_capture_code_t *) e->ip;
1252
1253 e->ip += sizeof(ngx_http_script_copy_capture_code_t);
1254
1255 n = code->n;
1256
1257 pos = e->pos;
1258
1259 if (n < r->ncaptures) {
1260
1261 cap = r->captures;
1262 p = r->captures_data;
1263
1264 if ((e->is_args || e->quote)
1265 && (e->request->quoted_uri || e->request->plus_in_uri))
1266 {
1267 e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
1268 cap[n + 1] - cap[n],
1269 NGX_ESCAPE_ARGS);
1270 } else {
1271 e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
1272 }
1273 }
1274
1275 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1276 "http script capture: \"%*s\"", e->pos - pos, pos);
1277}
1278
Igor Sysoev4959ec42005-05-23 12:07:45 +00001279#endif
1280
Igor Sysoev899b44e2005-05-12 14:58:06 +00001281
Igor Sysoev8508c102009-03-22 09:36:51 +00001282static ngx_int_t
1283ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
1284{
1285 ngx_http_script_full_name_code_t *code;
1286
1287 code = ngx_http_script_add_code(*sc->lengths,
1288 sizeof(ngx_http_script_full_name_code_t),
1289 NULL);
1290 if (code == NULL) {
1291 return NGX_ERROR;
1292 }
1293
1294 code->code = (ngx_http_script_code_pt) ngx_http_script_full_name_len_code;
Igor Sysoev5ef370d2009-04-27 11:32:33 +00001295 code->conf_prefix = sc->conf_prefix;
Igor Sysoev8508c102009-03-22 09:36:51 +00001296
1297 code = ngx_http_script_add_code(*sc->values,
1298 sizeof(ngx_http_script_full_name_code_t),
1299 &sc->main);
1300 if (code == NULL) {
1301 return NGX_ERROR;
1302 }
1303
1304 code->code = ngx_http_script_full_name_code;
Igor Sysoev5ef370d2009-04-27 11:32:33 +00001305 code->conf_prefix = sc->conf_prefix;
Igor Sysoev8508c102009-03-22 09:36:51 +00001306
1307 return NGX_OK;
1308}
1309
1310
1311static size_t
1312ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e)
1313{
1314 ngx_http_script_full_name_code_t *code;
1315
1316 code = (ngx_http_script_full_name_code_t *) e->ip;
1317
1318 e->ip += sizeof(ngx_http_script_full_name_code_t);
1319
Igor Sysoev5ef370d2009-04-27 11:32:33 +00001320 return code->conf_prefix ? ngx_cycle->conf_prefix.len:
1321 ngx_cycle->prefix.len;
Igor Sysoev8508c102009-03-22 09:36:51 +00001322}
1323
1324
1325static void
1326ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
1327{
1328 ngx_http_script_full_name_code_t *code;
1329
Maxim Dounin92f01262013-08-20 21:33:43 +04001330 ngx_str_t value, *prefix;
Igor Sysoev8508c102009-03-22 09:36:51 +00001331
1332 code = (ngx_http_script_full_name_code_t *) e->ip;
1333
1334 value.data = e->buf.data;
1335 value.len = e->pos - e->buf.data;
1336
Maxim Dounin92f01262013-08-20 21:33:43 +04001337 prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix:
1338 (ngx_str_t *) &ngx_cycle->prefix;
1339
1340 if (ngx_get_full_name(e->request->pool, prefix, &value) != NGX_OK) {
Igor Sysoev8508c102009-03-22 09:36:51 +00001341 e->ip = ngx_http_script_exit;
1342 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1343 return;
1344 }
1345
1346 e->buf = value;
1347
1348 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1349 "http script fullname: \"%V\"", &value);
1350
1351 e->ip += sizeof(ngx_http_script_full_name_code_t);
1352}
1353
1354
Igor Sysoev899b44e2005-05-12 14:58:06 +00001355void
1356ngx_http_script_return_code(ngx_http_script_engine_t *e)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001357{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001358 ngx_http_script_return_code_t *code;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001359
Igor Sysoev899b44e2005-05-12 14:58:06 +00001360 code = (ngx_http_script_return_code_t *) e->ip;
1361
Igor Sysoev4c1b0772010-06-18 15:15:20 +00001362 if (code->status < NGX_HTTP_BAD_REQUEST
1363 || code->text.value.len
1364 || code->text.lengths)
1365 {
1366 e->status = ngx_http_send_response(e->request, code->status, NULL,
1367 &code->text);
1368 } else {
1369 e->status = code->status;
Igor Sysoevafd7ec52006-05-29 17:28:12 +00001370 }
1371
Igor Sysoev4c1b0772010-06-18 15:15:20 +00001372 e->ip = ngx_http_script_exit;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001373}
1374
1375
1376void
Igor Sysoev5192b362005-07-08 14:34:20 +00001377ngx_http_script_break_code(ngx_http_script_engine_t *e)
1378{
1379 e->request->uri_changed = 0;
1380
1381 e->ip = ngx_http_script_exit;
1382}
1383
1384
1385void
Igor Sysoev899b44e2005-05-12 14:58:06 +00001386ngx_http_script_if_code(ngx_http_script_engine_t *e)
1387{
1388 ngx_http_script_if_code_t *code;
1389
1390 code = (ngx_http_script_if_code_t *) e->ip;
1391
1392 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1393 "http script if");
1394
1395 e->sp--;
1396
Maxim Dounin0ca52ad2013-10-18 18:13:35 +04001397 if (e->sp->len && (e->sp->len != 1 || e->sp->data[0] != '0')) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001398 if (code->loc_conf) {
1399 e->request->loc_conf = code->loc_conf;
Igor Sysoevb85fd592005-08-23 15:36:54 +00001400 ngx_http_update_location_config(e->request);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001401 }
1402
1403 e->ip += sizeof(ngx_http_script_if_code_t);
1404 return;
1405 }
1406
1407 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001408 "http script if: false");
Igor Sysoev899b44e2005-05-12 14:58:06 +00001409
1410 e->ip += code->next;
1411}
1412
1413
1414void
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001415ngx_http_script_equal_code(ngx_http_script_engine_t *e)
1416{
1417 ngx_http_variable_value_t *val, *res;
1418
1419 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1420 "http script equal");
1421
1422 e->sp--;
1423 val = e->sp;
1424 res = e->sp - 1;
1425
1426 e->ip += sizeof(uintptr_t);
1427
Igor Sysoev45656b42008-12-10 14:48:04 +00001428 if (val->len == res->len
1429 && ngx_strncmp(val->data, res->data, res->len) == 0)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001430 {
1431 *res = ngx_http_variable_true_value;
1432 return;
1433 }
1434
1435 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1436 "http script equal: no");
1437
1438 *res = ngx_http_variable_null_value;
1439}
1440
1441
1442void
1443ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
1444{
1445 ngx_http_variable_value_t *val, *res;
1446
1447 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1448 "http script not equal");
1449
1450 e->sp--;
1451 val = e->sp;
1452 res = e->sp - 1;
1453
1454 e->ip += sizeof(uintptr_t);
1455
Igor Sysoev45656b42008-12-10 14:48:04 +00001456 if (val->len == res->len
1457 && ngx_strncmp(val->data, res->data, res->len) == 0)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001458 {
1459 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1460 "http script not equal: no");
1461
1462 *res = ngx_http_variable_null_value;
1463 return;
1464 }
1465
1466 *res = ngx_http_variable_true_value;
1467}
1468
1469
1470void
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001471ngx_http_script_file_code(ngx_http_script_engine_t *e)
1472{
Igor Sysoev140c7552007-09-01 12:12:48 +00001473 ngx_str_t path;
1474 ngx_http_request_t *r;
1475 ngx_open_file_info_t of;
1476 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001477 ngx_http_variable_value_t *value;
1478 ngx_http_script_file_code_t *code;
1479
1480 value = e->sp - 1;
1481
1482 code = (ngx_http_script_file_code_t *) e->ip;
1483 e->ip += sizeof(ngx_http_script_file_code_t);
1484
Igor Sysoev140c7552007-09-01 12:12:48 +00001485 path.len = value->len - 1;
1486 path.data = value->data;
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001487
Igor Sysoev140c7552007-09-01 12:12:48 +00001488 r = e->request;
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001489
Igor Sysoev140c7552007-09-01 12:12:48 +00001490 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1491 "http script file op %p \"%V\"", code->op, &path);
1492
1493 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1494
Igor Sysoev5a0eac82008-06-26 14:07:59 +00001495 ngx_memzero(&of, sizeof(ngx_open_file_info_t));
1496
Igor Sysoev32661712009-09-30 13:21:52 +00001497 of.read_ahead = clcf->read_ahead;
Igor Sysoev385af282008-07-30 12:34:04 +00001498 of.directio = clcf->directio;
Igor Sysoev9b9616e2007-12-21 16:19:48 +00001499 of.valid = clcf->open_file_cache_valid;
Igor Sysoevf3b0e492007-12-22 13:19:39 +00001500 of.min_uses = clcf->open_file_cache_min_uses;
Igor Sysoevf1cc4572009-04-27 09:55:53 +00001501 of.test_only = 1;
Igor Sysoev140c7552007-09-01 12:12:48 +00001502 of.errors = clcf->open_file_cache_errors;
Igor Sysoev9afd58f2007-09-03 08:41:42 +00001503 of.events = clcf->open_file_cache_events;
Valentin Bartenev0e05ca02012-02-27 16:51:28 +00001504
1505 if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
1506 e->ip = ngx_http_script_exit;
1507 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1508 return;
1509 }
Igor Sysoev140c7552007-09-01 12:12:48 +00001510
1511 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
Igor Sysoev86b91592007-12-27 20:32:43 +00001512 != NGX_OK)
Igor Sysoev140c7552007-09-01 12:12:48 +00001513 {
Igor Sysoev7f6d71b2009-09-25 09:13:08 +00001514 if (of.err != NGX_ENOENT
1515 && of.err != NGX_ENOTDIR
1516 && of.err != NGX_ENAMETOOLONG)
1517 {
Igor Sysoev140c7552007-09-01 12:12:48 +00001518 ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
Igor Sysoevf1cc4572009-04-27 09:55:53 +00001519 "%s \"%s\" failed", of.failed, value->data);
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001520 }
1521
1522 switch (code->op) {
Igor Sysoevc55a1042006-08-09 19:59:45 +00001523
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001524 case ngx_http_script_file_plain:
Igor Sysoevb71c6902006-08-04 16:04:04 +00001525 case ngx_http_script_file_dir:
1526 case ngx_http_script_file_exists:
1527 case ngx_http_script_file_exec:
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001528 goto false_value;
Igor Sysoevc55a1042006-08-09 19:59:45 +00001529
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001530 case ngx_http_script_file_not_plain:
Igor Sysoevb71c6902006-08-04 16:04:04 +00001531 case ngx_http_script_file_not_dir:
Igor Sysoevc55a1042006-08-09 19:59:45 +00001532 case ngx_http_script_file_not_exists:
Igor Sysoevb71c6902006-08-04 16:04:04 +00001533 case ngx_http_script_file_not_exec:
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001534 goto true_value;
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001535 }
1536
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001537 goto false_value;
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001538 }
1539
1540 switch (code->op) {
1541 case ngx_http_script_file_plain:
Igor Sysoev140c7552007-09-01 12:12:48 +00001542 if (of.is_file) {
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001543 goto true_value;
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001544 }
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001545 goto false_value;
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001546
1547 case ngx_http_script_file_not_plain:
Igor Sysoev140c7552007-09-01 12:12:48 +00001548 if (of.is_file) {
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001549 goto false_value;
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001550 }
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001551 goto true_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001552
1553 case ngx_http_script_file_dir:
Igor Sysoev140c7552007-09-01 12:12:48 +00001554 if (of.is_dir) {
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001555 goto true_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001556 }
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001557 goto false_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001558
1559 case ngx_http_script_file_not_dir:
Igor Sysoev140c7552007-09-01 12:12:48 +00001560 if (of.is_dir) {
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001561 goto false_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001562 }
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001563 goto true_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001564
1565 case ngx_http_script_file_exists:
Igor Sysoev140c7552007-09-01 12:12:48 +00001566 if (of.is_file || of.is_dir || of.is_link) {
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001567 goto true_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001568 }
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001569 goto false_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001570
1571 case ngx_http_script_file_not_exists:
Igor Sysoev140c7552007-09-01 12:12:48 +00001572 if (of.is_file || of.is_dir || of.is_link) {
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001573 goto false_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001574 }
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001575 goto true_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001576
Igor Sysoevb71c6902006-08-04 16:04:04 +00001577 case ngx_http_script_file_exec:
Igor Sysoev140c7552007-09-01 12:12:48 +00001578 if (of.is_exec) {
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001579 goto true_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001580 }
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001581 goto false_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001582
1583 case ngx_http_script_file_not_exec:
Igor Sysoev140c7552007-09-01 12:12:48 +00001584 if (of.is_exec) {
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001585 goto false_value;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001586 }
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001587 goto true_value;
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001588 }
1589
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001590false_value:
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001591
Igor Sysoev140c7552007-09-01 12:12:48 +00001592 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001593 "http script file op false");
1594
1595 *value = ngx_http_variable_null_value;
1596 return;
1597
Igor Sysoeva3e9f7d2008-07-31 07:55:46 +00001598true_value:
Igor Sysoev94e32ce2006-04-07 14:08:04 +00001599
1600 *value = ngx_http_variable_true_value;
1601 return;
1602}
1603
1604
1605void
Igor Sysoeve31e90b2005-05-19 13:25:22 +00001606ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
1607{
1608 size_t len;
1609 ngx_http_script_engine_t le;
1610 ngx_http_script_len_code_pt lcode;
1611 ngx_http_script_complex_value_code_t *code;
1612
1613 code = (ngx_http_script_complex_value_code_t *) e->ip;
1614
1615 e->ip += sizeof(ngx_http_script_complex_value_code_t);
1616
1617 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1618 "http script complex value");
1619
1620 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
1621
1622 le.ip = code->lengths->elts;
Igor Sysoevaf3b7ea2006-05-31 14:11:45 +00001623 le.line = e->line;
Igor Sysoeve31e90b2005-05-19 13:25:22 +00001624 le.request = e->request;
Igor Sysoevaf3b7ea2006-05-31 14:11:45 +00001625 le.quote = e->quote;
Igor Sysoeve31e90b2005-05-19 13:25:22 +00001626
1627 for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
1628 lcode = *(ngx_http_script_len_code_pt *) le.ip;
1629 }
1630
1631 e->buf.len = len;
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001632 e->buf.data = ngx_pnalloc(e->request->pool, len);
Igor Sysoeve31e90b2005-05-19 13:25:22 +00001633 if (e->buf.data == NULL) {
1634 e->ip = ngx_http_script_exit;
1635 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1636 return;
1637 }
1638
1639 e->pos = e->buf.data;
1640
Igor Sysoev09c684b2005-11-09 17:25:55 +00001641 e->sp->len = e->buf.len;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001642 e->sp->data = e->buf.data;
Igor Sysoeve31e90b2005-05-19 13:25:22 +00001643 e->sp++;
1644}
1645
1646
1647void
Igor Sysoev899b44e2005-05-12 14:58:06 +00001648ngx_http_script_value_code(ngx_http_script_engine_t *e)
1649{
1650 ngx_http_script_value_code_t *code;
1651
1652 code = (ngx_http_script_value_code_t *) e->ip;
1653
1654 e->ip += sizeof(ngx_http_script_value_code_t);
1655
Igor Sysoev09c684b2005-11-09 17:25:55 +00001656 e->sp->len = code->text_len;
1657 e->sp->data = (u_char *) code->text_data;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001658
1659 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
Igor Sysoev5ba67392007-10-09 18:44:59 +00001660 "http script value: \"%v\"", e->sp);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001661
Igor Sysoev899b44e2005-05-12 14:58:06 +00001662 e->sp++;
1663}
1664
1665
1666void
1667ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
1668{
1669 ngx_http_request_t *r;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001670 ngx_http_script_var_code_t *code;
1671
Igor Sysoev899b44e2005-05-12 14:58:06 +00001672 code = (ngx_http_script_var_code_t *) e->ip;
1673
1674 e->ip += sizeof(ngx_http_script_var_code_t);
1675
1676 r = e->request;
1677
Igor Sysoev899b44e2005-05-12 14:58:06 +00001678 e->sp--;
1679
Igor Sysoev09c684b2005-11-09 17:25:55 +00001680 r->variables[code->index].len = e->sp->len;
1681 r->variables[code->index].valid = 1;
Igor Sysoev2d3f3f62007-10-14 18:56:15 +00001682 r->variables[code->index].no_cacheable = 0;
Igor Sysoev09c684b2005-11-09 17:25:55 +00001683 r->variables[code->index].not_found = 0;
1684 r->variables[code->index].data = e->sp->data;
Igor Sysoev45656b42008-12-10 14:48:04 +00001685
1686#if (NGX_DEBUG)
1687 {
1688 ngx_http_variable_t *v;
1689 ngx_http_core_main_conf_t *cmcf;
1690
1691 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1692
1693 v = cmcf->variables.elts;
1694
1695 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1696 "http script set $%V", &v[code->index].name);
1697 }
1698#endif
Igor Sysoev899b44e2005-05-12 14:58:06 +00001699}
1700
1701
1702void
Igor Sysoev7bdb7202006-04-19 15:30:56 +00001703ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e)
1704{
1705 ngx_http_script_var_handler_code_t *code;
1706
1707 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1708 "http script set var handler");
1709
1710 code = (ngx_http_script_var_handler_code_t *) e->ip;
1711
1712 e->ip += sizeof(ngx_http_script_var_handler_code_t);
1713
1714 e->sp--;
1715
1716 code->handler(e->request, e->sp, code->data);
1717}
1718
1719
1720void
Igor Sysoev899b44e2005-05-12 14:58:06 +00001721ngx_http_script_var_code(ngx_http_script_engine_t *e)
1722{
1723 ngx_http_variable_value_t *value;
1724 ngx_http_script_var_code_t *code;
1725
1726 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1727 "http script var");
1728
1729 code = (ngx_http_script_var_code_t *) e->ip;
1730
1731 e->ip += sizeof(ngx_http_script_var_code_t);
1732
Igor Sysoev09c684b2005-11-09 17:25:55 +00001733 value = ngx_http_get_flushed_variable(e->request, code->index);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001734
Igor Sysoev09c684b2005-11-09 17:25:55 +00001735 if (value && !value->not_found) {
1736 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
Igor Sysoev0d4b3722007-08-20 09:57:19 +00001737 "http script var: \"%v\"", value);
Igor Sysoev09c684b2005-11-09 17:25:55 +00001738
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001739 *e->sp = *value;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001740 e->sp++;
1741
1742 return;
1743 }
1744
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001745 *e->sp = ngx_http_variable_null_value;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001746 e->sp++;
1747}
1748
1749
1750void
1751ngx_http_script_nop_code(ngx_http_script_engine_t *e)
1752{
1753 e->ip += sizeof(uintptr_t);
Igor Sysoev7578ec92003-06-02 15:24:30 +00001754}