src/http/ngx_http_script.c - nginx-1.31.3 nginx/ @ 42f8df65b

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. size_t
  79. ngx_http_complex_value_size(ngx_http_request_t *r,
  80.     ngx_http_complex_value_t *val, size_t default_value)
  81. {
  82.     size_t     size;
  83.     ngx_str_t  value;

  84.     if (val == NULL) {
  85.         return default_value;
  86.     }

  87.     if (val->lengths == NULL) {
  88.         return val->u.size;
  89.     }

  90.     if (ngx_http_complex_value(r, val, &value) != NGX_OK) {
  91.         return default_value;
  92.     }

  93.     size = ngx_parse_size(&value);

  94.     if (size == (size_t) NGX_ERROR) {
  95.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  96.                       "invalid size \"%V\"", &value);
  97.         return default_value;
  98.     }

  99.     return size;
  100. }


  101. ngx_int_t
  102. ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
  103. {
  104.     ngx_str_t                  *v;
  105.     ngx_uint_t                  i, n, nv, nc;
  106.     ngx_array_t                 flushes, lengths, values, *pf, *pl, *pv;
  107.     ngx_http_script_compile_t   sc;

  108.     v = ccv->value;

  109.     nv = 0;
  110.     nc = 0;

  111.     for (i = 0; i < v->len; i++) {
  112.         if (v->data[i] == '$') {
  113.             if (i + 1 < v->len
  114.                 && v->data[i + 1] >= '1' && v->data[i + 1] <= '9')
  115.             {
  116.                 nc++;

  117.             } else {
  118.                 nv++;
  119.             }
  120.         }
  121.     }

  122.     if ((v->len == 0 || v->data[0] != '$')
  123.         && (ccv->conf_prefix || ccv->root_prefix))
  124.     {
  125.         if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
  126.             return NGX_ERROR;
  127.         }

  128.         ccv->conf_prefix = 0;
  129.         ccv->root_prefix = 0;
  130.     }

  131.     ccv->complex_value->value = *v;
  132.     ccv->complex_value->flushes = NULL;
  133.     ccv->complex_value->lengths = NULL;
  134.     ccv->complex_value->values = NULL;

  135.     if (nv == 0 && nc == 0) {
  136.         return NGX_OK;
  137.     }

  138.     n = nv + 1;

  139.     if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
  140.         != NGX_OK)
  141.     {
  142.         return NGX_ERROR;
  143.     }

  144.     n = nv * (2 * sizeof(ngx_http_script_copy_code_t)
  145.                   + sizeof(ngx_http_script_var_code_t))
  146.         + sizeof(uintptr_t);

  147.     if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
  148.         return NGX_ERROR;
  149.     }

  150.     n = (nv * (2 * sizeof(ngx_http_script_copy_code_t)
  151.                    + sizeof(ngx_http_script_var_code_t))
  152.                 + sizeof(uintptr_t)
  153.                 + v->len
  154.                 + sizeof(uintptr_t) - 1)
  155.             & ~(sizeof(uintptr_t) - 1);

  156.     if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
  157.         return NGX_ERROR;
  158.     }

  159.     pf = &flushes;
  160.     pl = &lengths;
  161.     pv = &values;

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

  163.     sc.cf = ccv->cf;
  164.     sc.source = v;
  165.     sc.flushes = &pf;
  166.     sc.lengths = &pl;
  167.     sc.values = &pv;
  168.     sc.complete_lengths = 1;
  169.     sc.complete_values = 1;
  170.     sc.zero = ccv->zero;
  171.     sc.conf_prefix = ccv->conf_prefix;
  172.     sc.root_prefix = ccv->root_prefix;

  173.     if (ngx_http_script_compile(&sc) != NGX_OK) {
  174.         return NGX_ERROR;
  175.     }

  176.     if (flushes.nelts) {
  177.         ccv->complex_value->flushes = flushes.elts;
  178.         ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
  179.     }

  180.     ccv->complex_value->lengths = lengths.elts;
  181.     ccv->complex_value->values = values.elts;

  182.     return NGX_OK;
  183. }


  184. char *
  185. ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  186. {
  187.     char  *p = conf;

  188.     ngx_str_t                          *value;
  189.     ngx_http_complex_value_t          **cv;
  190.     ngx_http_compile_complex_value_t    ccv;

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

  192.     if (*cv != NGX_CONF_UNSET_PTR && *cv != NULL) {
  193.         return "is duplicate";
  194.     }

  195.     *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
  196.     if (*cv == NULL) {
  197.         return NGX_CONF_ERROR;
  198.     }

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

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

  201.     ccv.cf = cf;
  202.     ccv.value = &value[1];
  203.     ccv.complex_value = *cv;

  204.     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  205.         return NGX_CONF_ERROR;
  206.     }

  207.     return NGX_CONF_OK;
  208. }


  209. char *
  210. ngx_http_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  211.     void *conf)
  212. {
  213.     char  *p = conf;

  214.     ngx_str_t                          *value;
  215.     ngx_http_complex_value_t          **cv;
  216.     ngx_http_compile_complex_value_t    ccv;

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

  218.     if (*cv != NGX_CONF_UNSET_PTR) {
  219.         return "is duplicate";
  220.     }

  221.     *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
  222.     if (*cv == NULL) {
  223.         return NGX_CONF_ERROR;
  224.     }

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

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

  227.     ccv.cf = cf;
  228.     ccv.value = &value[1];
  229.     ccv.complex_value = *cv;
  230.     ccv.zero = 1;

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

  234.     return NGX_CONF_OK;
  235. }


  236. char *
  237. ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  238.     void *conf)
  239. {
  240.     char  *p = conf;

  241.     char                      *rv;
  242.     ngx_http_complex_value_t  *cv;

  243.     rv = ngx_http_set_complex_value_slot(cf, cmd, conf);

  244.     if (rv != NGX_CONF_OK) {
  245.         return rv;
  246.     }

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

  248.     if (cv->lengths) {
  249.         return NGX_CONF_OK;
  250.     }

  251.     cv->u.size = ngx_parse_size(&cv->value);
  252.     if (cv->u.size == (size_t) NGX_ERROR) {
  253.         return "invalid value";
  254.     }

  255.     return NGX_CONF_OK;
  256. }


  257. ngx_int_t
  258. ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates)
  259. {
  260.     ngx_str_t                  val;
  261.     ngx_uint_t                 i;
  262.     ngx_http_complex_value_t  *cv;

  263.     if (predicates == NULL) {
  264.         return NGX_OK;
  265.     }

  266.     cv = predicates->elts;

  267.     for (i = 0; i < predicates->nelts; i++) {
  268.         if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
  269.             return NGX_ERROR;
  270.         }

  271.         if (val.len && (val.len != 1 || val.data[0] != '0')) {
  272.             return NGX_DECLINED;
  273.         }
  274.     }

  275.     return NGX_OK;
  276. }


  277. ngx_int_t
  278. ngx_http_test_required_predicates(ngx_http_request_t *r,
  279.     ngx_array_t *predicates)
  280. {
  281.     ngx_str_t                  val;
  282.     ngx_uint_t                 i;
  283.     ngx_http_complex_value_t  *cv;

  284.     if (predicates == NULL) {
  285.         return NGX_OK;
  286.     }

  287.     cv = predicates->elts;

  288.     for (i = 0; i < predicates->nelts; i++) {
  289.         if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
  290.             return NGX_ERROR;
  291.         }

  292.         if (val.len == 0 || (val.len == 1 && val.data[0] == '0')) {
  293.             return NGX_DECLINED;
  294.         }
  295.     }

  296.     return NGX_OK;
  297. }


  298. char *
  299. ngx_http_set_predicate_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  300. {
  301.     char  *p = conf;

  302.     ngx_str_t                          *value;
  303.     ngx_uint_t                          i;
  304.     ngx_array_t                       **a;
  305.     ngx_http_complex_value_t           *cv;
  306.     ngx_http_compile_complex_value_t    ccv;

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

  308.     if (*a == NGX_CONF_UNSET_PTR) {
  309.         *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t));
  310.         if (*a == NULL) {
  311.             return NGX_CONF_ERROR;
  312.         }
  313.     }

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

  315.     for (i = 1; i < cf->args->nelts; i++) {
  316.         cv = ngx_array_push(*a);
  317.         if (cv == NULL) {
  318.             return NGX_CONF_ERROR;
  319.         }

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

  321.         ccv.cf = cf;
  322.         ccv.value = &value[i];
  323.         ccv.complex_value = cv;

  324.         if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  325.             return NGX_CONF_ERROR;
  326.         }
  327.     }

  328.     return NGX_CONF_OK;
  329. }


  330. ngx_uint_t
  331. ngx_http_script_variables_count(ngx_str_t *value)
  332. {
  333.     ngx_uint_t  i, n;

  334.     for (n = 0, i = 0; i < value->len; i++) {
  335.         if (value->data[i] == '$') {
  336.             n++;
  337.         }
  338.     }

  339.     return n;
  340. }


  341. ngx_int_t
  342. ngx_http_script_compile(ngx_http_script_compile_t *sc)
  343. {
  344.     u_char       ch;
  345.     ngx_str_t    name;
  346.     ngx_uint_t   i, bracket;

  347.     if (ngx_http_script_init_arrays(sc) != NGX_OK) {
  348.         return NGX_ERROR;
  349.     }

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

  351.         name.len = 0;

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

  353.             if (++i == sc->source->len) {
  354.                 goto invalid_variable;
  355.             }

  356.             if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
  357. #if (NGX_PCRE)
  358.                 ngx_uint_t  n;

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

  360.                 if (sc->captures_mask & ((ngx_uint_t) 1 << n)) {
  361.                     sc->dup_capture = 1;
  362.                 }

  363.                 sc->captures_mask |= (ngx_uint_t) 1 << n;

  364.                 if (ngx_http_script_add_capture_code(sc, n) != NGX_OK) {
  365.                     return NGX_ERROR;
  366.                 }

  367.                 i++;

  368.                 continue;
  369. #else
  370.                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
  371.                                    "using variable \"$%c\" requires "
  372.                                    "PCRE library", sc->source->data[i]);
  373.                 return NGX_ERROR;
  374. #endif
  375.             }

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

  378.                 if (++i == sc->source->len) {
  379.                     goto invalid_variable;
  380.                 }

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

  382.             } else {
  383.                 bracket = 0;
  384.                 name.data = &sc->source->data[i];
  385.             }

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

  388.                 if (ch == '}' && bracket) {
  389.                     i++;
  390.                     bracket = 0;
  391.                     break;
  392.                 }

  393.                 if ((ch >= 'A' && ch <= 'Z')
  394.                     || (ch >= 'a' && ch <= 'z')
  395.                     || (ch >= '0' && ch <= '9')
  396.                     || ch == '_')
  397.                 {
  398.                     continue;
  399.                 }

  400.                 break;
  401.             }

  402.             if (bracket) {
  403.                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
  404.                                    "the closing bracket in \"%V\" "
  405.                                    "variable is missing", &name);
  406.                 return NGX_ERROR;
  407.             }

  408.             if (name.len == 0) {
  409.                 goto invalid_variable;
  410.             }

  411.             sc->variables++;

  412.             if (ngx_http_script_add_var_code(sc, &name) != NGX_OK) {
  413.                 return NGX_ERROR;
  414.             }

  415.             continue;
  416.         }

  417.         if (sc->source->data[i] == '?' && sc->compile_args) {
  418.             sc->args = 1;
  419.             sc->compile_args = 0;

  420.             if (ngx_http_script_add_args_code(sc) != NGX_OK) {
  421.                 return NGX_ERROR;
  422.             }

  423.             i++;

  424.             continue;
  425.         }

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

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

  428.             if (sc->source->data[i] == '$') {
  429.                 break;
  430.             }

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

  432.                 sc->args = 1;

  433.                 if (sc->compile_args) {
  434.                     break;
  435.                 }
  436.             }

  437.             i++;
  438.             name.len++;
  439.         }

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

  441.         if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len))
  442.             != NGX_OK)
  443.         {
  444.             return NGX_ERROR;
  445.         }
  446.     }

  447.     return ngx_http_script_done(sc);

  448. invalid_variable:

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

  450.     return NGX_ERROR;
  451. }


  452. u_char *
  453. ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,
  454.     void *code_lengths, size_t len, void *code_values)
  455. {
  456.     ngx_uint_t                    i;
  457.     ngx_http_script_code_pt       code;
  458.     ngx_http_script_len_code_pt   lcode;
  459.     ngx_http_script_engine_t      e;
  460.     ngx_http_core_main_conf_t    *cmcf;

  461.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  462.     for (i = 0; i < cmcf->variables.nelts; i++) {
  463.         if (r->variables[i].no_cacheable) {
  464.             r->variables[i].valid = 0;
  465.             r->variables[i].not_found = 0;
  466.         }
  467.     }

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

  469.     e.ip = code_lengths;
  470.     e.request = r;
  471.     e.flushed = 1;

  472.     while (*(uintptr_t *) e.ip) {
  473.         lcode = *(ngx_http_script_len_code_pt *) e.ip;
  474.         len += lcode(&e);
  475.     }


  476.     value->len = len;
  477.     value->data = ngx_pnalloc(r->pool, len);
  478.     if (value->data == NULL) {
  479.         return NULL;
  480.     }

  481.     e.ip = code_values;
  482.     e.pos = value->data;

  483.     while (*(uintptr_t *) e.ip) {
  484.         code = *(ngx_http_script_code_pt *) e.ip;
  485.         code((ngx_http_script_engine_t *) &e);
  486.     }

  487.     return e.pos;
  488. }


  489. void
  490. ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r,
  491.     ngx_array_t *indices)
  492. {
  493.     ngx_uint_t  n, *index;

  494.     if (indices) {
  495.         index = indices->elts;
  496.         for (n = 0; n < indices->nelts; n++) {
  497.             if (r->variables[index[n]].no_cacheable) {
  498.                 r->variables[index[n]].valid = 0;
  499.                 r->variables[index[n]].not_found = 0;
  500.             }
  501.         }
  502.     }
  503. }


  504. static ngx_int_t
  505. ngx_http_script_init_arrays(ngx_http_script_compile_t *sc)
  506. {
  507.     ngx_uint_t   n;

  508.     if (sc->flushes && *sc->flushes == NULL) {
  509.         n = sc->variables ? sc->variables : 1;
  510.         *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t));
  511.         if (*sc->flushes == NULL) {
  512.             return NGX_ERROR;
  513.         }
  514.     }

  515.     if (*sc->lengths == NULL) {
  516.         n = sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
  517.                              + sizeof(ngx_http_script_var_code_t))
  518.             + sizeof(uintptr_t);

  519.         *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
  520.         if (*sc->lengths == NULL) {
  521.             return NGX_ERROR;
  522.         }
  523.     }

  524.     if (*sc->values == NULL) {
  525.         n = (sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
  526.                               + sizeof(ngx_http_script_var_code_t))
  527.                 + sizeof(uintptr_t)
  528.                 + sc->source->len
  529.                 + sizeof(uintptr_t) - 1)
  530.             & ~(sizeof(uintptr_t) - 1);

  531.         *sc->values = ngx_array_create(sc->cf->pool, n, 1);
  532.         if (*sc->values == NULL) {
  533.             return NGX_ERROR;
  534.         }
  535.     }

  536.     sc->variables = 0;

  537.     return NGX_OK;
  538. }


  539. static ngx_int_t
  540. ngx_http_script_done(ngx_http_script_compile_t *sc)
  541. {
  542.     ngx_str_t    zero;
  543.     uintptr_t   *code;

  544.     if (sc->zero) {

  545.         zero.len = 1;
  546.         zero.data = (u_char *) "\0";

  547.         if (ngx_http_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
  548.             return NGX_ERROR;
  549.         }
  550.     }

  551.     if (sc->conf_prefix || sc->root_prefix) {
  552.         if (ngx_http_script_add_full_name_code(sc) != NGX_OK) {
  553.             return NGX_ERROR;
  554.         }
  555.     }

  556.     if (sc->complete_lengths) {
  557.         code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
  558.         if (code == NULL) {
  559.             return NGX_ERROR;
  560.         }

  561.         *code = (uintptr_t) NULL;
  562.     }

  563.     if (sc->complete_values) {
  564.         code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
  565.                                         &sc->main);
  566.         if (code == NULL) {
  567.             return NGX_ERROR;
  568.         }

  569.         *code = (uintptr_t) NULL;
  570.     }

  571.     return NGX_OK;
  572. }


  573. void *
  574. ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
  575. {
  576.     if (*codes == NULL) {
  577.         *codes = ngx_array_create(pool, 256, 1);
  578.         if (*codes == NULL) {
  579.             return NULL;
  580.         }
  581.     }

  582.     return ngx_array_push_n(*codes, size);
  583. }


  584. void *
  585. ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code)
  586. {
  587.     u_char  *elts, **p;
  588.     void    *new;

  589.     elts = codes->elts;

  590.     new = ngx_array_push_n(codes, size);
  591.     if (new == NULL) {
  592.         return NULL;
  593.     }

  594.     if (code) {
  595.         if (elts != codes->elts) {
  596.             p = code;
  597.             *p += (u_char *) codes->elts - elts;
  598.         }
  599.     }

  600.     return new;
  601. }


  602. static ngx_int_t
  603. ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value,
  604.     ngx_uint_t last)
  605. {
  606.     u_char                       *p;
  607.     size_t                        size, len, zero;
  608.     ngx_http_script_copy_code_t  *code;

  609.     zero = (sc->zero && last);
  610.     len = value->len + zero;

  611.     code = ngx_http_script_add_code(*sc->lengths,
  612.                                     sizeof(ngx_http_script_copy_code_t), NULL);
  613.     if (code == NULL) {
  614.         return NGX_ERROR;
  615.     }

  616.     code->code = (ngx_http_script_code_pt) (void *)
  617.                                                  ngx_http_script_copy_len_code;
  618.     code->len = len;

  619.     size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
  620.             & ~(sizeof(uintptr_t) - 1);

  621.     code = ngx_http_script_add_code(*sc->values, size, &sc->main);
  622.     if (code == NULL) {
  623.         return NGX_ERROR;
  624.     }

  625.     code->code = ngx_http_script_copy_code;
  626.     code->len = len;

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

  629.     if (zero) {
  630.         *p = '\0';
  631.         sc->zero = 0;
  632.     }

  633.     return NGX_OK;
  634. }


  635. size_t
  636. ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
  637. {
  638.     ngx_http_script_copy_code_t  *code;

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

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

  641.     return code->len;
  642. }


  643. void
  644. ngx_http_script_copy_code(ngx_http_script_engine_t *e)
  645. {
  646.     u_char                       *p;
  647.     ngx_http_script_copy_code_t  *code;

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

  649.     p = e->pos;

  650.     if (!e->skip) {
  651.         e->pos = ngx_copy(p, e->ip + sizeof(ngx_http_script_copy_code_t),
  652.                           code->len);
  653.     }

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

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


  659. static ngx_int_t
  660. ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, ngx_str_t *name)
  661. {
  662.     ngx_int_t                    index, *p;
  663.     ngx_http_script_var_code_t  *code;

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

  665.     if (index == NGX_ERROR) {
  666.         return NGX_ERROR;
  667.     }

  668.     if (sc->flushes) {
  669.         p = ngx_array_push(*sc->flushes);
  670.         if (p == NULL) {
  671.             return NGX_ERROR;
  672.         }

  673.         *p = index;
  674.     }

  675.     code = ngx_http_script_add_code(*sc->lengths,
  676.                                     sizeof(ngx_http_script_var_code_t), NULL);
  677.     if (code == NULL) {
  678.         return NGX_ERROR;
  679.     }

  680.     code->code = (ngx_http_script_code_pt) (void *)
  681.                                              ngx_http_script_copy_var_len_code;
  682.     code->index = (uintptr_t) index;

  683.     code = ngx_http_script_add_code(*sc->values,
  684.                                     sizeof(ngx_http_script_var_code_t),
  685.                                     &sc->main);
  686.     if (code == NULL) {
  687.         return NGX_ERROR;
  688.     }

  689.     code->code = ngx_http_script_copy_var_code;
  690.     code->index = (uintptr_t) index;

  691.     return NGX_OK;
  692. }


  693. size_t
  694. ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
  695. {
  696.     ngx_http_variable_value_t   *value;
  697.     ngx_http_script_var_code_t  *code;

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

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

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

  702.     } else {
  703.         value = ngx_http_get_flushed_variable(e->request, code->index);
  704.     }

  705.     if (value && !value->not_found) {
  706.         return value->len;
  707.     }

  708.     return 0;
  709. }


  710. void
  711. ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
  712. {
  713.     u_char                      *p;
  714.     ngx_http_variable_value_t   *value;
  715.     ngx_http_script_var_code_t  *code;

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

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

  718.     if (!e->skip) {

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

  721.         } else {
  722.             value = ngx_http_get_flushed_variable(e->request, code->index);
  723.         }

  724.         if (value && !value->not_found) {
  725.             p = e->pos;
  726.             e->pos = ngx_copy(p, value->data, value->len);

  727.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP,
  728.                            e->request->connection->log, 0,
  729.                            "http script var: \"%*s\"", e->pos - p, p);
  730.         }
  731.     }
  732. }


  733. static ngx_int_t
  734. ngx_http_script_add_args_code(ngx_http_script_compile_t *sc)
  735. {
  736.     uintptr_t   *code;

  737.     code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
  738.     if (code == NULL) {
  739.         return NGX_ERROR;
  740.     }

  741.     *code = (uintptr_t) ngx_http_script_mark_args_code;

  742.     code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t), &sc->main);
  743.     if (code == NULL) {
  744.         return NGX_ERROR;
  745.     }

  746.     *code = (uintptr_t) ngx_http_script_start_args_code;

  747.     return NGX_OK;
  748. }


  749. size_t
  750. ngx_http_script_mark_args_code(ngx_http_script_engine_t *e)
  751. {
  752.     e->is_args = 1;
  753.     e->ip += sizeof(uintptr_t);

  754.     return 1;
  755. }


  756. void
  757. ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
  758. {
  759.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  760.                    "http script args");

  761.     e->is_args = 1;
  762.     e->args = e->pos;
  763.     e->ip += sizeof(uintptr_t);
  764. }


  765. #if (NGX_PCRE)

  766. void
  767. ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
  768. {
  769.     int                           *cap;
  770.     u_char                        *p;
  771.     size_t                         len;
  772.     ngx_int_t                      rc;
  773.     ngx_uint_t                     n;
  774.     ngx_http_request_t            *r;
  775.     ngx_http_script_engine_t       le;
  776.     ngx_http_script_len_code_pt    lcode;
  777.     ngx_http_script_regex_code_t  *code;

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

  779.     r = e->request;

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

  782.     if (code->uri) {
  783.         e->line = r->uri;
  784.     } else {
  785.         e->sp--;
  786.         e->line.len = e->sp->len;
  787.         e->line.data = e->sp->data;
  788.     }

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

  790.     if (rc == NGX_DECLINED) {
  791.         if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  792.             ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  793.                           "\"%V\" does not match \"%V\"",
  794.                           &code->name, &e->line);
  795.         }

  796.         r->ncaptures = 0;

  797.         if (code->test) {
  798.             if (code->negative_test) {
  799.                 e->sp->len = 1;
  800.                 e->sp->data = (u_char *) "1";

  801.             } else {
  802.                 e->sp->len = 0;
  803.                 e->sp->data = (u_char *) "";
  804.             }

  805.             e->sp++;

  806.             e->ip += sizeof(ngx_http_script_regex_code_t);
  807.             return;
  808.         }

  809.         e->ip += code->next;
  810.         return;
  811.     }

  812.     if (rc == NGX_ERROR) {
  813.         e->ip = ngx_http_script_exit;
  814.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  815.         return;
  816.     }

  817.     if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  818.         ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  819.                       "\"%V\" matches \"%V\"", &code->name, &e->line);
  820.     }

  821.     if (code->test) {
  822.         if (code->negative_test) {
  823.             e->sp->len = 0;
  824.             e->sp->data = (u_char *) "";

  825.         } else {
  826.             e->sp->len = 1;
  827.             e->sp->data = (u_char *) "1";
  828.         }

  829.         e->sp++;

  830.         e->ip += sizeof(ngx_http_script_regex_code_t);
  831.         return;
  832.     }

  833.     if (code->status) {
  834.         e->status = code->status;

  835.         if (!code->redirect) {
  836.             e->ip = ngx_http_script_exit;
  837.             return;
  838.         }
  839.     }

  840.     if (code->uri) {
  841.         r->internal = 1;
  842.         r->valid_unparsed_uri = 0;

  843.         if (code->break_cycle) {
  844.             r->valid_location = 0;
  845.             r->uri_changed = 0;

  846.         } else {
  847.             r->uri_changed = 1;
  848.         }
  849.     }

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

  852.         cap = r->captures;
  853.         p = r->captures_data;

  854.         for (n = 2; n < r->ncaptures; n += 2) {
  855.             e->buf.len += cap[n + 1] - cap[n];

  856.             if (code->uri) {
  857.                 if (r->quoted_uri || r->plus_in_uri) {
  858.                     e->buf.len += 2 * ngx_escape_uri(NULL, &p[cap[n]],
  859.                                                      cap[n + 1] - cap[n],
  860.                                                      NGX_ESCAPE_ARGS);
  861.                 }
  862.             }
  863.         }

  864.     } else {
  865.         ngx_memzero(&le, sizeof(ngx_http_script_engine_t));

  866.         le.ip = code->lengths->elts;
  867.         le.line = e->line;
  868.         le.request = r;
  869.         le.quote = code->redirect;

  870.         len = 0;

  871.         while (*(uintptr_t *) le.ip) {
  872.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  873.             len += lcode(&le);
  874.         }

  875.         e->buf.len = len;
  876.     }

  877.     if (code->add_args && r->args.len) {
  878.         e->buf.len += r->args.len + 1;
  879.     }

  880.     e->buf.data = ngx_pnalloc(r->pool, e->buf.len);
  881.     if (e->buf.data == NULL) {
  882.         e->ip = ngx_http_script_exit;
  883.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  884.         return;
  885.     }

  886.     e->is_args = 0;
  887.     e->quote = code->redirect;

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

  889.     e->ip += sizeof(ngx_http_script_regex_code_t);
  890. }


  891. void
  892. ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
  893. {
  894.     u_char                            *dst, *src;
  895.     ngx_http_request_t                *r;
  896.     ngx_http_script_regex_end_code_t  *code;

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

  898.     r = e->request;

  899.     e->is_args = 0;
  900.     e->quote = 0;

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

  903.     if (code->redirect) {

  904.         dst = e->buf.data;
  905.         src = e->buf.data;

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

  908.         if (src < e->pos) {
  909.             dst = ngx_movemem(dst, src, e->pos - src);
  910.         }

  911.         e->pos = dst;

  912.         if (code->add_args && r->args.len) {
  913.             *e->pos++ = (u_char) (code->args ? '&' : '?');
  914.             e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
  915.         }

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

  917.         if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  918.             ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  919.                           "rewritten redirect: \"%V\"", &e->buf);
  920.         }

  921.         ngx_http_clear_location(r);

  922.         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
  923.         if (r->headers_out.location == NULL) {
  924.             e->ip = ngx_http_script_exit;
  925.             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  926.             return;
  927.         }

  928.         r->headers_out.location->hash = 1;
  929.         r->headers_out.location->next = NULL;
  930.         ngx_str_set(&r->headers_out.location->key, "Location");
  931.         r->headers_out.location->value = e->buf;

  932.         e->ip += sizeof(ngx_http_script_regex_end_code_t);
  933.         return;
  934.     }

  935.     if (e->args) {
  936.         e->buf.len = e->args - e->buf.data;

  937.         if (code->add_args && r->args.len) {
  938.             *e->pos++ = '&';
  939.             e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
  940.         }

  941.         r->args.len = e->pos - e->args;
  942.         r->args.data = e->args;

  943.         e->args = NULL;

  944.     } else {
  945.         e->buf.len = e->pos - e->buf.data;

  946.         if (!code->add_args) {
  947.             r->args.len = 0;
  948.         }
  949.     }

  950.     if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  951.         ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  952.                       "rewritten data: \"%V\", args: \"%V\"",
  953.                       &e->buf, &r->args);
  954.     }

  955.     if (code->uri) {
  956.         r->uri = e->buf;

  957.         if (r->uri.len == 0) {
  958.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  959.                           "the rewritten URI has a zero length");
  960.             e->ip = ngx_http_script_exit;
  961.             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  962.             return;
  963.         }

  964.         ngx_http_set_exten(r);
  965.     }

  966.     e->ip += sizeof(ngx_http_script_regex_end_code_t);
  967. }


  968. static ngx_int_t
  969. ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, ngx_uint_t n)
  970. {
  971.     ngx_http_script_copy_capture_code_t  *code;

  972.     code = ngx_http_script_add_code(*sc->lengths,
  973.                                     sizeof(ngx_http_script_copy_capture_code_t),
  974.                                     NULL);
  975.     if (code == NULL) {
  976.         return NGX_ERROR;
  977.     }

  978.     code->code = (ngx_http_script_code_pt) (void *)
  979.                                          ngx_http_script_copy_capture_len_code;
  980.     code->n = 2 * n;


  981.     code = ngx_http_script_add_code(*sc->values,
  982.                                     sizeof(ngx_http_script_copy_capture_code_t),
  983.                                     &sc->main);
  984.     if (code == NULL) {
  985.         return NGX_ERROR;
  986.     }

  987.     code->code = ngx_http_script_copy_capture_code;
  988.     code->n = 2 * n;

  989.     if (sc->ncaptures < n) {
  990.         sc->ncaptures = n;
  991.     }

  992.     return NGX_OK;
  993. }


  994. size_t
  995. ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
  996. {
  997.     int                                  *cap;
  998.     u_char                               *p;
  999.     ngx_uint_t                            n;
  1000.     ngx_http_request_t                   *r;
  1001.     ngx_http_script_copy_capture_code_t  *code;

  1002.     r = e->request;

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

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

  1005.     n = code->n;

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

  1007.         cap = r->captures;

  1008.         if ((e->is_args || e->quote)
  1009.             && (e->request->quoted_uri || e->request->plus_in_uri))
  1010.         {
  1011.             p = r->captures_data;

  1012.             return cap[n + 1] - cap[n]
  1013.                    + 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n],
  1014.                                         NGX_ESCAPE_ARGS);
  1015.         } else {
  1016.             return cap[n + 1] - cap[n];
  1017.         }
  1018.     }

  1019.     return 0;
  1020. }


  1021. void
  1022. ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
  1023. {
  1024.     int                                  *cap;
  1025.     u_char                               *p, *pos;
  1026.     ngx_uint_t                            n;
  1027.     ngx_http_request_t                   *r;
  1028.     ngx_http_script_copy_capture_code_t  *code;

  1029.     r = e->request;

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

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

  1032.     n = code->n;

  1033.     pos = e->pos;

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

  1035.         cap = r->captures;
  1036.         p = r->captures_data;

  1037.         if ((e->is_args || e->quote)
  1038.             && (e->request->quoted_uri || e->request->plus_in_uri))
  1039.         {
  1040.             e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
  1041.                                                cap[n + 1] - cap[n],
  1042.                                                NGX_ESCAPE_ARGS);
  1043.         } else {
  1044.             e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
  1045.         }
  1046.     }

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

  1050. #endif


  1051. static ngx_int_t
  1052. ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
  1053. {
  1054.     ngx_http_script_full_name_code_t  *code;

  1055.     code = ngx_http_script_add_code(*sc->lengths,
  1056.                                     sizeof(ngx_http_script_full_name_code_t),
  1057.                                     NULL);
  1058.     if (code == NULL) {
  1059.         return NGX_ERROR;
  1060.     }

  1061.     code->code = (ngx_http_script_code_pt) (void *)
  1062.                                             ngx_http_script_full_name_len_code;
  1063.     code->conf_prefix = sc->conf_prefix;

  1064.     code = ngx_http_script_add_code(*sc->values,
  1065.                                     sizeof(ngx_http_script_full_name_code_t),
  1066.                                     &sc->main);
  1067.     if (code == NULL) {
  1068.         return NGX_ERROR;
  1069.     }

  1070.     code->code = ngx_http_script_full_name_code;
  1071.     code->conf_prefix = sc->conf_prefix;

  1072.     return NGX_OK;
  1073. }


  1074. static size_t
  1075. ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e)
  1076. {
  1077.     ngx_http_script_full_name_code_t  *code;

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

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

  1080.     return code->conf_prefix ? ngx_cycle->conf_prefix.len:
  1081.                                ngx_cycle->prefix.len;
  1082. }


  1083. static void
  1084. ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
  1085. {
  1086.     ngx_http_script_full_name_code_t  *code;

  1087.     ngx_str_t  value, *prefix;

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

  1089.     value.data = e->buf.data;
  1090.     value.len = e->pos - e->buf.data;

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

  1093.     if (ngx_get_full_name(e->request->pool, prefix, &value) != NGX_OK) {
  1094.         e->ip = ngx_http_script_exit;
  1095.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1096.         return;
  1097.     }

  1098.     e->buf = value;

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

  1101.     e->ip += sizeof(ngx_http_script_full_name_code_t);
  1102. }


  1103. void
  1104. ngx_http_script_return_code(ngx_http_script_engine_t *e)
  1105. {
  1106.     ngx_http_script_return_code_t  *code;

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

  1108.     if (code->status < NGX_HTTP_BAD_REQUEST
  1109.         || code->text.value.len
  1110.         || code->text.lengths)
  1111.     {
  1112.         e->status = ngx_http_send_response(e->request, code->status, NULL,
  1113.                                            &code->text);
  1114.     } else {
  1115.         e->status = code->status;
  1116.     }

  1117.     e->ip = ngx_http_script_exit;
  1118. }


  1119. void
  1120. ngx_http_script_break_code(ngx_http_script_engine_t *e)
  1121. {
  1122.     ngx_http_request_t  *r;

  1123.     r = e->request;

  1124.     if (r->uri_changed) {
  1125.         r->valid_location = 0;
  1126.         r->uri_changed = 0;
  1127.     }

  1128.     e->ip = ngx_http_script_exit;
  1129. }


  1130. void
  1131. ngx_http_script_if_code(ngx_http_script_engine_t *e)
  1132. {
  1133.     ngx_http_script_if_code_t  *code;

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

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

  1137.     e->sp--;

  1138.     if (e->sp->len && (e->sp->len != 1 || e->sp->data[0] != '0')) {
  1139.         if (code->loc_conf) {
  1140.             e->request->loc_conf = code->loc_conf;
  1141.             ngx_http_update_location_config(e->request);
  1142.         }

  1143.         e->ip += sizeof(ngx_http_script_if_code_t);
  1144.         return;
  1145.     }

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

  1148.     e->ip += code->next;
  1149. }


  1150. void
  1151. ngx_http_script_equal_code(ngx_http_script_engine_t *e)
  1152. {
  1153.     ngx_http_variable_value_t  *val, *res;

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

  1156.     e->sp--;
  1157.     val = e->sp;
  1158.     res = e->sp - 1;

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

  1160.     if (val->len == res->len
  1161.         && ngx_strncmp(val->data, res->data, res->len) == 0)
  1162.     {
  1163.         *res = ngx_http_variable_true_value;
  1164.         return;
  1165.     }

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

  1168.     *res = ngx_http_variable_null_value;
  1169. }


  1170. void
  1171. ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
  1172. {
  1173.     ngx_http_variable_value_t  *val, *res;

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

  1176.     e->sp--;
  1177.     val = e->sp;
  1178.     res = e->sp - 1;

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

  1180.     if (val->len == res->len
  1181.         && ngx_strncmp(val->data, res->data, res->len) == 0)
  1182.     {
  1183.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1184.                        "http script not equal: no");

  1185.         *res = ngx_http_variable_null_value;
  1186.         return;
  1187.     }

  1188.     *res = ngx_http_variable_true_value;
  1189. }


  1190. void
  1191. ngx_http_script_file_code(ngx_http_script_engine_t *e)
  1192. {
  1193.     ngx_str_t                     path;
  1194.     ngx_http_request_t           *r;
  1195.     ngx_open_file_info_t          of;
  1196.     ngx_http_core_loc_conf_t     *clcf;
  1197.     ngx_http_variable_value_t    *value;
  1198.     ngx_http_script_file_code_t  *code;

  1199.     value = e->sp - 1;

  1200.     code = (ngx_http_script_file_code_t *) e->ip;
  1201.     e->ip += sizeof(ngx_http_script_file_code_t);

  1202.     path.len = value->len - 1;
  1203.     path.data = value->data;

  1204.     r = e->request;

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

  1207.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

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

  1209.     of.read_ahead = clcf->read_ahead;
  1210.     of.directio = clcf->directio;
  1211.     of.valid = clcf->open_file_cache_valid;
  1212.     of.min_uses = clcf->open_file_cache_min_uses;
  1213.     of.test_only = 1;
  1214.     of.errors = clcf->open_file_cache_errors;
  1215.     of.events = clcf->open_file_cache_events;

  1216.     if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
  1217.         e->ip = ngx_http_script_exit;
  1218.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1219.         return;
  1220.     }

  1221.     if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
  1222.         != NGX_OK)
  1223.     {
  1224.         if (of.err == 0) {
  1225.             e->ip = ngx_http_script_exit;
  1226.             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1227.             return;
  1228.         }

  1229.         if (of.err != NGX_ENOENT
  1230.             && of.err != NGX_ENOTDIR
  1231.             && of.err != NGX_ENAMETOOLONG)
  1232.         {
  1233.             ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
  1234.                           "%s \"%s\" failed", of.failed, value->data);
  1235.         }

  1236.         switch (code->op) {

  1237.         case ngx_http_script_file_plain:
  1238.         case ngx_http_script_file_dir:
  1239.         case ngx_http_script_file_exists:
  1240.         case ngx_http_script_file_exec:
  1241.              goto false_value;

  1242.         case ngx_http_script_file_not_plain:
  1243.         case ngx_http_script_file_not_dir:
  1244.         case ngx_http_script_file_not_exists:
  1245.         case ngx_http_script_file_not_exec:
  1246.              goto true_value;
  1247.         }

  1248.         goto false_value;
  1249.     }

  1250.     switch (code->op) {
  1251.     case ngx_http_script_file_plain:
  1252.         if (of.is_file) {
  1253.              goto true_value;
  1254.         }
  1255.         goto false_value;

  1256.     case ngx_http_script_file_not_plain:
  1257.         if (of.is_file) {
  1258.             goto false_value;
  1259.         }
  1260.         goto true_value;

  1261.     case ngx_http_script_file_dir:
  1262.         if (of.is_dir) {
  1263.              goto true_value;
  1264.         }
  1265.         goto false_value;

  1266.     case ngx_http_script_file_not_dir:
  1267.         if (of.is_dir) {
  1268.             goto false_value;
  1269.         }
  1270.         goto true_value;

  1271.     case ngx_http_script_file_exists:
  1272.         if (of.is_file || of.is_dir || of.is_link) {
  1273.              goto true_value;
  1274.         }
  1275.         goto false_value;

  1276.     case ngx_http_script_file_not_exists:
  1277.         if (of.is_file || of.is_dir || of.is_link) {
  1278.             goto false_value;
  1279.         }
  1280.         goto true_value;

  1281.     case ngx_http_script_file_exec:
  1282.         if (of.is_exec) {
  1283.              goto true_value;
  1284.         }
  1285.         goto false_value;

  1286.     case ngx_http_script_file_not_exec:
  1287.         if (of.is_exec) {
  1288.             goto false_value;
  1289.         }
  1290.         goto true_value;
  1291.     }

  1292. false_value:

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

  1295.     *value = ngx_http_variable_null_value;
  1296.     return;

  1297. true_value:

  1298.     *value = ngx_http_variable_true_value;
  1299.     return;
  1300. }


  1301. void
  1302. ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
  1303. {
  1304.     size_t                                 len;
  1305.     ngx_http_script_engine_t               le;
  1306.     ngx_http_script_len_code_pt            lcode;
  1307.     ngx_http_script_complex_value_code_t  *code;

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

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

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

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

  1313.     le.ip = code->lengths->elts;
  1314.     le.line = e->line;
  1315.     le.request = e->request;
  1316.     le.is_args = e->is_args;
  1317.     le.quote = e->quote;

  1318.     for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
  1319.         lcode = *(ngx_http_script_len_code_pt *) le.ip;
  1320.     }

  1321.     e->buf.len = len;
  1322.     e->buf.data = ngx_pnalloc(e->request->pool, len);
  1323.     if (e->buf.data == NULL) {
  1324.         e->ip = ngx_http_script_exit;
  1325.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1326.         return;
  1327.     }

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

  1329.     e->sp->len = e->buf.len;
  1330.     e->sp->data = e->buf.data;
  1331.     e->sp++;
  1332. }


  1333. void
  1334. ngx_http_script_value_code(ngx_http_script_engine_t *e)
  1335. {
  1336.     ngx_http_script_value_code_t  *code;

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

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

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

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

  1343.     e->sp++;
  1344. }


  1345. void
  1346. ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
  1347. {
  1348.     ngx_http_request_t          *r;
  1349.     ngx_http_script_var_code_t  *code;

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

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

  1352.     r = e->request;

  1353.     e->sp--;

  1354.     r->variables[code->index].len = e->sp->len;
  1355.     r->variables[code->index].valid = 1;
  1356.     r->variables[code->index].no_cacheable = 0;
  1357.     r->variables[code->index].not_found = 0;
  1358.     r->variables[code->index].data = e->sp->data;

  1359. #if (NGX_DEBUG)
  1360.     {
  1361.     ngx_http_variable_t        *v;
  1362.     ngx_http_core_main_conf_t  *cmcf;

  1363.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  1364.     v = cmcf->variables.elts;

  1365.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1366.                    "http script set $%V", &v[code->index].name);
  1367.     }
  1368. #endif
  1369. }


  1370. void
  1371. ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e)
  1372. {
  1373.     ngx_http_script_var_handler_code_t  *code;

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

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

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

  1378.     e->sp--;

  1379.     code->handler(e->request, e->sp, code->data);
  1380. }


  1381. void
  1382. ngx_http_script_var_code(ngx_http_script_engine_t *e)
  1383. {
  1384.     ngx_http_variable_value_t   *value;
  1385.     ngx_http_script_var_code_t  *code;

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

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

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

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

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

  1394.         *e->sp = *value;
  1395.         e->sp++;

  1396.         return;
  1397.     }

  1398.     *e->sp = ngx_http_variable_null_value;
  1399.     e->sp++;
  1400. }


  1401. void
  1402. ngx_http_script_nop_code(ngx_http_script_engine_t *e)
  1403. {
  1404.     e->ip += sizeof(uintptr_t);
  1405. }