src/http/ngx_http_script.c - nginx source code

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 (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
  114.                 nc++;

  115.             } else {
  116.                 nv++;
  117.             }
  118.         }
  119.     }

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

  126.         ccv->conf_prefix = 0;
  127.         ccv->root_prefix = 0;
  128.     }

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

  133.     if (nv == 0 && nc == 0) {
  134.         return NGX_OK;
  135.     }

  136.     n = nv + 1;

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

  142.     n = nv * (2 * sizeof(ngx_http_script_copy_code_t)
  143.                   + sizeof(ngx_http_script_var_code_t))
  144.         + sizeof(uintptr_t);

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

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

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

  157.     pf = &flushes;
  158.     pl = &lengths;
  159.     pv = &values;

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

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

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

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

  178.     ccv->complex_value->lengths = lengths.elts;
  179.     ccv->complex_value->values = values.elts;

  180.     return NGX_OK;
  181. }


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

  186.     ngx_str_t                          *value;
  187.     ngx_http_complex_value_t          **cv;
  188.     ngx_http_compile_complex_value_t    ccv;

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

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

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

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

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

  199.     ccv.cf = cf;
  200.     ccv.value = &value[1];
  201.     ccv.complex_value = *cv;

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

  205.     return NGX_CONF_OK;
  206. }


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

  212.     ngx_str_t                          *value;
  213.     ngx_http_complex_value_t          **cv;
  214.     ngx_http_compile_complex_value_t    ccv;

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

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

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

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

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

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

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

  232.     return NGX_CONF_OK;
  233. }


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

  239.     char                      *rv;
  240.     ngx_http_complex_value_t  *cv;

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

  242.     if (rv != NGX_CONF_OK) {
  243.         return rv;
  244.     }

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

  246.     if (cv->lengths) {
  247.         return NGX_CONF_OK;
  248.     }

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

  253.     return NGX_CONF_OK;
  254. }


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

  261.     if (predicates == NULL) {
  262.         return NGX_OK;
  263.     }

  264.     cv = predicates->elts;

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

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

  273.     return NGX_OK;
  274. }


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

  282.     if (predicates == NULL) {
  283.         return NGX_OK;
  284.     }

  285.     cv = predicates->elts;

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

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

  294.     return NGX_OK;
  295. }


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

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

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

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

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

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

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

  319.         ccv.cf = cf;
  320.         ccv.value = &value[i];
  321.         ccv.complex_value = cv;

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

  326.     return NGX_CONF_OK;
  327. }


  328. ngx_uint_t
  329. ngx_http_script_variables_count(ngx_str_t *value)
  330. {
  331.     ngx_uint_t  i, n;

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

  337.     return n;
  338. }


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

  345.     if (ngx_http_script_init_arrays(sc) != NGX_OK) {
  346.         return NGX_ERROR;
  347.     }

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

  349.         name.len = 0;

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

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

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

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

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

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

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

  365.                 i++;

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

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

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

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

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

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

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

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

  398.                 break;
  399.             }

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

  406.             if (name.len == 0) {
  407.                 goto invalid_variable;
  408.             }

  409.             sc->variables++;

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

  413.             continue;
  414.         }

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

  418.             if (ngx_http_script_add_args_code(sc) != NGX_OK) {
  419.                 return NGX_ERROR;
  420.             }

  421.             i++;

  422.             continue;
  423.         }

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

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

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

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

  430.                 sc->args = 1;

  431.                 if (sc->compile_args) {
  432.                     break;
  433.                 }
  434.             }

  435.             i++;
  436.             name.len++;
  437.         }

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

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

  445.     return ngx_http_script_done(sc);

  446. invalid_variable:

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

  448.     return NGX_ERROR;
  449. }


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

  459.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

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

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

  467.     e.ip = code_lengths;
  468.     e.request = r;
  469.     e.flushed = 1;

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


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

  479.     e.ip = code_values;
  480.     e.pos = value->data;

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

  485.     return e.pos;
  486. }


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

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


  502. static ngx_int_t
  503. ngx_http_script_init_arrays(ngx_http_script_compile_t *sc)
  504. {
  505.     ngx_uint_t   n;

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

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

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

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

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

  534.     sc->variables = 0;

  535.     return NGX_OK;
  536. }


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

  542.     if (sc->zero) {

  543.         zero.len = 1;
  544.         zero.data = (u_char *) "\0";

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

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

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

  559.         *code = (uintptr_t) NULL;
  560.     }

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

  567.         *code = (uintptr_t) NULL;
  568.     }

  569.     return NGX_OK;
  570. }


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

  580.     return ngx_array_push_n(*codes, size);
  581. }


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

  587.     elts = codes->elts;

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

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

  598.     return new;
  599. }


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

  607.     zero = (sc->zero && last);
  608.     len = value->len + zero;

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

  614.     code->code = (ngx_http_script_code_pt) (void *)
  615.                                                  ngx_http_script_copy_len_code;
  616.     code->len = len;

  617.     size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
  618.             & ~(sizeof(uintptr_t) - 1);

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

  623.     code->code = ngx_http_script_copy_code;
  624.     code->len = len;

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

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

  631.     return NGX_OK;
  632. }


  633. size_t
  634. ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
  635. {
  636.     ngx_http_script_copy_code_t  *code;

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

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

  639.     return code->len;
  640. }


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

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

  647.     p = e->pos;

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

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

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


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

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

  663.     if (index == NGX_ERROR) {
  664.         return NGX_ERROR;
  665.     }

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

  671.         *p = index;
  672.     }

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

  678.     code->code = (ngx_http_script_code_pt) (void *)
  679.                                              ngx_http_script_copy_var_len_code;
  680.     code->index = (uintptr_t) index;

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

  687.     code->code = ngx_http_script_copy_var_code;
  688.     code->index = (uintptr_t) index;

  689.     return NGX_OK;
  690. }


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

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

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

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

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

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

  706.     return 0;
  707. }


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

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

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

  716.     if (!e->skip) {

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

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

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

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


  731. static ngx_int_t
  732. ngx_http_script_add_args_code(ngx_http_script_compile_t *sc)
  733. {
  734.     uintptr_t   *code;

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

  739.     *code = (uintptr_t) ngx_http_script_mark_args_code;

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

  744.     *code = (uintptr_t) ngx_http_script_start_args_code;

  745.     return NGX_OK;
  746. }


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

  752.     return 1;
  753. }


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

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


  763. #if (NGX_PCRE)

  764. void
  765. ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
  766. {
  767.     size_t                         len;
  768.     ngx_int_t                      rc;
  769.     ngx_uint_t                     n;
  770.     ngx_http_request_t            *r;
  771.     ngx_http_script_engine_t       le;
  772.     ngx_http_script_len_code_pt    lcode;
  773.     ngx_http_script_regex_code_t  *code;

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

  775.     r = e->request;

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

  778.     if (code->uri) {
  779.         e->line = r->uri;
  780.     } else {
  781.         e->sp--;
  782.         e->line.len = e->sp->len;
  783.         e->line.data = e->sp->data;
  784.     }

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

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

  792.         r->ncaptures = 0;

  793.         if (code->test) {
  794.             if (code->negative_test) {
  795.                 e->sp->len = 1;
  796.                 e->sp->data = (u_char *) "1";

  797.             } else {
  798.                 e->sp->len = 0;
  799.                 e->sp->data = (u_char *) "";
  800.             }

  801.             e->sp++;

  802.             e->ip += sizeof(ngx_http_script_regex_code_t);
  803.             return;
  804.         }

  805.         e->ip += code->next;
  806.         return;
  807.     }

  808.     if (rc == NGX_ERROR) {
  809.         e->ip = ngx_http_script_exit;
  810.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  811.         return;
  812.     }

  813.     if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  814.         ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  815.                       "\"%V\" matches \"%V\"", &code->name, &e->line);
  816.     }

  817.     if (code->test) {
  818.         if (code->negative_test) {
  819.             e->sp->len = 0;
  820.             e->sp->data = (u_char *) "";

  821.         } else {
  822.             e->sp->len = 1;
  823.             e->sp->data = (u_char *) "1";
  824.         }

  825.         e->sp++;

  826.         e->ip += sizeof(ngx_http_script_regex_code_t);
  827.         return;
  828.     }

  829.     if (code->status) {
  830.         e->status = code->status;

  831.         if (!code->redirect) {
  832.             e->ip = ngx_http_script_exit;
  833.             return;
  834.         }
  835.     }

  836.     if (code->uri) {
  837.         r->internal = 1;
  838.         r->valid_unparsed_uri = 0;

  839.         if (code->break_cycle) {
  840.             r->valid_location = 0;
  841.             r->uri_changed = 0;

  842.         } else {
  843.             r->uri_changed = 1;
  844.         }
  845.     }

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

  848.         if (code->uri) {
  849.             if (r->ncaptures && (r->quoted_uri || r->plus_in_uri)) {
  850.                 e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
  851.                                                  NGX_ESCAPE_ARGS);
  852.             }
  853.         }

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

  857.     } else {
  858.         ngx_memzero(&le, sizeof(ngx_http_script_engine_t));

  859.         le.ip = code->lengths->elts;
  860.         le.line = e->line;
  861.         le.request = r;
  862.         le.quote = code->redirect;

  863.         len = 0;

  864.         while (*(uintptr_t *) le.ip) {
  865.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  866.             len += lcode(&le);
  867.         }

  868.         e->buf.len = len;
  869.     }

  870.     if (code->add_args && r->args.len) {
  871.         e->buf.len += r->args.len + 1;
  872.     }

  873.     e->buf.data = ngx_pnalloc(r->pool, e->buf.len);
  874.     if (e->buf.data == NULL) {
  875.         e->ip = ngx_http_script_exit;
  876.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  877.         return;
  878.     }

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

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

  881.     e->ip += sizeof(ngx_http_script_regex_code_t);
  882. }


  883. void
  884. ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
  885. {
  886.     u_char                            *dst, *src;
  887.     ngx_http_request_t                *r;
  888.     ngx_http_script_regex_end_code_t  *code;

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

  890.     r = e->request;

  891.     e->quote = 0;

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

  894.     if (code->redirect) {

  895.         dst = e->buf.data;
  896.         src = e->buf.data;

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

  899.         if (src < e->pos) {
  900.             dst = ngx_movemem(dst, src, e->pos - src);
  901.         }

  902.         e->pos = dst;

  903.         if (code->add_args && r->args.len) {
  904.             *e->pos++ = (u_char) (code->args ? '&' : '?');
  905.             e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
  906.         }

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

  908.         if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  909.             ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  910.                           "rewritten redirect: \"%V\"", &e->buf);
  911.         }

  912.         ngx_http_clear_location(r);

  913.         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
  914.         if (r->headers_out.location == NULL) {
  915.             e->ip = ngx_http_script_exit;
  916.             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  917.             return;
  918.         }

  919.         r->headers_out.location->hash = 1;
  920.         r->headers_out.location->next = NULL;
  921.         ngx_str_set(&r->headers_out.location->key, "Location");
  922.         r->headers_out.location->value = e->buf;

  923.         e->ip += sizeof(ngx_http_script_regex_end_code_t);
  924.         return;
  925.     }

  926.     if (e->args) {
  927.         e->buf.len = e->args - e->buf.data;

  928.         if (code->add_args && r->args.len) {
  929.             *e->pos++ = '&';
  930.             e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
  931.         }

  932.         r->args.len = e->pos - e->args;
  933.         r->args.data = e->args;

  934.         e->args = NULL;

  935.     } else {
  936.         e->buf.len = e->pos - e->buf.data;

  937.         if (!code->add_args) {
  938.             r->args.len = 0;
  939.         }
  940.     }

  941.     if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  942.         ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  943.                       "rewritten data: \"%V\", args: \"%V\"",
  944.                       &e->buf, &r->args);
  945.     }

  946.     if (code->uri) {
  947.         r->uri = e->buf;

  948.         if (r->uri.len == 0) {
  949.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  950.                           "the rewritten URI has a zero length");
  951.             e->ip = ngx_http_script_exit;
  952.             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  953.             return;
  954.         }

  955.         ngx_http_set_exten(r);
  956.     }

  957.     e->ip += sizeof(ngx_http_script_regex_end_code_t);
  958. }


  959. static ngx_int_t
  960. ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, ngx_uint_t n)
  961. {
  962.     ngx_http_script_copy_capture_code_t  *code;

  963.     code = ngx_http_script_add_code(*sc->lengths,
  964.                                     sizeof(ngx_http_script_copy_capture_code_t),
  965.                                     NULL);
  966.     if (code == NULL) {
  967.         return NGX_ERROR;
  968.     }

  969.     code->code = (ngx_http_script_code_pt) (void *)
  970.                                          ngx_http_script_copy_capture_len_code;
  971.     code->n = 2 * n;


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

  978.     code->code = ngx_http_script_copy_capture_code;
  979.     code->n = 2 * n;

  980.     if (sc->ncaptures < n) {
  981.         sc->ncaptures = n;
  982.     }

  983.     return NGX_OK;
  984. }


  985. size_t
  986. ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
  987. {
  988.     int                                  *cap;
  989.     u_char                               *p;
  990.     ngx_uint_t                            n;
  991.     ngx_http_request_t                   *r;
  992.     ngx_http_script_copy_capture_code_t  *code;

  993.     r = e->request;

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

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

  996.     n = code->n;

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

  998.         cap = r->captures;

  999.         if ((e->is_args || e->quote)
  1000.             && (e->request->quoted_uri || e->request->plus_in_uri))
  1001.         {
  1002.             p = r->captures_data;

  1003.             return cap[n + 1] - cap[n]
  1004.                    + 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n],
  1005.                                         NGX_ESCAPE_ARGS);
  1006.         } else {
  1007.             return cap[n + 1] - cap[n];
  1008.         }
  1009.     }

  1010.     return 0;
  1011. }


  1012. void
  1013. ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
  1014. {
  1015.     int                                  *cap;
  1016.     u_char                               *p, *pos;
  1017.     ngx_uint_t                            n;
  1018.     ngx_http_request_t                   *r;
  1019.     ngx_http_script_copy_capture_code_t  *code;

  1020.     r = e->request;

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

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

  1023.     n = code->n;

  1024.     pos = e->pos;

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

  1026.         cap = r->captures;
  1027.         p = r->captures_data;

  1028.         if ((e->is_args || e->quote)
  1029.             && (e->request->quoted_uri || e->request->plus_in_uri))
  1030.         {
  1031.             e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
  1032.                                                cap[n + 1] - cap[n],
  1033.                                                NGX_ESCAPE_ARGS);
  1034.         } else {
  1035.             e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
  1036.         }
  1037.     }

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

  1041. #endif


  1042. static ngx_int_t
  1043. ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
  1044. {
  1045.     ngx_http_script_full_name_code_t  *code;

  1046.     code = ngx_http_script_add_code(*sc->lengths,
  1047.                                     sizeof(ngx_http_script_full_name_code_t),
  1048.                                     NULL);
  1049.     if (code == NULL) {
  1050.         return NGX_ERROR;
  1051.     }

  1052.     code->code = (ngx_http_script_code_pt) (void *)
  1053.                                             ngx_http_script_full_name_len_code;
  1054.     code->conf_prefix = sc->conf_prefix;

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

  1061.     code->code = ngx_http_script_full_name_code;
  1062.     code->conf_prefix = sc->conf_prefix;

  1063.     return NGX_OK;
  1064. }


  1065. static size_t
  1066. ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e)
  1067. {
  1068.     ngx_http_script_full_name_code_t  *code;

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

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

  1071.     return code->conf_prefix ? ngx_cycle->conf_prefix.len:
  1072.                                ngx_cycle->prefix.len;
  1073. }


  1074. static void
  1075. ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
  1076. {
  1077.     ngx_http_script_full_name_code_t  *code;

  1078.     ngx_str_t  value, *prefix;

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

  1080.     value.data = e->buf.data;
  1081.     value.len = e->pos - e->buf.data;

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

  1084.     if (ngx_get_full_name(e->request->pool, prefix, &value) != NGX_OK) {
  1085.         e->ip = ngx_http_script_exit;
  1086.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1087.         return;
  1088.     }

  1089.     e->buf = value;

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

  1092.     e->ip += sizeof(ngx_http_script_full_name_code_t);
  1093. }


  1094. void
  1095. ngx_http_script_return_code(ngx_http_script_engine_t *e)
  1096. {
  1097.     ngx_http_script_return_code_t  *code;

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

  1099.     if (code->status < NGX_HTTP_BAD_REQUEST
  1100.         || code->text.value.len
  1101.         || code->text.lengths)
  1102.     {
  1103.         e->status = ngx_http_send_response(e->request, code->status, NULL,
  1104.                                            &code->text);
  1105.     } else {
  1106.         e->status = code->status;
  1107.     }

  1108.     e->ip = ngx_http_script_exit;
  1109. }


  1110. void
  1111. ngx_http_script_break_code(ngx_http_script_engine_t *e)
  1112. {
  1113.     ngx_http_request_t  *r;

  1114.     r = e->request;

  1115.     if (r->uri_changed) {
  1116.         r->valid_location = 0;
  1117.         r->uri_changed = 0;
  1118.     }

  1119.     e->ip = ngx_http_script_exit;
  1120. }


  1121. void
  1122. ngx_http_script_if_code(ngx_http_script_engine_t *e)
  1123. {
  1124.     ngx_http_script_if_code_t  *code;

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

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

  1128.     e->sp--;

  1129.     if (e->sp->len && (e->sp->len != 1 || e->sp->data[0] != '0')) {
  1130.         if (code->loc_conf) {
  1131.             e->request->loc_conf = code->loc_conf;
  1132.             ngx_http_update_location_config(e->request);
  1133.         }

  1134.         e->ip += sizeof(ngx_http_script_if_code_t);
  1135.         return;
  1136.     }

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

  1139.     e->ip += code->next;
  1140. }


  1141. void
  1142. ngx_http_script_equal_code(ngx_http_script_engine_t *e)
  1143. {
  1144.     ngx_http_variable_value_t  *val, *res;

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

  1147.     e->sp--;
  1148.     val = e->sp;
  1149.     res = e->sp - 1;

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

  1151.     if (val->len == res->len
  1152.         && ngx_strncmp(val->data, res->data, res->len) == 0)
  1153.     {
  1154.         *res = ngx_http_variable_true_value;
  1155.         return;
  1156.     }

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

  1159.     *res = ngx_http_variable_null_value;
  1160. }


  1161. void
  1162. ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
  1163. {
  1164.     ngx_http_variable_value_t  *val, *res;

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

  1167.     e->sp--;
  1168.     val = e->sp;
  1169.     res = e->sp - 1;

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

  1171.     if (val->len == res->len
  1172.         && ngx_strncmp(val->data, res->data, res->len) == 0)
  1173.     {
  1174.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1175.                        "http script not equal: no");

  1176.         *res = ngx_http_variable_null_value;
  1177.         return;
  1178.     }

  1179.     *res = ngx_http_variable_true_value;
  1180. }


  1181. void
  1182. ngx_http_script_file_code(ngx_http_script_engine_t *e)
  1183. {
  1184.     ngx_str_t                     path;
  1185.     ngx_http_request_t           *r;
  1186.     ngx_open_file_info_t          of;
  1187.     ngx_http_core_loc_conf_t     *clcf;
  1188.     ngx_http_variable_value_t    *value;
  1189.     ngx_http_script_file_code_t  *code;

  1190.     value = e->sp - 1;

  1191.     code = (ngx_http_script_file_code_t *) e->ip;
  1192.     e->ip += sizeof(ngx_http_script_file_code_t);

  1193.     path.len = value->len - 1;
  1194.     path.data = value->data;

  1195.     r = e->request;

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

  1198.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

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

  1200.     of.read_ahead = clcf->read_ahead;
  1201.     of.directio = clcf->directio;
  1202.     of.valid = clcf->open_file_cache_valid;
  1203.     of.min_uses = clcf->open_file_cache_min_uses;
  1204.     of.test_only = 1;
  1205.     of.errors = clcf->open_file_cache_errors;
  1206.     of.events = clcf->open_file_cache_events;

  1207.     if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
  1208.         e->ip = ngx_http_script_exit;
  1209.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1210.         return;
  1211.     }

  1212.     if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
  1213.         != NGX_OK)
  1214.     {
  1215.         if (of.err == 0) {
  1216.             e->ip = ngx_http_script_exit;
  1217.             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1218.             return;
  1219.         }

  1220.         if (of.err != NGX_ENOENT
  1221.             && of.err != NGX_ENOTDIR
  1222.             && of.err != NGX_ENAMETOOLONG)
  1223.         {
  1224.             ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
  1225.                           "%s \"%s\" failed", of.failed, value->data);
  1226.         }

  1227.         switch (code->op) {

  1228.         case ngx_http_script_file_plain:
  1229.         case ngx_http_script_file_dir:
  1230.         case ngx_http_script_file_exists:
  1231.         case ngx_http_script_file_exec:
  1232.              goto false_value;

  1233.         case ngx_http_script_file_not_plain:
  1234.         case ngx_http_script_file_not_dir:
  1235.         case ngx_http_script_file_not_exists:
  1236.         case ngx_http_script_file_not_exec:
  1237.              goto true_value;
  1238.         }

  1239.         goto false_value;
  1240.     }

  1241.     switch (code->op) {
  1242.     case ngx_http_script_file_plain:
  1243.         if (of.is_file) {
  1244.              goto true_value;
  1245.         }
  1246.         goto false_value;

  1247.     case ngx_http_script_file_not_plain:
  1248.         if (of.is_file) {
  1249.             goto false_value;
  1250.         }
  1251.         goto true_value;

  1252.     case ngx_http_script_file_dir:
  1253.         if (of.is_dir) {
  1254.              goto true_value;
  1255.         }
  1256.         goto false_value;

  1257.     case ngx_http_script_file_not_dir:
  1258.         if (of.is_dir) {
  1259.             goto false_value;
  1260.         }
  1261.         goto true_value;

  1262.     case ngx_http_script_file_exists:
  1263.         if (of.is_file || of.is_dir || of.is_link) {
  1264.              goto true_value;
  1265.         }
  1266.         goto false_value;

  1267.     case ngx_http_script_file_not_exists:
  1268.         if (of.is_file || of.is_dir || of.is_link) {
  1269.             goto false_value;
  1270.         }
  1271.         goto true_value;

  1272.     case ngx_http_script_file_exec:
  1273.         if (of.is_exec) {
  1274.              goto true_value;
  1275.         }
  1276.         goto false_value;

  1277.     case ngx_http_script_file_not_exec:
  1278.         if (of.is_exec) {
  1279.             goto false_value;
  1280.         }
  1281.         goto true_value;
  1282.     }

  1283. false_value:

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

  1286.     *value = ngx_http_variable_null_value;
  1287.     return;

  1288. true_value:

  1289.     *value = ngx_http_variable_true_value;
  1290.     return;
  1291. }


  1292. void
  1293. ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
  1294. {
  1295.     size_t                                 len;
  1296.     ngx_http_script_engine_t               le;
  1297.     ngx_http_script_len_code_pt            lcode;
  1298.     ngx_http_script_complex_value_code_t  *code;

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

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

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

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

  1304.     le.ip = code->lengths->elts;
  1305.     le.line = e->line;
  1306.     le.request = e->request;
  1307.     le.quote = e->quote;

  1308.     for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
  1309.         lcode = *(ngx_http_script_len_code_pt *) le.ip;
  1310.     }

  1311.     e->buf.len = len;
  1312.     e->buf.data = ngx_pnalloc(e->request->pool, len);
  1313.     if (e->buf.data == NULL) {
  1314.         e->ip = ngx_http_script_exit;
  1315.         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1316.         return;
  1317.     }

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

  1319.     e->sp->len = e->buf.len;
  1320.     e->sp->data = e->buf.data;
  1321.     e->sp++;
  1322. }


  1323. void
  1324. ngx_http_script_value_code(ngx_http_script_engine_t *e)
  1325. {
  1326.     ngx_http_script_value_code_t  *code;

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

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

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

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

  1333.     e->sp++;
  1334. }


  1335. void
  1336. ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
  1337. {
  1338.     ngx_http_request_t          *r;
  1339.     ngx_http_script_var_code_t  *code;

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

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

  1342.     r = e->request;

  1343.     e->sp--;

  1344.     r->variables[code->index].len = e->sp->len;
  1345.     r->variables[code->index].valid = 1;
  1346.     r->variables[code->index].no_cacheable = 0;
  1347.     r->variables[code->index].not_found = 0;
  1348.     r->variables[code->index].data = e->sp->data;

  1349. #if (NGX_DEBUG)
  1350.     {
  1351.     ngx_http_variable_t        *v;
  1352.     ngx_http_core_main_conf_t  *cmcf;

  1353.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  1354.     v = cmcf->variables.elts;

  1355.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1356.                    "http script set $%V", &v[code->index].name);
  1357.     }
  1358. #endif
  1359. }


  1360. void
  1361. ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e)
  1362. {
  1363.     ngx_http_script_var_handler_code_t  *code;

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

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

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

  1368.     e->sp--;

  1369.     code->handler(e->request, e->sp, code->data);
  1370. }


  1371. void
  1372. ngx_http_script_var_code(ngx_http_script_engine_t *e)
  1373. {
  1374.     ngx_http_variable_value_t   *value;
  1375.     ngx_http_script_var_code_t  *code;

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

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

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

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

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

  1384.         *e->sp = *value;
  1385.         e->sp++;

  1386.         return;
  1387.     }

  1388.     *e->sp = ngx_http_variable_null_value;
  1389.     e->sp++;
  1390. }


  1391. void
  1392. ngx_http_script_nop_code(ngx_http_script_engine_t *e)
  1393. {
  1394.     e->ip += sizeof(uintptr_t);
  1395. }