Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http_script.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 
12 
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,
18  ngx_str_t *name);
19 static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc);
20 #if (NGX_PCRE)
21 static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc,
22  ngx_uint_t n);
23 #endif
24 static ngx_int_t
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);
28 
29 
30 #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
31 
32 static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL;
33 
34 
35 void
38 {
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 
59  ngx_str_t *value)
60 {
61  size_t len;
65 
66  if (val->lengths == NULL) {
67  *value = val->value;
68  return NGX_OK;
69  }
70 
72 
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 
107 ngx_int_t
109 {
110  ngx_str_t *v;
111  ngx_uint_t i, n, nv, nc;
112  ngx_array_t flushes, lengths, values, *pf, *pl, *pv;
114 
115  v = ccv->value;
116 
117  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 
131  if ((v->len == 0 || v->data[0] != '$')
132  && (ccv->conf_prefix || ccv->root_prefix))
133  {
134  if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
135  return NGX_ERROR;
136  }
137 
138  ccv->conf_prefix = 0;
139  ccv->root_prefix = 0;
140  }
141 
142  ccv->complex_value->value = *v;
143  ccv->complex_value->flushes = NULL;
144  ccv->complex_value->lengths = NULL;
145  ccv->complex_value->values = NULL;
146 
147  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 
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 
211 char *
213 {
214  char *p = conf;
215 
216  ngx_str_t *value;
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 
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 
247 ngx_int_t
249 {
250  ngx_str_t val;
251  ngx_uint_t i;
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 
265  if (val.len && (val.len != 1 || val.data[0] != '0')) {
266  return NGX_DECLINED;
267  }
268  }
269 
270  return NGX_OK;
271 }
272 
273 
274 char *
276 {
277  char *p = conf;
278 
279  ngx_str_t *value;
280  ngx_uint_t i;
281  ngx_array_t **a;
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 
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 
319 {
320  ngx_uint_t i, n;
321 
322  for (n = 0, i = 0; i < value->len; i++) {
323  if (value->data[i] == '$') {
324  n++;
325  }
326  }
327 
328  return n;
329 }
330 
331 
332 ngx_int_t
334 {
335  u_char ch;
336  ngx_str_t name;
337  ngx_uint_t i, bracket;
338 
339  if (ngx_http_script_init_arrays(sc) != NGX_OK) {
340  return NGX_ERROR;
341  }
342 
343  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 
353 #if (NGX_PCRE)
354  {
355  ngx_uint_t n;
356 
357  if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
358 
359  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 
367  if (ngx_http_script_add_capture_code(sc, n) != NGX_OK) {
368  return NGX_ERROR;
369  }
370 
371  i++;
372 
373  continue;
374  }
375  }
376 #endif
377 
378  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) {
414  "the closing bracket in \"%V\" "
415  "variable is missing", &name);
416  return NGX_ERROR;
417  }
418 
419  if (name.len == 0) {
420  goto invalid_variable;
421  }
422 
423  sc->variables++;
424 
425  if (ngx_http_script_add_var_code(sc, &name) != NGX_OK) {
426  return NGX_ERROR;
427  }
428 
429  continue;
430  }
431 
432  if (sc->source->data[i] == '?' && sc->compile_args) {
433  sc->args = 1;
434  sc->compile_args = 0;
435 
436  if (ngx_http_script_add_args_code(sc) != NGX_OK) {
437  return NGX_ERROR;
438  }
439 
440  i++;
441 
442  continue;
443  }
444 
445  name.data = &sc->source->data[i];
446 
447  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 
462  i++;
463  name.len++;
464  }
465 
466  sc->size += name.len;
467 
468  if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len))
469  != NGX_OK)
470  {
471  return NGX_ERROR;
472  }
473  }
474 
475  return ngx_http_script_done(sc);
476 
477 invalid_variable:
478 
479  ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");
480 
481  return NGX_ERROR;
482 }
483 
484 
485 u_char *
487  void *code_lengths, size_t len, void *code_values)
488 {
489  ngx_uint_t i;
494 
496 
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;
501  }
502  }
503 
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;
517  value->data = ngx_pnalloc(r->pool, len);
518  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 
534 void
536  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++) {
543  if (r->variables[index[n]].no_cacheable) {
544  r->variables[index[n]].valid = 0;
545  r->variables[index[n]].not_found = 0;
546  }
547  }
548  }
549 }
550 
551 
552 static ngx_int_t
553 ngx_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 
596 static ngx_int_t
597 ngx_http_script_done(ngx_http_script_compile_t *sc)
598 {
599  ngx_str_t zero;
600  uintptr_t *code;
601 
602  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 
618  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 
641 void *
643 {
644  if (*codes == NULL) {
645  *codes = ngx_array_create(pool, 256, 1);
646  if (*codes == NULL) {
647  return NULL;
648  }
649  }
650 
651  return ngx_array_push_n(*codes, size);
652 }
653 
654 
655 void *
656 ngx_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) {
665  return NULL;
666  }
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 }
677 
678 
679 static ngx_int_t
680 ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value,
681  ngx_uint_t last)
682 {
683  u_char *p;
684  size_t size, len, zero;
686 
687  zero = (sc->zero && last);
688  len = value->len + zero;
689 
690  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 
697  code->len = len;
698 
699  size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
700  & ~(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 
708  code->len = len;
709 
710  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  }
717 
718  return NGX_OK;
719 }
720 
721 
722 size_t
724 {
726 
727  code = (ngx_http_script_copy_code_t *) e->ip;
728 
729  e->ip += sizeof(ngx_http_script_copy_code_t);
730 
731  return code->len;
732 }
733 
734 
735 void
737 {
738  u_char *p;
740 
741  code = (ngx_http_script_copy_code_t *) e->ip;
742 
743  p = e->pos;
744 
745  if (!e->skip) {
746  e->pos = ngx_copy(p, e->ip + sizeof(ngx_http_script_copy_code_t),
747  code->len);
748  }
749 
750  e->ip += sizeof(ngx_http_script_copy_code_t)
751  + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
752 
754  "http script copy: \"%*s\"", e->pos - p, p);
755 }
756 
757 
758 static ngx_int_t
759 ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, ngx_str_t *name)
760 {
761  ngx_int_t index, *p;
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 
786  code->index = (uintptr_t) index;
787 
788  code = ngx_http_script_add_code(*sc->values,
790  &sc->main);
791  if (code == NULL) {
792  return NGX_ERROR;
793  }
794 
796  code->index = (uintptr_t) index;
797 
798  return NGX_OK;
799 }
800 
801 
802 size_t
804 {
807 
808  code = (ngx_http_script_var_code_t *) e->ip;
809 
810  e->ip += sizeof(ngx_http_script_var_code_t);
811 
812  if (e->flushed) {
813  value = ngx_http_get_indexed_variable(e->request, code->index);
814 
815  } else {
816  value = ngx_http_get_flushed_variable(e->request, code->index);
817  }
818 
819  if (value && !value->not_found) {
820  return value->len;
821  }
822 
823  return 0;
824 }
825 
826 
827 void
829 {
830  u_char *p;
833 
834  code = (ngx_http_script_var_code_t *) e->ip;
835 
836  e->ip += sizeof(ngx_http_script_var_code_t);
837 
838  if (!e->skip) {
839 
840  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) {
848  p = e->pos;
849  e->pos = ngx_copy(p, value->data, value->len);
850 
852  e->request->connection->log, 0,
853  "http script var: \"%*s\"", e->pos - p, p);
854  }
855  }
856 }
857 
858 
859 static ngx_int_t
860 ngx_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 
882 size_t
884 {
885  e->is_args = 1;
886  e->ip += sizeof(uintptr_t);
887 
888  return 1;
889 }
890 
891 
892 void
894 {
896  "http script args");
897 
898  e->is_args = 1;
899  e->args = e->pos;
900  e->ip += sizeof(uintptr_t);
901 }
902 
903 
904 #if (NGX_PCRE)
905 
906 void
907 ngx_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;
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 
922  "http script regex: \"%V\"", &code->name);
923 
924  if (code->uri) {
925  e->line = r->uri;
926  } else {
927  e->sp--;
928  e->line.len = e->sp->len;
929  e->line.data = e->sp->data;
930  }
931 
932  rc = ngx_http_regex_exec(r, code->regex, &e->line);
933 
934  if (rc == NGX_DECLINED) {
935  if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
937  "\"%V\" does not match \"%V\"",
938  &code->name, &e->line);
939  }
940 
941  r->ncaptures = 0;
942 
943  if (code->test) {
944  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 
953  e->sp++;
954 
955  e->ip += sizeof(ngx_http_script_regex_code_t);
956  return;
957  }
958 
959  e->ip += code->next;
960  return;
961  }
962 
963  if (rc == NGX_ERROR) {
966  return;
967  }
968 
969  if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
971  "\"%V\" matches \"%V\"", &code->name, &e->line);
972  }
973 
974  if (code->test) {
975  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 
984  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) {
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;
1005  r->uri_changed = 0;
1006 
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) {
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,
1018  NGX_ESCAPE_ARGS);
1019  }
1020  }
1021 
1022  for (n = 2; n < r->ncaptures; n += 2) {
1023  e->buf.len += r->captures[n + 1] - r->captures[n];
1024  }
1025 
1026  } else {
1027  ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
1028 
1029  le.ip = code->lengths->elts;
1030  le.line = e->line;
1031  le.request = r;
1032  le.quote = code->redirect;
1033 
1034  len = 0;
1035 
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 
1044  if (code->add_args && r->args.len) {
1045  e->buf.len += r->args.len + 1;
1046  }
1047 
1048  e->buf.data = ngx_pnalloc(r->pool, e->buf.len);
1049  if (e->buf.data == NULL) {
1050  e->ip = ngx_http_script_exit;
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 
1063 void
1064 ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
1065 {
1066  u_char *dst, *src;
1067  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 
1077  "http script regex end");
1078 
1079  if (code->redirect) {
1080 
1081  dst = e->buf.data;
1082  src = e->buf.data;
1083 
1084  ngx_unescape_uri(&dst, &src, e->pos - e->buf.data,
1086 
1087  if (src < e->pos) {
1088  dst = ngx_movemem(dst, src, e->pos - src);
1089  }
1090 
1091  e->pos = dst;
1092 
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);
1096  }
1097 
1098  e->buf.len = e->pos - e->buf.data;
1099 
1100  if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
1102  "rewritten redirect: \"%V\"", &e->buf);
1103  }
1104 
1106 
1108  if (r->headers_out.location == NULL) {
1109  e->ip = ngx_http_script_exit;
1111  return;
1112  }
1113 
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;
1117 
1118  e->ip += sizeof(ngx_http_script_regex_end_code_t);
1119  return;
1120  }
1121 
1122  if (e->args) {
1123  e->buf.len = e->args - e->buf.data;
1124 
1125  if (code->add_args && r->args.len) {
1126  *e->pos++ = '&';
1127  e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
1128  }
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;
1137 
1138  if (!code->add_args) {
1139  r->args.len = 0;
1140  }
1141  }
1142 
1143  if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
1145  "rewritten data: \"%V\", args: \"%V\"",
1146  &e->buf, &r->args);
1147  }
1148 
1149  if (code->uri) {
1150  r->uri = e->buf;
1151 
1152  if (r->uri.len == 0) {
1154  "the rewritten URI has a zero length");
1155  e->ip = ngx_http_script_exit;
1157  return;
1158  }
1159 
1160  ngx_http_set_exten(r);
1161  }
1162 
1163  e->ip += sizeof(ngx_http_script_regex_end_code_t);
1164 }
1165 
1166 
1167 static ngx_int_t
1168 ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, ngx_uint_t n)
1169 {
1171 
1172  code = ngx_http_script_add_code(*sc->lengths,
1174  NULL);
1175  if (code == NULL) {
1176  return NGX_ERROR;
1177  }
1178 
1179  code->code = (ngx_http_script_code_pt)
1181  code->n = 2 * n;
1182 
1183 
1184  code = ngx_http_script_add_code(*sc->values,
1186  &sc->main);
1187  if (code == NULL) {
1188  return NGX_ERROR;
1189  }
1190 
1192  code->n = 2 * n;
1193 
1194  if (sc->ncaptures < n) {
1195  sc->ncaptures = n;
1196  }
1197 
1198  return NGX_OK;
1199 }
1200 
1201 
1202 size_t
1204 {
1205  int *cap;
1206  u_char *p;
1207  ngx_uint_t n;
1208  ngx_http_request_t *r;
1210 
1211  r = e->request;
1212 
1214 
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 
1240 void
1242 {
1243  int *cap;
1244  u_char *p, *pos;
1245  ngx_uint_t n;
1246  ngx_http_request_t *r;
1248 
1249  r = e->request;
1250 
1252 
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 
1276  "http script capture: \"%*s\"", e->pos - pos, pos);
1277 }
1278 
1279 #endif
1280 
1281 
1282 static ngx_int_t
1283 ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
1284 {
1286 
1287  code = ngx_http_script_add_code(*sc->lengths,
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;
1295  code->conf_prefix = sc->conf_prefix;
1296 
1297  code = ngx_http_script_add_code(*sc->values,
1299  &sc->main);
1300  if (code == NULL) {
1301  return NGX_ERROR;
1302  }
1303 
1304  code->code = ngx_http_script_full_name_code;
1305  code->conf_prefix = sc->conf_prefix;
1306 
1307  return NGX_OK;
1308 }
1309 
1310 
1311 static size_t
1312 ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e)
1313 {
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 
1320  return code->conf_prefix ? ngx_cycle->conf_prefix.len:
1321  ngx_cycle->prefix.len;
1322 }
1323 
1324 
1325 static void
1326 ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
1327 {
1329 
1330  ngx_str_t value;
1331 
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 
1337  if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &value, code->conf_prefix)
1338  != NGX_OK)
1339  {
1340  e->ip = ngx_http_script_exit;
1342  return;
1343  }
1344 
1345  e->buf = value;
1346 
1348  "http script fullname: \"%V\"", &value);
1349 
1350  e->ip += sizeof(ngx_http_script_full_name_code_t);
1351 }
1352 
1353 
1354 void
1356 {
1358 
1359  code = (ngx_http_script_return_code_t *) e->ip;
1360 
1361  if (code->status < NGX_HTTP_BAD_REQUEST
1362  || code->text.value.len
1363  || code->text.lengths)
1364  {
1365  e->status = ngx_http_send_response(e->request, code->status, NULL,
1366  &code->text);
1367  } else {
1368  e->status = code->status;
1369  }
1370 
1371  e->ip = ngx_http_script_exit;
1372 }
1373 
1374 
1375 void
1377 {
1378  e->request->uri_changed = 0;
1379 
1380  e->ip = ngx_http_script_exit;
1381 }
1382 
1383 
1384 void
1386 {
1388 
1389  code = (ngx_http_script_if_code_t *) e->ip;
1390 
1392  "http script if");
1393 
1394  e->sp--;
1395 
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;
1400  }
1401 
1402  e->ip += sizeof(ngx_http_script_if_code_t);
1403  return;
1404  }
1405 
1407  "http script if: false");
1408 
1409  e->ip += code->next;
1410 }
1411 
1412 
1413 void
1415 {
1416  ngx_http_variable_value_t *val, *res;
1417 
1419  "http script equal");
1420 
1421  e->sp--;
1422  val = e->sp;
1423  res = e->sp - 1;
1424 
1425  e->ip += sizeof(uintptr_t);
1426 
1427  if (val->len == res->len
1428  && ngx_strncmp(val->data, res->data, res->len) == 0)
1429  {
1431  return;
1432  }
1433 
1435  "http script equal: no");
1436 
1438 }
1439 
1440 
1441 void
1443 {
1444  ngx_http_variable_value_t *val, *res;
1445 
1447  "http script not equal");
1448 
1449  e->sp--;
1450  val = e->sp;
1451  res = e->sp - 1;
1452 
1453  e->ip += sizeof(uintptr_t);
1454 
1455  if (val->len == res->len
1456  && ngx_strncmp(val->data, res->data, res->len) == 0)
1457  {
1459  "http script not equal: no");
1460 
1462  return;
1463  }
1464 
1466 }
1467 
1468 
1469 void
1471 {
1472  ngx_str_t path;
1473  ngx_http_request_t *r;
1478 
1479  value = e->sp - 1;
1480 
1481  code = (ngx_http_script_file_code_t *) e->ip;
1482  e->ip += sizeof(ngx_http_script_file_code_t);
1483 
1484  path.len = value->len - 1;
1485  path.data = value->data;
1486 
1487  r = e->request;
1488 
1490  "http script file op %p \"%V\"", code->op, &path);
1491 
1493 
1494  ngx_memzero(&of, sizeof(ngx_open_file_info_t));
1495 
1496  of.read_ahead = clcf->read_ahead;
1497  of.directio = clcf->directio;
1498  of.valid = clcf->open_file_cache_valid;
1500  of.test_only = 1;
1501  of.errors = clcf->open_file_cache_errors;
1502  of.events = clcf->open_file_cache_events;
1503 
1504  if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
1505  e->ip = ngx_http_script_exit;
1507  return;
1508  }
1509 
1510  if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
1511  != NGX_OK)
1512  {
1513  if (of.err != NGX_ENOENT
1514  && of.err != NGX_ENOTDIR
1515  && of.err != NGX_ENAMETOOLONG)
1516  {
1518  "%s \"%s\" failed", of.failed, value->data);
1519  }
1520 
1521  switch (code->op) {
1522 
1527  goto false_value;
1528 
1533  goto true_value;
1534  }
1535 
1536  goto false_value;
1537  }
1538 
1539  switch (code->op) {
1541  if (of.is_file) {
1542  goto true_value;
1543  }
1544  goto false_value;
1545 
1547  if (of.is_file) {
1548  goto false_value;
1549  }
1550  goto true_value;
1551 
1553  if (of.is_dir) {
1554  goto true_value;
1555  }
1556  goto false_value;
1557 
1559  if (of.is_dir) {
1560  goto false_value;
1561  }
1562  goto true_value;
1563 
1565  if (of.is_file || of.is_dir || of.is_link) {
1566  goto true_value;
1567  }
1568  goto false_value;
1569 
1571  if (of.is_file || of.is_dir || of.is_link) {
1572  goto false_value;
1573  }
1574  goto true_value;
1575 
1577  if (of.is_exec) {
1578  goto true_value;
1579  }
1580  goto false_value;
1581 
1583  if (of.is_exec) {
1584  goto false_value;
1585  }
1586  goto true_value;
1587  }
1588 
1589 false_value:
1590 
1592  "http script file op false");
1593 
1595  return;
1596 
1597 true_value:
1598 
1600  return;
1601 }
1602 
1603 
1604 void
1606 {
1607  size_t len;
1611 
1613 
1615 
1617  "http script complex value");
1618 
1619  ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
1620 
1621  le.ip = code->lengths->elts;
1622  le.line = e->line;
1623  le.request = e->request;
1624  le.quote = e->quote;
1625 
1626  for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
1627  lcode = *(ngx_http_script_len_code_pt *) le.ip;
1628  }
1629 
1630  e->buf.len = len;
1631  e->buf.data = ngx_pnalloc(e->request->pool, len);
1632  if (e->buf.data == NULL) {
1633  e->ip = ngx_http_script_exit;
1635  return;
1636  }
1637 
1638  e->pos = e->buf.data;
1639 
1640  e->sp->len = e->buf.len;
1641  e->sp->data = e->buf.data;
1642  e->sp++;
1643 }
1644 
1645 
1646 void
1648 {
1650 
1651  code = (ngx_http_script_value_code_t *) e->ip;
1652 
1653  e->ip += sizeof(ngx_http_script_value_code_t);
1654 
1655  e->sp->len = code->text_len;
1656  e->sp->data = (u_char *) code->text_data;
1657 
1659  "http script value: \"%v\"", e->sp);
1660 
1661  e->sp++;
1662 }
1663 
1664 
1665 void
1667 {
1668  ngx_http_request_t *r;
1670 
1671  code = (ngx_http_script_var_code_t *) e->ip;
1672 
1673  e->ip += sizeof(ngx_http_script_var_code_t);
1674 
1675  r = e->request;
1676 
1677  e->sp--;
1678 
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;
1684 
1685 #if (NGX_DEBUG)
1686  {
1689 
1691 
1692  v = cmcf->variables.elts;
1693 
1695  "http script set $%V", &v[code->index].name);
1696  }
1697 #endif
1698 }
1699 
1700 
1701 void
1703 {
1705 
1707  "http script set var handler");
1708 
1709  code = (ngx_http_script_var_handler_code_t *) e->ip;
1710 
1711  e->ip += sizeof(ngx_http_script_var_handler_code_t);
1712 
1713  e->sp--;
1714 
1715  code->handler(e->request, e->sp, code->data);
1716 }
1717 
1718 
1719 void
1721 {
1724 
1726  "http script var");
1727 
1728  code = (ngx_http_script_var_code_t *) e->ip;
1729 
1730  e->ip += sizeof(ngx_http_script_var_code_t);
1731 
1732  value = ngx_http_get_flushed_variable(e->request, code->index);
1733 
1734  if (value && !value->not_found) {
1736  "http script var: \"%v\"", value);
1737 
1738  *e->sp = *value;
1739  e->sp++;
1740 
1741  return;
1742  }
1743 
1745  e->sp++;
1746 }
1747 
1748 
1749 void
1751 {
1752  e->ip += sizeof(uintptr_t);
1753 }