src/http/ngx_http_script.c - nginx-1.7.10

Global variables defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_http.h>


  8. static ngx_int_t ngx_http_script_init_arrays(ngx_http_script_compile_t *sc);
  9. static ngx_int_t ngx_http_script_done(ngx_http_script_compile_t *sc);
  10. static ngx_int_t ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc,
  11.     ngx_str_t *value, ngx_uint_t last);
  12. static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc,
  13.     ngx_str_t *name);
  14. static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc);
  15. #if (NGX_PCRE)
  16. static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc,
  17.      ngx_uint_t n);
  18. #endif
  19. static ngx_int_t
  20.      ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc);
  21. static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e);
  22. static void ngx_http_script_full_name_code(ngx_http_script_engine_t *e);


  23. #define ngx_http_script_exit  (u_char *) &ngx_http_script_exit_code

  24. static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL;


  25. void
  26. ngx_http_script_flush_complex_value(ngx_http_request_t *r,
  27.     ngx_http_complex_value_t *val)
  28. {
  29.     ngx_uint_t *index;

  30.     index = val->flushes;

  31.     if (index) {
  32.         while (*index != (ngx_uint_t) -1) {

  33.             if (r->variables[*index].no_cacheable) {
  34.                 r->variables[*index].valid = 0;
  35.                 r->variables[*index].not_found = 0;
  36.             }

  37.             index++;
  38.         }
  39.     }
  40. }


  41. ngx_int_t
  42. ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val,
  43.     ngx_str_t *value)
  44. {
  45.     size_t                        len;
  46.     ngx_http_script_code_pt       code;
  47.     ngx_http_script_len_code_pt   lcode;
  48.     ngx_http_script_engine_t      e;

  49.     if (val->lengths == NULL) {
  50.         *value = val->value;
  51.         return NGX_OK;
  52.     }

  53.     ngx_http_script_flush_complex_value(r, val);

  54.     ngx_memzero(&e, sizeof(ngx_http_script_engine_t));

  55.     e.ip = val->lengths;
  56.     e.request = r;
  57.     e.flushed = 1;

  58.     len = 0;

  59.     while (*(uintptr_t *) e.ip) {
  60.         lcode = *(ngx_http_script_len_code_pt *) e.ip;
  61.         len += lcode(&e);
  62.     }

  63.     value->len = len;
  64.     value->data = ngx_pnalloc(r->pool, len);
  65.     if (value->data == NULL) {
  66.         return NGX_ERROR;
  67.     }

  68.     e.ip = val->values;
  69.     e.pos = value->data;
  70.     e.buf = *value;

  71.     while (*(uintptr_t *) e.ip) {
  72.         code = *(ngx_http_script_code_pt *) e.ip;
  73.         code((ngx_http_script_engine_t *) &e);
  74.     }

  75.     *value = e.buf;

  76.     return NGX_OK;
  77. }


  78. ngx_int_t
  79. ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
  80. {
  81.     ngx_str_t                  *v;
  82.     ngx_uint_t                  i, n, nv, nc;
  83.     ngx_array_t                 flushes, lengths, values, *pf, *pl, *pv;
  84.     ngx_http_script_compile_t   sc;

  85.     v = ccv->value;

  86.     nv = 0;
  87.     nc = 0;

  88.     for (i = 0; i < v->len; i++) {
  89.         if (v->data[i] == '$') {
  90.             if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
  91.                 nc++;

  92.             } else {
  93.                 nv++;
  94.             }
  95.         }
  96.     }

  97.     if ((v->len == 0 || v->data[0] != '$')
  98.         && (ccv->conf_prefix || ccv->root_prefix))
  99.     {
  100.         if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
  101.             return NGX_ERROR;
  102.         }

  103.         ccv->conf_prefix = 0;
  104.         ccv->root_prefix = 0;
  105.     }

  106.     ccv->complex_value->value = *v;
  107.     ccv->complex_value->flushes = NULL;
  108.     ccv->complex_value->lengths = NULL;
  109.     ccv->complex_value->values = NULL;

  110.     if (nv == 0 && nc == 0) {
  111.         return NGX_OK;
  112.     }

  113.     n = nv + 1;

  114.     if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
  115.         != NGX_OK)
  116.     {
  117.         return NGX_ERROR;
  118.     }

  119.     n = nv * (2 * sizeof(ngx_http_script_copy_code_t)
  120.                   + sizeof(ngx_http_script_var_code_t))
  121.         + sizeof(uintptr_t);

  122.     if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
  123.         return NGX_ERROR;
  124.     }

  125.     n = (nv * (2 * sizeof(ngx_http_script_copy_code_t)
  126.                    + sizeof(ngx_http_script_var_code_t))
  127.                 + sizeof(uintptr_t)
  128.                 + v->len
  129.                 + sizeof(uintptr_t) - 1)
  130.             & ~(sizeof(uintptr_t) - 1);

  131.     if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
  132.         return NGX_ERROR;
  133.     }

  134.     pf = &flushes;
  135.     pl = &lengths;
  136.     pv = &values;

  137.     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

  138.     sc.cf = ccv->cf;
  139.     sc.source = v;
  140.     sc.flushes = &pf;
  141.     sc.lengths = &pl;
  142.     sc.values = &pv;
  143.     sc.complete_lengths = 1;
  144.     sc.complete_values = 1;
  145.     sc.zero = ccv->zero;
  146.     sc.conf_prefix = ccv->conf_prefix;
  147.     sc.root_prefix = ccv->root_prefix;

  148.     if (ngx_http_script_compile(&sc) != NGX_OK) {
  149.         return NGX_ERROR;
  150.     }

  151.     if (flushes.nelts) {
  152.         ccv->complex_value->flushes = flushes.elts;
  153.         ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
  154.     }

  155.     ccv->complex_value->lengths = lengths.elts;
  156.     ccv->complex_value->values = values.elts;

  157.     return NGX_OK;
  158. }


  159. char *
  160. ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  161. {
  162.     char  *p = conf;

  163.     ngx_str_t                          *value;
  164.     ngx_http_complex_value_t          **cv;
  165.     ngx_http_compile_complex_value_t    ccv;

  166.     cv = (ngx_http_complex_value_t **) (p + cmd->offset);

  167.     if (*cv != NULL) {
  168.         return "duplicate";
  169.     }

  170.     *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
  171.     if (*cv == NULL) {
  172.         return NGX_CONF_ERROR;
  173.     }

  174.     value = cf->args->elts;

  175.     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));

  176.     ccv.cf = cf;
  177.     ccv.value = &value[1];
  178.     ccv.complex_value = *cv;

  179.     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  180.         return NGX_CONF_ERROR;
  181.     }

  182.     return NGX_CONF_OK;
  183. }


  184. ngx_int_t
  185. ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates)
  186. {
  187.     ngx_str_t                  val;
  188.     ngx_uint_t                 i;
  189.     ngx_http_complex_value_t  *cv;

  190.     if (predicates == NULL) {
  191.         return NGX_OK;
  192.     }

  193.     cv = predicates->elts;

  194.     for (i = 0; i < predicates->nelts; i++) {
  195.         if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
  196.             return NGX_ERROR;
  197.         }

  198.         if (val.len && (val.len != 1 || val.data[0] != '0')) {
  199.             return NGX_DECLINED;
  200.         }
  201.     }

  202.     return NGX_OK;
  203. }


  204. char *
  205. ngx_http_set_predicate_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  206. {
  207.     char  *p = conf;

  208.     ngx_str_t                          *value;
  209.     ngx_uint_t                          i;
  210.     ngx_array_t                       **a;
  211.     ngx_http_complex_value_t           *cv;
  212.     ngx_http_compile_complex_value_t    ccv;

  213.     a = (ngx_array_t **) (p + cmd->offset);

  214.     if (*a == NGX_CONF_UNSET_PTR) {
  215.         *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t));
  216.         if (*a == NULL) {
  217.             return NGX_CONF_ERROR;
  218.         }
  219.     }

  220.     value = cf->args->elts;

  221.     for (i = 1; i < cf->args->nelts; i++) {
  222.         cv = ngx_array_push(*a);
  223.         if (cv == NULL) {
  224.             return NGX_CONF_ERROR;
  225.         }

  226.         ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));

  227.         ccv.cf = cf;
  228.         ccv.value = &value[i];
  229.         ccv.complex_value = cv;

  230.         if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  231.             return NGX_CONF_ERROR;
  232.         }
  233.     }

  234.     return NGX_CONF_OK;
  235. }


  236. ngx_uint_t
  237. ngx_http_script_variables_count(ngx_str_t *value)
  238. {
  239.     ngx_uint_t  i, n;

  240.     for (n = 0, i = 0; i < value->len; i++) {
  241.         if (value->data[i] == '$') {
  242.             n++;
  243.         }
  244.     }

  245.     return n;
  246. }


  247. ngx_int_t
  248. ngx_http_script_compile(ngx_http_script_compile_t *sc)
  249. {
  250.     u_char       ch;
  251.     ngx_str_t    name;
  252.     ngx_uint_t   i, bracket;

  253.     if (ngx_http_script_init_arrays(sc) != NGX_OK) {
  254.         return NGX_ERROR;
  255.     }

  256.     for (i = 0; i < sc->source->len; /* void */ ) {

  257.         name.len = 0;

  258.         if (sc->source->data[i] == '$') {

  259.             if (++i == sc->source->len) {
  260.                 goto invalid_variable;
  261.             }

  262. #if (NGX_PCRE)
  263.             {
  264.             ngx_uint_t  n;

  265.             if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {

  266.                 n = sc->source->data[i] - '0';

  267.                 if (sc->captures_mask & (1 << n)) {
  268.                     sc->dup_capture = 1;
  269.                 }

  270.                 sc->captures_mask |= 1 << n;

  271.                 if (ngx_http_script_add_capture_code(sc, n) != NGX_OK) {
  272.                     return NGX_ERROR;
  273.                 }

  274.                 i++;

  275.                 continue;
  276.             }
  277.             }
  278. #endif

  279.             if (sc->source->data[i] == '{') {
  280.                 bracket = 1;

  281.                 if (++i == sc->source->len) {
  282.                     goto invalid_variable;
  283.                 }

  284.                 name.data = &sc->source->data[i];

  285.             } else {
  286.                 bracket = 0;
  287.                 name.data = &sc->source->data[i];
  288.             }

  289.             for ( /* void */ ; i < sc->source->len; i++, name.len++) {
  290.                 ch = sc->source->data[i];

  291.                 if (ch == '}' && bracket) {
  292.                     i++;
  293.                     bracket = 0;
  294.                     break;
  295.                 }

  296.                 if ((ch >= 'A' && ch <= 'Z')
  297.                     || (ch >= 'a' && ch <= 'z')
  298.                     || (ch >= '0' && ch <= '9')
  299.                     || ch == '_')
  300.                 {
  301.                     continue;
  302.                 }

  303.                 break;
  304.             }

  305.             if (bracket) {
  306.                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
  307.                                    "the closing bracket in \"%V\" "
  308.                                    "variable is missing", &name);
  309.                 return NGX_ERROR;
  310.             }

  311.             if (name.len == 0) {
  312.                 goto invalid_variable;
  313.             }

  314.             sc->variables++;

  315.             if (ngx_http_script_add_var_code(sc, &name) != NGX_OK) {
  316.                 return NGX_ERROR;
  317.             }

  318.             continue;
  319.         }

  320.         if (sc->source->data[i] == '?' && sc->compile_args) {
  321.             sc->args = 1;
  322.             sc->compile_args = 0;

  323.             if (ngx_http_script_add_args_code(sc) != NGX_OK) {
  324.                 return NGX_ERROR;
  325.             }

  326.             i++;

  327.             continue;
  328.         }

  329.         name.data = &sc->source->data[i];

  330.         while (i < sc->source->len) {

  331.             if (sc->source->data[i] == '$') {
  332.                 break;
  333.             }

  334.             if (sc->source->data[i] == '?') {

  335.                 sc->args = 1;

  336.                 if (sc->compile_args) {
  337.                     break;
  338.                 }
  339.             }

  340.             i++;
  341.             name.len++;
  342.         }

  343.         sc->size += name.len;

  344.         if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len))
  345.             != NGX_OK)
  346.         {
  347.             return NGX_ERROR;
  348.         }
  349.     }

  350.     return ngx_http_script_done(sc);

  351. invalid_variable:

  352.     ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");

  353.     return NGX_ERROR;
  354. }


  355. u_char *
  356. ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,
  357.     void *code_lengths, size_t len, void *code_values)
  358. {
  359.     ngx_uint_t                    i;
  360.     ngx_http_script_code_pt       code;
  361.     ngx_http_script_len_code_pt   lcode;
  362.     ngx_http_script_engine_t      e;
  363.     ngx_http_core_main_conf_t    *cmcf;

  364.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  365.     for (i = 0; i < cmcf->variables.nelts; i++) {
  366.         if (r->variables[i].no_cacheable) {
  367.             r->variables[i].valid = 0;
  368.             r->variables[i].not_found = 0;
  369.         }
  370.     }

  371.     ngx_memzero(&e, sizeof(ngx_http_script_engine_t));

  372.     e.ip = code_lengths;
  373.     e.request = r;
  374.     e.flushed = 1;

  375.     while (*(uintptr_t *) e.ip) {
  376.         lcode = *(ngx_http_script_len_code_pt *) e.ip;
  377.         len += lcode(&e);
  378.     }


  379.     value->len = len;
  380.     value->data = ngx_pnalloc(r->pool, len);
  381.     if (value->data == NULL) {
  382.         return NULL;
  383.     }

  384.     e.ip = code_values;
  385.     e.pos = value->data;

  386.     while (*(uintptr_t *) e.ip) {
  387.         code = *(ngx_http_script_code_pt *) e.ip;
  388.         code((ngx_http_script_engine_t *) &e);
  389.     }

  390.     return e.pos;
  391. }


  392. void
  393. ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r,
  394.     ngx_array_t *indices)
  395. {
  396.     ngx_uint_t  n, *index;

  397.     if (indices) {
  398.         index = indices->elts;
  399.         for (n = 0; n < indices->nelts; n++) {
  400.             if (r->variables[index[n]].no_cacheable) {
  401.                 r->variables[index[n]].valid = 0;
  402.                 r->variables[index[n]].not_found = 0;
  403.             }
  404.         }
  405.     }
  406. }


  407. static ngx_int_t
  408. ngx_http_script_init_arrays(ngx_http_script_compile_t *sc)
  409. {
  410.     ngx_uint_t   n;

  411.     if (sc->flushes && *sc->flushes == NULL) {
  412.         n = sc->variables ? sc->variables : 1;
  413.         *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t));
  414.         if (*sc->flushes == NULL) {
  415.             return NGX_ERROR;
  416.         }
  417.     }

  418.     if (*sc->lengths == NULL) {
  419.         n = sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
  420.                              + sizeof(ngx_http_script_var_code_t))
  421.             + sizeof(uintptr_t);

  422.         *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
  423.         if (*sc->lengths == NULL) {
  424.             return NGX_ERROR;
  425.         }
  426.     }

  427.     if (*sc->values == NULL) {
  428.         n = (sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
  429.                               + sizeof(ngx_http_script_var_code_t))
  430.                 + sizeof(uintptr_t)
  431.                 + sc->source->len
  432.                 + sizeof(uintptr_t) - 1)
  433.             & ~(sizeof(uintptr_t) - 1);

  434.         *sc->values = ngx_array_create(sc->cf->pool, n, 1);
  435.         if (*sc->values == NULL) {
  436.             return NGX_ERROR;
  437.         }
  438.     }

  439.     sc->variables = 0;

  440.     return NGX_OK;
  441. }


  442. static ngx_int_t
  443. ngx_http_script_done(ngx_http_script_compile_t *sc)
  444. {
  445.     ngx_str_t    zero;
  446.     uintptr_t   *code;

  447.     if (sc->zero) {

  448.         zero.len = 1;
  449.         zero.data = (u_char *) "\0";

  450.         if (ngx_http_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
  451.             return NGX_ERROR;
  452.         }
  453.     }

  454.     if (sc->conf_prefix || sc->root_prefix) {
  455.         if (ngx_http_script_add_full_name_code(sc) != NGX_OK) {
  456.             return NGX_ERROR;
  457.         }
  458.     }

  459.     if (sc->complete_lengths) {
  460.         code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
  461.         if (code == NULL) {
  462.             return NGX_ERROR;
  463.         }

  464.         *code = (uintptr_t) NULL;
  465.     }

  466.     if (sc->complete_values) {
  467.         code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
  468.                                         &sc->main);
  469.         if (code == NULL) {
  470.             return NGX_ERROR;
  471.         }

  472.         *code = (uintptr_t) NULL;
  473.     }

  474.     return NGX_OK;
  475. }


  476. void *
  477. ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
  478. {
  479.     if (*codes == NULL) {
  480.         *codes = ngx_array_create(pool, 256, 1);
  481.         if (*codes == NULL) {
  482.             return NULL;
  483.         }
  484.     }

  485.     return ngx_array_push_n(*codes, size);
  486. }


  487. void *
  488. ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code)
  489. {
  490.     u_char  *elts, **p;
  491.     void    *new;

  492.     elts = codes->elts;

  493.     new = ngx_array_push_n(codes, size);
  494.     if (new == NULL) {
  495.         return NULL;
  496.     }

  497.     if (code) {
  498.         if (elts != codes->elts) {
  499.             p = code;
  500.             *p += (u_char *) codes->elts - elts;
  501.         }
  502.     }

  503.     return new;
  504. }


  505. static ngx_int_t
  506. ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value,
  507.     ngx_uint_t last)
  508. {
  509.     u_char                       *p;
  510.     size_t                        size, len, zero;
  511.     ngx_http_script_copy_code_t  *code;

  512.     zero = (sc->zero && last);
  513.     len = value->len + zero;

  514.     code = ngx_http_script_add_code(*sc->lengths,
  515.                                     sizeof(ngx_http_script_copy_code_t), NULL);
  516.     if (code == NULL) {
  517.         return NGX_ERROR;
  518.     }

  519.     code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
  520.     code->len = len;

  521.     size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
  522.             & ~(sizeof(uintptr_t) - 1);

  523.     code = ngx_http_script_add_code(*sc->values, size, &sc->main);
  524.     if (code == NULL) {
  525.         return NGX_ERROR;
  526.     }

  527.     code->code = ngx_http_script_copy_code;
  528.     code->len = len;

  529.     p = ngx_cpymem((u_char *) code + sizeof(ngx_http_script_copy_code_t),
  530.                    value->data, value->len);

  531.     if (zero) {
  532.         *p = '\0';
  533.         sc->zero = 0;
  534.     }

  535.     return NGX_OK;
  536. }


  537. size_t
  538. ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
  539. {
  540.     ngx_http_script_copy_code_t  *code;

  541.     code = (ngx_http_script_copy_code_t *) e->ip;

  542.     e->ip += sizeof(ngx_http_script_copy_code_t);

  543.     return code->len;
  544. }


  545. void
  546. ngx_http_script_copy_code(ngx_http_script_engine_t *e)
  547. {
  548.     u_char                       *p;
  549.     ngx_http_script_copy_code_t  *code;

  550.     code = (ngx_http_script_copy_code_t *) e->ip;

  551.     p = e->pos;

  552.     if (!e->skip) {
  553.         e->pos = ngx_copy(p, e->ip + sizeof(ngx_http_script_copy_code_t),
  554.                           code->len);
  555.     }

  556.     e->ip += sizeof(ngx_http_script_copy_code_t)
  557.           + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));

  558.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  559.                    "http script copy: \"%*s\"", e->pos - p, p);
  560. }


  561. static ngx_int_t
  562. ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, ngx_str_t *name)
  563. {
  564.     ngx_int_t                    index, *p;
  565.     ngx_http_script_var_code_t  *code;

  566.     index = ngx_http_get_variable_index(sc->cf, name);

  567.     if (index == NGX_ERROR) {
  568.         return NGX_ERROR;
  569.     }

  570.     if (sc->flushes) {
  571.         p = ngx_array_push(*sc->flushes);
  572.         if (p == NULL) {
  573.             return NGX_ERROR;
  574.         }

  575.         *p = index;
  576.     }

  577.     code = ngx_http_script_add_code(*sc->lengths,
  578.                                     sizeof(ngx_http_script_var_code_t), NULL);
  579.     if (code == NULL) {
  580.         return NGX_ERROR;
  581.     }

  582.     code->code = (ngx_http_script_code_pt) ngx_http_script_copy_var_len_code;
  583.     code->index = (uintptr_t) index;

  584.     code = ngx_http_script_add_code(*sc->values,
  585.                                     sizeof(ngx_http_script_var_code_t),
  586.                                     &sc->main);
  587.     if (code == NULL) {
  588.         return NGX_ERROR;
  589.     }

  590.     code->code = ngx_http_script_copy_var_code;
  591.     code->index = (uintptr_t) index;

  592.     return NGX_OK;
  593. }


  594. size_t
  595. ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
  596. {
  597.     ngx_http_variable_value_t   *value;
  598.     ngx_http_script_var_code_t  *code;

  599.     code = (ngx_http_script_var_code_t *) e->ip;

  600.     e->ip += sizeof(ngx_http_script_var_code_t);

  601.     if (e->flushed) {
  602.         value = ngx_http_get_indexed_variable(e->request, code->index);

  603.     } else {
  604.         value = ngx_http_get_flushed_variable(e->request, code->index);
  605.     }

  606.     if (value && !value->not_found) {
  607.         return value->len;
  608.     }

  609.     return 0;
  610. }


  611. void
  612. ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
  613. {
  614.     u_char                      *p;
  615.     ngx_http_variable_value_t   *value;
  616.     ngx_http_script_var_code_t  *code;

  617.     code = (ngx_http_script_var_code_t *) e->ip;

  618.     e->ip += sizeof(ngx_http_script_var_code_t);

  619.     if (!e->skip) {

  620.         if (e->flushed) {
  621.             value = ngx_http_get_indexed_variable(e->request, code->index);

  622.         } else {
  623.             value = ngx_http_get_flushed_variable(e->request, code->index);
  624.         }

  625.         if (value && !value->not_found) {
  626.             p = e->pos;
  627.             e->pos = ngx_copy(p, value->data, value->len);

  628.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP,
  629.                            e->request->connection->log, 0,
  630.                            "http script var: \"%*s\"", e->pos - p, p);
  631.         }
  632.     }
  633. }


  634. static ngx_int_t
  635. ngx_http_script_add_args_code(ngx_http_script_compile_t *sc)
  636. {
  637.     uintptr_t   *code;

  638.     code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
  639.     if (code == NULL) {
  640.         return NGX_ERROR;
  641.     }

  642.     *code = (uintptr_t) ngx_http_script_mark_args_code;

  643.     code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t), &sc->main);
  644.     if (code == NULL) {
  645.         return NGX_ERROR;
  646.     }

  647.     *code = (uintptr_t) ngx_http_script_start_args_code;

  648.     return NGX_OK;
  649. }


  650. size_t
  651. ngx_http_script_mark_args_code(ngx_http_script_engine_t *e)
  652. {
  653.     e->is_args = 1;
  654.     e->ip += sizeof(uintptr_t);

  655.     return 1;
  656. }


  657. void
  658. ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
  659. {
  660.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  661.                    "http script args");

  662.     e->is_args = 1;
  663.     e->args = e->pos;
  664.     e->ip += sizeof(uintptr_t);
  665. }


  666. #if (NGX_PCRE)

  667. void
  668. ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
  669. {
  670.     size_t                         len;
  671.     ngx_int_t                      rc;
  672.     ngx_uint_t                     n;
  673.     ngx_http_request_t            *r;
  674.     ngx_http_script_engine_t       le;
  675.     ngx_http_script_len_code_pt    lcode;
  676.     ngx_http_script_regex_code_t  *code;

  677.     code = (ngx_http_script_regex_code_t *) e->ip;

  678.     r = e->request;

  679.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  680.                    "http script regex: \"%V\"", &code->name);

  681.     if (code->uri) {
  682.         e->line = r->uri;
  683.     } else {
  684.         e->sp--;
  685.         e->line.len = e->sp->len;
  686.         e->line.data = e->sp->data;
  687.     }

  688.     rc = ngx_http_regex_exec(r, code->regex, &e->line);

  689.     if (rc == NGX_DECLINED) {
  690.         if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  691.             ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  692.                           "\"%V\" does not match \"%V\"",
  693.                           &code->name, &e->line);
  694.         }

  695.         r->ncaptures = 0;

  696.         if (code->test) {
  697.             if (code->negative_test) {
  698.                 e->sp->len = 1;
  699.                 e->sp->data = (u_char *) "1";

  700.             } else {
  701.                 e->sp->len = 0;
  702.                 e->sp->data = (u_char *) "";
  703.             }

  704.             e->sp++;

  705.             e->ip += sizeof(ngx_http_script_regex_code_t);
  706.             return;
  707.         }

  708.         e->ip += code->next;
  709.         return;
  710.     }

  711.     if (rc == NGX_ERROR) {
  712.         e->ip = ngx_http_script_exit;
  713.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  714.         return;
  715.     }

  716.     if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  717.         ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  718.                       "\"%V\" matches \"%V\"", &code->name, &e->line);
  719.     }

  720.     if (code->test) {
  721.         if (code->negative_test) {
  722.             e->sp->len = 0;
  723.             e->sp->data = (u_char *) "";

  724.         } else {
  725.             e->sp->len = 1;
  726.             e->sp->data = (u_char *) "1";
  727.         }

  728.         e->sp++;

  729.         e->ip += sizeof(ngx_http_script_regex_code_t);
  730.         return;
  731.     }

  732.     if (code->status) {
  733.         e->status = code->status;

  734.         if (!code->redirect) {
  735.             e->ip = ngx_http_script_exit;
  736.             return;
  737.         }
  738.     }

  739.     if (code->uri) {
  740.         r->internal = 1;
  741.         r->valid_unparsed_uri = 0;

  742.         if (code->break_cycle) {
  743.             r->valid_location = 0;
  744.             r->uri_changed = 0;

  745.         } else {
  746.             r->uri_changed = 1;
  747.         }
  748.     }

  749.     if (code->lengths == NULL) {
  750.         e->buf.len = code->size;

  751.         if (code->uri) {
  752.             if (r->ncaptures && (r->quoted_uri || r->plus_in_uri)) {
  753.                 e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
  754.                                                  NGX_ESCAPE_ARGS);
  755.             }
  756.         }

  757.         for (n = 2; n < r->ncaptures; n += 2) {
  758.             e->buf.len += r->captures[n + 1] - r->captures[n];
  759.         }

  760.     } else {
  761.         ngx_memzero(&le, sizeof(ngx_http_script_engine_t));

  762.         le.ip = code->lengths->elts;
  763.         le.line = e->line;
  764.         le.request = r;
  765.         le.quote = code->redirect;

  766.         len = 0;

  767.         while (*(uintptr_t *) le.ip) {
  768.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  769.             len += lcode(&le);
  770.         }

  771.         e->buf.len = len;
  772.     }

  773.     if (code->add_args && r->args.len) {
  774.         e->buf.len += r->args.len + 1;
  775.     }

  776.     e->buf.data = ngx_pnalloc(r->pool, e->buf.len);
  777.     if (e->buf.data == NULL) {
  778.         e->ip = ngx_http_script_exit;
  779.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  780.         return;
  781.     }

  782.     e->quote = code->redirect;

  783.     e->pos = e->buf.data;

  784.     e->ip += sizeof(ngx_http_script_regex_code_t);
  785. }


  786. void
  787. ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
  788. {
  789.     u_char                            *dst, *src;
  790.     ngx_http_request_t                *r;
  791.     ngx_http_script_regex_end_code_t  *code;

  792.     code = (ngx_http_script_regex_end_code_t *) e->ip;

  793.     r = e->request;

  794.     e->quote = 0;

  795.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  796.                    "http script regex end");

  797.     if (code->redirect) {

  798.         dst = e->buf.data;
  799.         src = e->buf.data;

  800.         ngx_unescape_uri(&dst, &src, e->pos - e->buf.data,
  801.                          NGX_UNESCAPE_REDIRECT);

  802.         if (src < e->pos) {
  803.             dst = ngx_movemem(dst, src, e->pos - src);
  804.         }

  805.         e->pos = dst;

  806.         if (code->add_args && r->args.len) {
  807.             *e->pos++ = (u_char) (code->args ? '&' : '?');
  808.             e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
  809.         }

  810.         e->buf.len = e->pos - e->buf.data;

  811.         if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  812.             ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  813.                           "rewritten redirect: \"%V\"", &e->buf);
  814.         }

  815.         ngx_http_clear_location(r);

  816.         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
  817.         if (r->headers_out.location == NULL) {
  818.             e->ip = ngx_http_script_exit;
  819.             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  820.             return;
  821.         }

  822.         r->headers_out.location->hash = 1;
  823.         ngx_str_set(&r->headers_out.location->key, "Location");
  824.         r->headers_out.location->value = e->buf;

  825.         e->ip += sizeof(ngx_http_script_regex_end_code_t);
  826.         return;
  827.     }

  828.     if (e->args) {
  829.         e->buf.len = e->args - e->buf.data;

  830.         if (code->add_args && r->args.len) {
  831.             *e->pos++ = '&';
  832.             e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
  833.         }

  834.         r->args.len = e->pos - e->args;
  835.         r->args.data = e->args;

  836.         e->args = NULL;

  837.     } else {
  838.         e->buf.len = e->pos - e->buf.data;

  839.         if (!code->add_args) {
  840.             r->args.len = 0;
  841.         }
  842.     }

  843.     if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  844.         ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  845.                       "rewritten data: \"%V\", args: \"%V\"",
  846.                       &e->buf, &r->args);
  847.     }

  848.     if (code->uri) {
  849.         r->uri = e->buf;

  850.         if (r->uri.len == 0) {
  851.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  852.                           "the rewritten URI has a zero length");
  853.             e->ip = ngx_http_script_exit;
  854.             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  855.             return;
  856.         }

  857.         ngx_http_set_exten(r);
  858.     }

  859.     e->ip += sizeof(ngx_http_script_regex_end_code_t);
  860. }


  861. static ngx_int_t
  862. ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, ngx_uint_t n)
  863. {
  864.     ngx_http_script_copy_capture_code_t  *code;

  865.     code = ngx_http_script_add_code(*sc->lengths,
  866.                                     sizeof(ngx_http_script_copy_capture_code_t),
  867.                                     NULL);
  868.     if (code == NULL) {
  869.         return NGX_ERROR;
  870.     }

  871.     code->code = (ngx_http_script_code_pt)
  872.                       ngx_http_script_copy_capture_len_code;
  873.     code->n = 2 * n;


  874.     code = ngx_http_script_add_code(*sc->values,
  875.                                     sizeof(ngx_http_script_copy_capture_code_t),
  876.                                     &sc->main);
  877.     if (code == NULL) {
  878.         return NGX_ERROR;
  879.     }

  880.     code->code = ngx_http_script_copy_capture_code;
  881.     code->n = 2 * n;

  882.     if (sc->ncaptures < n) {
  883.         sc->ncaptures = n;
  884.     }

  885.     return NGX_OK;
  886. }


  887. size_t
  888. ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
  889. {
  890.     int                                  *cap;
  891.     u_char                               *p;
  892.     ngx_uint_t                            n;
  893.     ngx_http_request_t                   *r;
  894.     ngx_http_script_copy_capture_code_t  *code;

  895.     r = e->request;

  896.     code = (ngx_http_script_copy_capture_code_t *) e->ip;

  897.     e->ip += sizeof(ngx_http_script_copy_capture_code_t);

  898.     n = code->n;

  899.     if (n < r->ncaptures) {

  900.         cap = r->captures;

  901.         if ((e->is_args || e->quote)
  902.             && (e->request->quoted_uri || e->request->plus_in_uri))
  903.         {
  904.             p = r->captures_data;

  905.             return cap[n + 1] - cap[n]
  906.                    + 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n],
  907.                                         NGX_ESCAPE_ARGS);
  908.         } else {
  909.             return cap[n + 1] - cap[n];
  910.         }
  911.     }

  912.     return 0;
  913. }


  914. void
  915. ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
  916. {
  917.     int                                  *cap;
  918.     u_char                               *p, *pos;
  919.     ngx_uint_t                            n;
  920.     ngx_http_request_t                   *r;
  921.     ngx_http_script_copy_capture_code_t  *code;

  922.     r = e->request;

  923.     code = (ngx_http_script_copy_capture_code_t *) e->ip;

  924.     e->ip += sizeof(ngx_http_script_copy_capture_code_t);

  925.     n = code->n;

  926.     pos = e->pos;

  927.     if (n < r->ncaptures) {

  928.         cap = r->captures;
  929.         p = r->captures_data;

  930.         if ((e->is_args || e->quote)
  931.             && (e->request->quoted_uri || e->request->plus_in_uri))
  932.         {
  933.             e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
  934.                                                cap[n + 1] - cap[n],
  935.                                                NGX_ESCAPE_ARGS);
  936.         } else {
  937.             e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
  938.         }
  939.     }

  940.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  941.                    "http script capture: \"%*s\"", e->pos - pos, pos);
  942. }

  943. #endif


  944. static ngx_int_t
  945. ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
  946. {
  947.     ngx_http_script_full_name_code_t  *code;

  948.     code = ngx_http_script_add_code(*sc->lengths,
  949.                                     sizeof(ngx_http_script_full_name_code_t),
  950.                                     NULL);
  951.     if (code == NULL) {
  952.         return NGX_ERROR;
  953.     }

  954.     code->code = (ngx_http_script_code_pt) ngx_http_script_full_name_len_code;
  955.     code->conf_prefix = sc->conf_prefix;

  956.     code = ngx_http_script_add_code(*sc->values,
  957.                                     sizeof(ngx_http_script_full_name_code_t),
  958.                                     &sc->main);
  959.     if (code == NULL) {
  960.         return NGX_ERROR;
  961.     }

  962.     code->code = ngx_http_script_full_name_code;
  963.     code->conf_prefix = sc->conf_prefix;

  964.     return NGX_OK;
  965. }


  966. static size_t
  967. ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e)
  968. {
  969.     ngx_http_script_full_name_code_t  *code;

  970.     code = (ngx_http_script_full_name_code_t *) e->ip;

  971.     e->ip += sizeof(ngx_http_script_full_name_code_t);

  972.     return code->conf_prefix ? ngx_cycle->conf_prefix.len:
  973.                                ngx_cycle->prefix.len;
  974. }


  975. static void
  976. ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
  977. {
  978.     ngx_http_script_full_name_code_t  *code;

  979.     ngx_str_t  value, *prefix;

  980.     code = (ngx_http_script_full_name_code_t *) e->ip;

  981.     value.data = e->buf.data;
  982.     value.len = e->pos - e->buf.data;

  983.     prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix:
  984.                                  (ngx_str_t *) &ngx_cycle->prefix;

  985.     if (ngx_get_full_name(e->request->pool, prefix, &value) != NGX_OK) {
  986.         e->ip = ngx_http_script_exit;
  987.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  988.         return;
  989.     }

  990.     e->buf = value;

  991.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  992.                    "http script fullname: \"%V\"", &value);

  993.     e->ip += sizeof(ngx_http_script_full_name_code_t);
  994. }


  995. void
  996. ngx_http_script_return_code(ngx_http_script_engine_t *e)
  997. {
  998.     ngx_http_script_return_code_t  *code;

  999.     code = (ngx_http_script_return_code_t *) e->ip;

  1000.     if (code->status < NGX_HTTP_BAD_REQUEST
  1001.         || code->text.value.len
  1002.         || code->text.lengths)
  1003.     {
  1004.         e->status = ngx_http_send_response(e->request, code->status, NULL,
  1005.                                            &code->text);
  1006.     } else {
  1007.         e->status = code->status;
  1008.     }

  1009.     e->ip = ngx_http_script_exit;
  1010. }


  1011. void
  1012. ngx_http_script_break_code(ngx_http_script_engine_t *e)
  1013. {
  1014.     e->request->uri_changed = 0;

  1015.     e->ip = ngx_http_script_exit;
  1016. }


  1017. void
  1018. ngx_http_script_if_code(ngx_http_script_engine_t *e)
  1019. {
  1020.     ngx_http_script_if_code_t  *code;

  1021.     code = (ngx_http_script_if_code_t *) e->ip;

  1022.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1023.                    "http script if");

  1024.     e->sp--;

  1025.     if (e->sp->len && (e->sp->len != 1 || e->sp->data[0] != '0')) {
  1026.         if (code->loc_conf) {
  1027.             e->request->loc_conf = code->loc_conf;
  1028.             ngx_http_update_location_config(e->request);
  1029.         }

  1030.         e->ip += sizeof(ngx_http_script_if_code_t);
  1031.         return;
  1032.     }

  1033.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1034.                    "http script if: false");

  1035.     e->ip += code->next;
  1036. }


  1037. void
  1038. ngx_http_script_equal_code(ngx_http_script_engine_t *e)
  1039. {
  1040.     ngx_http_variable_value_t  *val, *res;

  1041.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1042.                    "http script equal");

  1043.     e->sp--;
  1044.     val = e->sp;
  1045.     res = e->sp - 1;

  1046.     e->ip += sizeof(uintptr_t);

  1047.     if (val->len == res->len
  1048.         && ngx_strncmp(val->data, res->data, res->len) == 0)
  1049.     {
  1050.         *res = ngx_http_variable_true_value;
  1051.         return;
  1052.     }

  1053.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1054.                    "http script equal: no");

  1055.     *res = ngx_http_variable_null_value;
  1056. }


  1057. void
  1058. ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
  1059. {
  1060.     ngx_http_variable_value_t  *val, *res;

  1061.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1062.                    "http script not equal");

  1063.     e->sp--;
  1064.     val = e->sp;
  1065.     res = e->sp - 1;

  1066.     e->ip += sizeof(uintptr_t);

  1067.     if (val->len == res->len
  1068.         && ngx_strncmp(val->data, res->data, res->len) == 0)
  1069.     {
  1070.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1071.                        "http script not equal: no");

  1072.         *res = ngx_http_variable_null_value;
  1073.         return;
  1074.     }

  1075.     *res = ngx_http_variable_true_value;
  1076. }


  1077. void
  1078. ngx_http_script_file_code(ngx_http_script_engine_t *e)
  1079. {
  1080.     ngx_str_t                     path;
  1081.     ngx_http_request_t           *r;
  1082.     ngx_open_file_info_t          of;
  1083.     ngx_http_core_loc_conf_t     *clcf;
  1084.     ngx_http_variable_value_t    *value;
  1085.     ngx_http_script_file_code_t  *code;

  1086.     value = e->sp - 1;

  1087.     code = (ngx_http_script_file_code_t *) e->ip;
  1088.     e->ip += sizeof(ngx_http_script_file_code_t);

  1089.     path.len = value->len - 1;
  1090.     path.data = value->data;

  1091.     r = e->request;

  1092.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1093.                    "http script file op %p \"%V\"", code->op, &path);

  1094.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1095.     ngx_memzero(&of, sizeof(ngx_open_file_info_t));

  1096.     of.read_ahead = clcf->read_ahead;
  1097.     of.directio = clcf->directio;
  1098.     of.valid = clcf->open_file_cache_valid;
  1099.     of.min_uses = clcf->open_file_cache_min_uses;
  1100.     of.test_only = 1;
  1101.     of.errors = clcf->open_file_cache_errors;
  1102.     of.events = clcf->open_file_cache_events;

  1103.     if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
  1104.         e->ip = ngx_http_script_exit;
  1105.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1106.         return;
  1107.     }

  1108.     if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
  1109.         != NGX_OK)
  1110.     {
  1111.         if (of.err != NGX_ENOENT
  1112.             && of.err != NGX_ENOTDIR
  1113.             && of.err != NGX_ENAMETOOLONG)
  1114.         {
  1115.             ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
  1116.                           "%s \"%s\" failed", of.failed, value->data);
  1117.         }

  1118.         switch (code->op) {

  1119.         case ngx_http_script_file_plain:
  1120.         case ngx_http_script_file_dir:
  1121.         case ngx_http_script_file_exists:
  1122.         case ngx_http_script_file_exec:
  1123.              goto false_value;

  1124.         case ngx_http_script_file_not_plain:
  1125.         case ngx_http_script_file_not_dir:
  1126.         case ngx_http_script_file_not_exists:
  1127.         case ngx_http_script_file_not_exec:
  1128.              goto true_value;
  1129.         }

  1130.         goto false_value;
  1131.     }

  1132.     switch (code->op) {
  1133.     case ngx_http_script_file_plain:
  1134.         if (of.is_file) {
  1135.              goto true_value;
  1136.         }
  1137.         goto false_value;

  1138.     case ngx_http_script_file_not_plain:
  1139.         if (of.is_file) {
  1140.             goto false_value;
  1141.         }
  1142.         goto true_value;

  1143.     case ngx_http_script_file_dir:
  1144.         if (of.is_dir) {
  1145.              goto true_value;
  1146.         }
  1147.         goto false_value;

  1148.     case ngx_http_script_file_not_dir:
  1149.         if (of.is_dir) {
  1150.             goto false_value;
  1151.         }
  1152.         goto true_value;

  1153.     case ngx_http_script_file_exists:
  1154.         if (of.is_file || of.is_dir || of.is_link) {
  1155.              goto true_value;
  1156.         }
  1157.         goto false_value;

  1158.     case ngx_http_script_file_not_exists:
  1159.         if (of.is_file || of.is_dir || of.is_link) {
  1160.             goto false_value;
  1161.         }
  1162.         goto true_value;

  1163.     case ngx_http_script_file_exec:
  1164.         if (of.is_exec) {
  1165.              goto true_value;
  1166.         }
  1167.         goto false_value;

  1168.     case ngx_http_script_file_not_exec:
  1169.         if (of.is_exec) {
  1170.             goto false_value;
  1171.         }
  1172.         goto true_value;
  1173.     }

  1174. false_value:

  1175.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1176.                    "http script file op false");

  1177.     *value = ngx_http_variable_null_value;
  1178.     return;

  1179. true_value:

  1180.     *value = ngx_http_variable_true_value;
  1181.     return;
  1182. }


  1183. void
  1184. ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
  1185. {
  1186.     size_t                                 len;
  1187.     ngx_http_script_engine_t               le;
  1188.     ngx_http_script_len_code_pt            lcode;
  1189.     ngx_http_script_complex_value_code_t  *code;

  1190.     code = (ngx_http_script_complex_value_code_t *) e->ip;

  1191.     e->ip += sizeof(ngx_http_script_complex_value_code_t);

  1192.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1193.                    "http script complex value");

  1194.     ngx_memzero(&le, sizeof(ngx_http_script_engine_t));

  1195.     le.ip = code->lengths->elts;
  1196.     le.line = e->line;
  1197.     le.request = e->request;
  1198.     le.quote = e->quote;

  1199.     for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
  1200.         lcode = *(ngx_http_script_len_code_pt *) le.ip;
  1201.     }

  1202.     e->buf.len = len;
  1203.     e->buf.data = ngx_pnalloc(e->request->pool, len);
  1204.     if (e->buf.data == NULL) {
  1205.         e->ip = ngx_http_script_exit;
  1206.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1207.         return;
  1208.     }

  1209.     e->pos = e->buf.data;

  1210.     e->sp->len = e->buf.len;
  1211.     e->sp->data = e->buf.data;
  1212.     e->sp++;
  1213. }


  1214. void
  1215. ngx_http_script_value_code(ngx_http_script_engine_t *e)
  1216. {
  1217.     ngx_http_script_value_code_t  *code;

  1218.     code = (ngx_http_script_value_code_t *) e->ip;

  1219.     e->ip += sizeof(ngx_http_script_value_code_t);

  1220.     e->sp->len = code->text_len;
  1221.     e->sp->data = (u_char *) code->text_data;

  1222.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1223.                    "http script value: \"%v\"", e->sp);

  1224.     e->sp++;
  1225. }


  1226. void
  1227. ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
  1228. {
  1229.     ngx_http_request_t          *r;
  1230.     ngx_http_script_var_code_t  *code;

  1231.     code = (ngx_http_script_var_code_t *) e->ip;

  1232.     e->ip += sizeof(ngx_http_script_var_code_t);

  1233.     r = e->request;

  1234.     e->sp--;

  1235.     r->variables[code->index].len = e->sp->len;
  1236.     r->variables[code->index].valid = 1;
  1237.     r->variables[code->index].no_cacheable = 0;
  1238.     r->variables[code->index].not_found = 0;
  1239.     r->variables[code->index].data = e->sp->data;

  1240. #if (NGX_DEBUG)
  1241.     {
  1242.     ngx_http_variable_t        *v;
  1243.     ngx_http_core_main_conf_t  *cmcf;

  1244.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  1245.     v = cmcf->variables.elts;

  1246.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1247.                    "http script set $%V", &v[code->index].name);
  1248.     }
  1249. #endif
  1250. }


  1251. void
  1252. ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e)
  1253. {
  1254.     ngx_http_script_var_handler_code_t  *code;

  1255.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1256.                    "http script set var handler");

  1257.     code = (ngx_http_script_var_handler_code_t *) e->ip;

  1258.     e->ip += sizeof(ngx_http_script_var_handler_code_t);

  1259.     e->sp--;

  1260.     code->handler(e->request, e->sp, code->data);
  1261. }


  1262. void
  1263. ngx_http_script_var_code(ngx_http_script_engine_t *e)
  1264. {
  1265.     ngx_http_variable_value_t   *value;
  1266.     ngx_http_script_var_code_t  *code;

  1267.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1268.                    "http script var");

  1269.     code = (ngx_http_script_var_code_t *) e->ip;

  1270.     e->ip += sizeof(ngx_http_script_var_code_t);

  1271.     value = ngx_http_get_flushed_variable(e->request, code->index);

  1272.     if (value && !value->not_found) {
  1273.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1274.                        "http script var: \"%v\"", value);

  1275.         *e->sp = *value;
  1276.         e->sp++;

  1277.         return;
  1278.     }

  1279.     *e->sp = ngx_http_variable_null_value;
  1280.     e->sp++;
  1281. }


  1282. void
  1283. ngx_http_script_nop_code(ngx_http_script_engine_t *e)
  1284. {
  1285.     e->ip += sizeof(uintptr_t);
  1286. }