Annotation of embedaddon/nginx/src/http/ngx_http_script.c, revision 1.1.1.1
1.1 misho 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
36: ngx_http_script_flush_complex_value(ngx_http_request_t *r,
37: 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:
57: ngx_int_t
58: ngx_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:
71: ngx_http_script_flush_complex_value(r, val);
72:
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:
107: ngx_int_t
108: ngx_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:
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:
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:
211: char *
212: ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
213: {
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:
247: ngx_int_t
248: ngx_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:
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 *
275: ngx_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:
317: ngx_uint_t
318: ngx_http_script_variables_count(ngx_str_t *value)
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
333: ngx_http_script_compile(ngx_http_script_compile_t *sc)
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) {
413: ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
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 *
486: ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,
487: void *code_lengths, size_t len, void *code_values)
488: {
489: 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++) {
498: if (r->variables[i].no_cacheable) {
499: r->variables[i].valid = 0;
500: r->variables[i].not_found = 0;
501: }
502: }
503:
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;
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
535: ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r,
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 *
642: ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
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;
685: ngx_http_script_copy_code_t *code;
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:
696: code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
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:
707: code->code = ngx_http_script_copy_code;
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
723: ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
724: {
725: ngx_http_script_copy_code_t *code;
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
736: ngx_http_script_copy_code(ngx_http_script_engine_t *e)
737: {
738: u_char *p;
739: ngx_http_script_copy_code_t *code;
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:
753: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
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;
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:
802: size_t
803: ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
804: {
805: ngx_http_variable_value_t *value;
806: ngx_http_script_var_code_t *code;
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
828: ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
829: {
830: u_char *p;
831: ngx_http_variable_value_t *value;
832: ngx_http_script_var_code_t *code;
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:
851: ngx_log_debug2(NGX_LOG_DEBUG_HTTP,
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
883: ngx_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:
892: void
893: ngx_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");
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;
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) {
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)) {
936: ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
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) {
964: e->ip = ngx_http_script_exit;
965: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
966: return;
967: }
968:
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);
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) {
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;
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;
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:
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:
1076: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
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,
1085: NGX_UNESCAPE_REDIRECT);
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)) {
1101: ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
1102: "rewritten redirect: \"%V\"", &e->buf);
1103: }
1104:
1105: ngx_http_clear_location(r);
1106:
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;
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)) {
1144: 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:
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;
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: {
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:
1202: size_t
1203: ngx_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:
1240: void
1241: ngx_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:
1279: #endif
1280:
1281:
1282: static ngx_int_t
1283: ngx_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;
1295: code->conf_prefix = sc->conf_prefix;
1296:
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;
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: {
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:
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: {
1328: ngx_http_script_full_name_code_t *code;
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;
1341: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1342: return;
1343: }
1344:
1345: e->buf = value;
1346:
1347: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1348: "http script fullname: \"%V\"", &value);
1349:
1350: e->ip += sizeof(ngx_http_script_full_name_code_t);
1351: }
1352:
1353:
1354: void
1355: ngx_http_script_return_code(ngx_http_script_engine_t *e)
1356: {
1357: ngx_http_script_return_code_t *code;
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
1376: ngx_http_script_break_code(ngx_http_script_engine_t *e)
1377: {
1378: e->request->uri_changed = 0;
1379:
1380: e->ip = ngx_http_script_exit;
1381: }
1382:
1383:
1384: void
1385: ngx_http_script_if_code(ngx_http_script_engine_t *e)
1386: {
1387: ngx_http_script_if_code_t *code;
1388:
1389: code = (ngx_http_script_if_code_t *) e->ip;
1390:
1391: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
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;
1399: ngx_http_update_location_config(e->request);
1400: }
1401:
1402: e->ip += sizeof(ngx_http_script_if_code_t);
1403: return;
1404: }
1405:
1406: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1407: "http script if: false");
1408:
1409: e->ip += code->next;
1410: }
1411:
1412:
1413: void
1414: ngx_http_script_equal_code(ngx_http_script_engine_t *e)
1415: {
1416: ngx_http_variable_value_t *val, *res;
1417:
1418: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
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: {
1430: *res = ngx_http_variable_true_value;
1431: return;
1432: }
1433:
1434: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1435: "http script equal: no");
1436:
1437: *res = ngx_http_variable_null_value;
1438: }
1439:
1440:
1441: void
1442: ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
1443: {
1444: ngx_http_variable_value_t *val, *res;
1445:
1446: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
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: {
1458: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1459: "http script not equal: no");
1460:
1461: *res = ngx_http_variable_null_value;
1462: return;
1463: }
1464:
1465: *res = ngx_http_variable_true_value;
1466: }
1467:
1468:
1469: void
1470: ngx_http_script_file_code(ngx_http_script_engine_t *e)
1471: {
1472: ngx_str_t path;
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;
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:
1489: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1490: "http script file op %p \"%V\"", code->op, &path);
1491:
1492: clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
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;
1499: of.min_uses = clcf->open_file_cache_min_uses;
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;
1506: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
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: {
1517: ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
1518: "%s \"%s\" failed", of.failed, value->data);
1519: }
1520:
1521: switch (code->op) {
1522:
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:
1527: goto false_value;
1528:
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:
1533: goto true_value;
1534: }
1535:
1536: goto false_value;
1537: }
1538:
1539: switch (code->op) {
1540: case ngx_http_script_file_plain:
1541: if (of.is_file) {
1542: goto true_value;
1543: }
1544: goto false_value;
1545:
1546: case ngx_http_script_file_not_plain:
1547: if (of.is_file) {
1548: goto false_value;
1549: }
1550: goto true_value;
1551:
1552: case ngx_http_script_file_dir:
1553: if (of.is_dir) {
1554: goto true_value;
1555: }
1556: goto false_value;
1557:
1558: case ngx_http_script_file_not_dir:
1559: if (of.is_dir) {
1560: goto false_value;
1561: }
1562: goto true_value;
1563:
1564: case ngx_http_script_file_exists:
1565: if (of.is_file || of.is_dir || of.is_link) {
1566: goto true_value;
1567: }
1568: goto false_value;
1569:
1570: case ngx_http_script_file_not_exists:
1571: if (of.is_file || of.is_dir || of.is_link) {
1572: goto false_value;
1573: }
1574: goto true_value;
1575:
1576: case ngx_http_script_file_exec:
1577: if (of.is_exec) {
1578: goto true_value;
1579: }
1580: goto false_value;
1581:
1582: case ngx_http_script_file_not_exec:
1583: if (of.is_exec) {
1584: goto false_value;
1585: }
1586: goto true_value;
1587: }
1588:
1589: false_value:
1590:
1591: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1592: "http script file op false");
1593:
1594: *value = ngx_http_variable_null_value;
1595: return;
1596:
1597: true_value:
1598:
1599: *value = ngx_http_variable_true_value;
1600: return;
1601: }
1602:
1603:
1604: void
1605: ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
1606: {
1607: size_t len;
1608: ngx_http_script_engine_t le;
1609: ngx_http_script_len_code_pt lcode;
1610: ngx_http_script_complex_value_code_t *code;
1611:
1612: code = (ngx_http_script_complex_value_code_t *) e->ip;
1613:
1614: e->ip += sizeof(ngx_http_script_complex_value_code_t);
1615:
1616: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
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;
1634: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
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
1647: ngx_http_script_value_code(ngx_http_script_engine_t *e)
1648: {
1649: ngx_http_script_value_code_t *code;
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:
1658: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1659: "http script value: \"%v\"", e->sp);
1660:
1661: e->sp++;
1662: }
1663:
1664:
1665: void
1666: ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
1667: {
1668: ngx_http_request_t *r;
1669: ngx_http_script_var_code_t *code;
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: {
1687: ngx_http_variable_t *v;
1688: ngx_http_core_main_conf_t *cmcf;
1689:
1690: cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1691:
1692: v = cmcf->variables.elts;
1693:
1694: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1695: "http script set $%V", &v[code->index].name);
1696: }
1697: #endif
1698: }
1699:
1700:
1701: void
1702: ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e)
1703: {
1704: ngx_http_script_var_handler_code_t *code;
1705:
1706: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
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
1720: ngx_http_script_var_code(ngx_http_script_engine_t *e)
1721: {
1722: ngx_http_variable_value_t *value;
1723: ngx_http_script_var_code_t *code;
1724:
1725: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
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) {
1735: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1736: "http script var: \"%v\"", value);
1737:
1738: *e->sp = *value;
1739: e->sp++;
1740:
1741: return;
1742: }
1743:
1744: *e->sp = ngx_http_variable_null_value;
1745: e->sp++;
1746: }
1747:
1748:
1749: void
1750: ngx_http_script_nop_code(ngx_http_script_engine_t *e)
1751: {
1752: e->ip += sizeof(uintptr_t);
1753: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>