Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_http.h>
0011 
0012 
0013 static ngx_int_t ngx_http_script_init_arrays(ngx_http_script_compile_t *sc);
0014 static ngx_int_t ngx_http_script_done(ngx_http_script_compile_t *sc);
0015 static ngx_int_t ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc,
0016     ngx_str_t *value, ngx_uint_t last);
0017 static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc,
0018     ngx_str_t *name);
0019 static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc);
0020 #if (NGX_PCRE)
0021 static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc,
0022     ngx_uint_t n);
0023 #endif
0024 static ngx_int_t
0025     ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc);
0026 static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e);
0027 static void ngx_http_script_full_name_code(ngx_http_script_engine_t *e);
0028 
0029 
0030 #define ngx_http_script_exit  (u_char *) &ngx_http_script_exit_code
0031 
0032 static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL;
0033 
0034 
0035 void
0036 ngx_http_script_flush_complex_value(ngx_http_request_t *r,
0037     ngx_http_complex_value_t *val)
0038 {
0039     ngx_uint_t *index;
0040 
0041     index = val->flushes;
0042 
0043     if (index) {
0044         while (*index != (ngx_uint_t) -1) {
0045 
0046             if (r->variables[*index].no_cacheable) {
0047                 r->variables[*index].valid = 0;
0048                 r->variables[*index].not_found = 0;
0049             }
0050 
0051             index++;
0052         }
0053     }
0054 }
0055 
0056 
0057 ngx_int_t
0058 ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val,
0059     ngx_str_t *value)
0060 {
0061     size_t                        len;
0062     ngx_http_script_code_pt       code;
0063     ngx_http_script_len_code_pt   lcode;
0064     ngx_http_script_engine_t      e;
0065 
0066     if (val->lengths == NULL) {
0067         *value = val->value;
0068         return NGX_OK;
0069     }
0070 
0071     ngx_http_script_flush_complex_value(r, val);
0072 
0073     ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
0074 
0075     e.ip = val->lengths;
0076     e.request = r;
0077     e.flushed = 1;
0078 
0079     len = 0;
0080 
0081     while (*(uintptr_t *) e.ip) {
0082         lcode = *(ngx_http_script_len_code_pt *) e.ip;
0083         len += lcode(&e);
0084     }
0085 
0086     value->len = len;
0087     value->data = ngx_pnalloc(r->pool, len);
0088     if (value->data == NULL) {
0089         return NGX_ERROR;
0090     }
0091 
0092     e.ip = val->values;
0093     e.pos = value->data;
0094     e.buf = *value;
0095 
0096     while (*(uintptr_t *) e.ip) {
0097         code = *(ngx_http_script_code_pt *) e.ip;
0098         code((ngx_http_script_engine_t *) &e);
0099     }
0100 
0101     *value = e.buf;
0102 
0103     return NGX_OK;
0104 }
0105 
0106 
0107 ngx_int_t
0108 ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
0109 {
0110     ngx_str_t                  *v;
0111     ngx_uint_t                  i, n, nv, nc;
0112     ngx_array_t                 flushes, lengths, values, *pf, *pl, *pv;
0113     ngx_http_script_compile_t   sc;
0114 
0115     v = ccv->value;
0116 
0117     nv = 0;
0118     nc = 0;
0119 
0120     for (i = 0; i < v->len; i++) {
0121         if (v->data[i] == '$') {
0122             if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
0123                 nc++;
0124 
0125             } else {
0126                 nv++;
0127             }
0128         }
0129     }
0130 
0131     if ((v->len == 0 || v->data[0] != '$')
0132         && (ccv->conf_prefix || ccv->root_prefix))
0133     {
0134         if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
0135             return NGX_ERROR;
0136         }
0137 
0138         ccv->conf_prefix = 0;
0139         ccv->root_prefix = 0;
0140     }
0141 
0142     ccv->complex_value->value = *v;
0143     ccv->complex_value->flushes = NULL;
0144     ccv->complex_value->lengths = NULL;
0145     ccv->complex_value->values = NULL;
0146 
0147     if (nv == 0 && nc == 0) {
0148         return NGX_OK;
0149     }
0150 
0151     n = nv + 1;
0152 
0153     if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
0154         != NGX_OK)
0155     {
0156         return NGX_ERROR;
0157     }
0158 
0159     n = nv * (2 * sizeof(ngx_http_script_copy_code_t)
0160                   + sizeof(ngx_http_script_var_code_t))
0161         + sizeof(uintptr_t);
0162 
0163     if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
0164         return NGX_ERROR;
0165     }
0166 
0167     n = (nv * (2 * sizeof(ngx_http_script_copy_code_t)
0168                    + sizeof(ngx_http_script_var_code_t))
0169                 + sizeof(uintptr_t)
0170                 + v->len
0171                 + sizeof(uintptr_t) - 1)
0172             & ~(sizeof(uintptr_t) - 1);
0173 
0174     if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
0175         return NGX_ERROR;
0176     }
0177 
0178     pf = &flushes;
0179     pl = &lengths;
0180     pv = &values;
0181 
0182     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
0183 
0184     sc.cf = ccv->cf;
0185     sc.source = v;
0186     sc.flushes = &pf;
0187     sc.lengths = &pl;
0188     sc.values = &pv;
0189     sc.complete_lengths = 1;
0190     sc.complete_values = 1;
0191     sc.zero = ccv->zero;
0192     sc.conf_prefix = ccv->conf_prefix;
0193     sc.root_prefix = ccv->root_prefix;
0194 
0195     if (ngx_http_script_compile(&sc) != NGX_OK) {
0196         return NGX_ERROR;
0197     }
0198 
0199     if (flushes.nelts) {
0200         ccv->complex_value->flushes = flushes.elts;
0201         ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
0202     }
0203 
0204     ccv->complex_value->lengths = lengths.elts;
0205     ccv->complex_value->values = values.elts;
0206 
0207     return NGX_OK;
0208 }
0209 
0210 
0211 char *
0212 ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0213 {
0214     char  *p = conf;
0215 
0216     ngx_str_t                          *value;
0217     ngx_http_complex_value_t          **cv;
0218     ngx_http_compile_complex_value_t    ccv;
0219 
0220     cv = (ngx_http_complex_value_t **) (p + cmd->offset);
0221 
0222     if (*cv != NULL) {
0223         return "is duplicate";
0224     }
0225 
0226     *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
0227     if (*cv == NULL) {
0228         return NGX_CONF_ERROR;
0229     }
0230 
0231     value = cf->args->elts;
0232 
0233     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
0234 
0235     ccv.cf = cf;
0236     ccv.value = &value[1];
0237     ccv.complex_value = *cv;
0238 
0239     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
0240         return NGX_CONF_ERROR;
0241     }
0242 
0243     return NGX_CONF_OK;
0244 }
0245 
0246 
0247 ngx_int_t
0248 ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates)
0249 {
0250     ngx_str_t                  val;
0251     ngx_uint_t                 i;
0252     ngx_http_complex_value_t  *cv;
0253 
0254     if (predicates == NULL) {
0255         return NGX_OK;
0256     }
0257 
0258     cv = predicates->elts;
0259 
0260     for (i = 0; i < predicates->nelts; i++) {
0261         if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
0262             return NGX_ERROR;
0263         }
0264 
0265         if (val.len && (val.len != 1 || val.data[0] != '0')) {
0266             return NGX_DECLINED;
0267         }
0268     }
0269 
0270     return NGX_OK;
0271 }
0272 
0273 
0274 char *
0275 ngx_http_set_predicate_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0276 {
0277     char  *p = conf;
0278 
0279     ngx_str_t                          *value;
0280     ngx_uint_t                          i;
0281     ngx_array_t                       **a;
0282     ngx_http_complex_value_t           *cv;
0283     ngx_http_compile_complex_value_t    ccv;
0284 
0285     a = (ngx_array_t **) (p + cmd->offset);
0286 
0287     if (*a == NGX_CONF_UNSET_PTR) {
0288         *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t));
0289         if (*a == NULL) {
0290             return NGX_CONF_ERROR;
0291         }
0292     }
0293 
0294     value = cf->args->elts;
0295 
0296     for (i = 1; i < cf->args->nelts; i++) {
0297         cv = ngx_array_push(*a);
0298         if (cv == NULL) {
0299             return NGX_CONF_ERROR;
0300         }
0301 
0302         ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
0303 
0304         ccv.cf = cf;
0305         ccv.value = &value[i];
0306         ccv.complex_value = cv;
0307 
0308         if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
0309             return NGX_CONF_ERROR;
0310         }
0311     }
0312 
0313     return NGX_CONF_OK;
0314 }
0315 
0316 
0317 ngx_uint_t
0318 ngx_http_script_variables_count(ngx_str_t *value)
0319 {
0320     ngx_uint_t  i, n;
0321 
0322     for (n = 0, i = 0; i < value->len; i++) {
0323         if (value->data[i] == '$') {
0324             n++;
0325         }
0326     }
0327 
0328     return n;
0329 }
0330 
0331 
0332 ngx_int_t
0333 ngx_http_script_compile(ngx_http_script_compile_t *sc)
0334 {
0335     u_char       ch;
0336     ngx_str_t    name;
0337     ngx_uint_t   i, bracket;
0338 
0339     if (ngx_http_script_init_arrays(sc) != NGX_OK) {
0340         return NGX_ERROR;
0341     }
0342 
0343     for (i = 0; i < sc->source->len; /* void */ ) {
0344 
0345         name.len = 0;
0346 
0347         if (sc->source->data[i] == '$') {
0348 
0349             if (++i == sc->source->len) {
0350                 goto invalid_variable;
0351             }
0352 
0353             if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
0354 #if (NGX_PCRE)
0355                 ngx_uint_t  n;
0356 
0357                 n = sc->source->data[i] - '0';
0358 
0359                 if (sc->captures_mask & ((ngx_uint_t) 1 << n)) {
0360                     sc->dup_capture = 1;
0361                 }
0362 
0363                 sc->captures_mask |= (ngx_uint_t) 1 << n;
0364 
0365                 if (ngx_http_script_add_capture_code(sc, n) != NGX_OK) {
0366                     return NGX_ERROR;
0367                 }
0368 
0369                 i++;
0370 
0371                 continue;
0372 #else
0373                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
0374                                    "using variable \"$%c\" requires "
0375                                    "PCRE library", sc->source->data[i]);
0376                 return NGX_ERROR;
0377 #endif
0378             }
0379 
0380             if (sc->source->data[i] == '{') {
0381                 bracket = 1;
0382 
0383                 if (++i == sc->source->len) {
0384                     goto invalid_variable;
0385                 }
0386 
0387                 name.data = &sc->source->data[i];
0388 
0389             } else {
0390                 bracket = 0;
0391                 name.data = &sc->source->data[i];
0392             }
0393 
0394             for ( /* void */ ; i < sc->source->len; i++, name.len++) {
0395                 ch = sc->source->data[i];
0396 
0397                 if (ch == '}' && bracket) {
0398                     i++;
0399                     bracket = 0;
0400                     break;
0401                 }
0402 
0403                 if ((ch >= 'A' && ch <= 'Z')
0404                     || (ch >= 'a' && ch <= 'z')
0405                     || (ch >= '0' && ch <= '9')
0406                     || ch == '_')
0407                 {
0408                     continue;
0409                 }
0410 
0411                 break;
0412             }
0413 
0414             if (bracket) {
0415                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
0416                                    "the closing bracket in \"%V\" "
0417                                    "variable is missing", &name);
0418                 return NGX_ERROR;
0419             }
0420 
0421             if (name.len == 0) {
0422                 goto invalid_variable;
0423             }
0424 
0425             sc->variables++;
0426 
0427             if (ngx_http_script_add_var_code(sc, &name) != NGX_OK) {
0428                 return NGX_ERROR;
0429             }
0430 
0431             continue;
0432         }
0433 
0434         if (sc->source->data[i] == '?' && sc->compile_args) {
0435             sc->args = 1;
0436             sc->compile_args = 0;
0437 
0438             if (ngx_http_script_add_args_code(sc) != NGX_OK) {
0439                 return NGX_ERROR;
0440             }
0441 
0442             i++;
0443 
0444             continue;
0445         }
0446 
0447         name.data = &sc->source->data[i];
0448 
0449         while (i < sc->source->len) {
0450 
0451             if (sc->source->data[i] == '$') {
0452                 break;
0453             }
0454 
0455             if (sc->source->data[i] == '?') {
0456 
0457                 sc->args = 1;
0458 
0459                 if (sc->compile_args) {
0460                     break;
0461                 }
0462             }
0463 
0464             i++;
0465             name.len++;
0466         }
0467 
0468         sc->size += name.len;
0469 
0470         if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len))
0471             != NGX_OK)
0472         {
0473             return NGX_ERROR;
0474         }
0475     }
0476 
0477     return ngx_http_script_done(sc);
0478 
0479 invalid_variable:
0480 
0481     ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");
0482 
0483     return NGX_ERROR;
0484 }
0485 
0486 
0487 u_char *
0488 ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,
0489     void *code_lengths, size_t len, void *code_values)
0490 {
0491     ngx_uint_t                    i;
0492     ngx_http_script_code_pt       code;
0493     ngx_http_script_len_code_pt   lcode;
0494     ngx_http_script_engine_t      e;
0495     ngx_http_core_main_conf_t    *cmcf;
0496 
0497     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
0498 
0499     for (i = 0; i < cmcf->variables.nelts; i++) {
0500         if (r->variables[i].no_cacheable) {
0501             r->variables[i].valid = 0;
0502             r->variables[i].not_found = 0;
0503         }
0504     }
0505 
0506     ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
0507 
0508     e.ip = code_lengths;
0509     e.request = r;
0510     e.flushed = 1;
0511 
0512     while (*(uintptr_t *) e.ip) {
0513         lcode = *(ngx_http_script_len_code_pt *) e.ip;
0514         len += lcode(&e);
0515     }
0516 
0517 
0518     value->len = len;
0519     value->data = ngx_pnalloc(r->pool, len);
0520     if (value->data == NULL) {
0521         return NULL;
0522     }
0523 
0524     e.ip = code_values;
0525     e.pos = value->data;
0526 
0527     while (*(uintptr_t *) e.ip) {
0528         code = *(ngx_http_script_code_pt *) e.ip;
0529         code((ngx_http_script_engine_t *) &e);
0530     }
0531 
0532     return e.pos;
0533 }
0534 
0535 
0536 void
0537 ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r,
0538     ngx_array_t *indices)
0539 {
0540     ngx_uint_t  n, *index;
0541 
0542     if (indices) {
0543         index = indices->elts;
0544         for (n = 0; n < indices->nelts; n++) {
0545             if (r->variables[index[n]].no_cacheable) {
0546                 r->variables[index[n]].valid = 0;
0547                 r->variables[index[n]].not_found = 0;
0548             }
0549         }
0550     }
0551 }
0552 
0553 
0554 static ngx_int_t
0555 ngx_http_script_init_arrays(ngx_http_script_compile_t *sc)
0556 {
0557     ngx_uint_t   n;
0558 
0559     if (sc->flushes && *sc->flushes == NULL) {
0560         n = sc->variables ? sc->variables : 1;
0561         *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t));
0562         if (*sc->flushes == NULL) {
0563             return NGX_ERROR;
0564         }
0565     }
0566 
0567     if (*sc->lengths == NULL) {
0568         n = sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
0569                              + sizeof(ngx_http_script_var_code_t))
0570             + sizeof(uintptr_t);
0571 
0572         *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
0573         if (*sc->lengths == NULL) {
0574             return NGX_ERROR;
0575         }
0576     }
0577 
0578     if (*sc->values == NULL) {
0579         n = (sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
0580                               + sizeof(ngx_http_script_var_code_t))
0581                 + sizeof(uintptr_t)
0582                 + sc->source->len
0583                 + sizeof(uintptr_t) - 1)
0584             & ~(sizeof(uintptr_t) - 1);
0585 
0586         *sc->values = ngx_array_create(sc->cf->pool, n, 1);
0587         if (*sc->values == NULL) {
0588             return NGX_ERROR;
0589         }
0590     }
0591 
0592     sc->variables = 0;
0593 
0594     return NGX_OK;
0595 }
0596 
0597 
0598 static ngx_int_t
0599 ngx_http_script_done(ngx_http_script_compile_t *sc)
0600 {
0601     ngx_str_t    zero;
0602     uintptr_t   *code;
0603 
0604     if (sc->zero) {
0605 
0606         zero.len = 1;
0607         zero.data = (u_char *) "\0";
0608 
0609         if (ngx_http_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
0610             return NGX_ERROR;
0611         }
0612     }
0613 
0614     if (sc->conf_prefix || sc->root_prefix) {
0615         if (ngx_http_script_add_full_name_code(sc) != NGX_OK) {
0616             return NGX_ERROR;
0617         }
0618     }
0619 
0620     if (sc->complete_lengths) {
0621         code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
0622         if (code == NULL) {
0623             return NGX_ERROR;
0624         }
0625 
0626         *code = (uintptr_t) NULL;
0627     }
0628 
0629     if (sc->complete_values) {
0630         code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
0631                                         &sc->main);
0632         if (code == NULL) {
0633             return NGX_ERROR;
0634         }
0635 
0636         *code = (uintptr_t) NULL;
0637     }
0638 
0639     return NGX_OK;
0640 }
0641 
0642 
0643 void *
0644 ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
0645 {
0646     if (*codes == NULL) {
0647         *codes = ngx_array_create(pool, 256, 1);
0648         if (*codes == NULL) {
0649             return NULL;
0650         }
0651     }
0652 
0653     return ngx_array_push_n(*codes, size);
0654 }
0655 
0656 
0657 void *
0658 ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code)
0659 {
0660     u_char  *elts, **p;
0661     void    *new;
0662 
0663     elts = codes->elts;
0664 
0665     new = ngx_array_push_n(codes, size);
0666     if (new == NULL) {
0667         return NULL;
0668     }
0669 
0670     if (code) {
0671         if (elts != codes->elts) {
0672             p = code;
0673             *p += (u_char *) codes->elts - elts;
0674         }
0675     }
0676 
0677     return new;
0678 }
0679 
0680 
0681 static ngx_int_t
0682 ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value,
0683     ngx_uint_t last)
0684 {
0685     u_char                       *p;
0686     size_t                        size, len, zero;
0687     ngx_http_script_copy_code_t  *code;
0688 
0689     zero = (sc->zero && last);
0690     len = value->len + zero;
0691 
0692     code = ngx_http_script_add_code(*sc->lengths,
0693                                     sizeof(ngx_http_script_copy_code_t), NULL);
0694     if (code == NULL) {
0695         return NGX_ERROR;
0696     }
0697 
0698     code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
0699     code->len = len;
0700 
0701     size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
0702             & ~(sizeof(uintptr_t) - 1);
0703 
0704     code = ngx_http_script_add_code(*sc->values, size, &sc->main);
0705     if (code == NULL) {
0706         return NGX_ERROR;
0707     }
0708 
0709     code->code = ngx_http_script_copy_code;
0710     code->len = len;
0711 
0712     p = ngx_cpymem((u_char *) code + sizeof(ngx_http_script_copy_code_t),
0713                    value->data, value->len);
0714 
0715     if (zero) {
0716         *p = '\0';
0717         sc->zero = 0;
0718     }
0719 
0720     return NGX_OK;
0721 }
0722 
0723 
0724 size_t
0725 ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
0726 {
0727     ngx_http_script_copy_code_t  *code;
0728 
0729     code = (ngx_http_script_copy_code_t *) e->ip;
0730 
0731     e->ip += sizeof(ngx_http_script_copy_code_t);
0732 
0733     return code->len;
0734 }
0735 
0736 
0737 void
0738 ngx_http_script_copy_code(ngx_http_script_engine_t *e)
0739 {
0740     u_char                       *p;
0741     ngx_http_script_copy_code_t  *code;
0742 
0743     code = (ngx_http_script_copy_code_t *) e->ip;
0744 
0745     p = e->pos;
0746 
0747     if (!e->skip) {
0748         e->pos = ngx_copy(p, e->ip + sizeof(ngx_http_script_copy_code_t),
0749                           code->len);
0750     }
0751 
0752     e->ip += sizeof(ngx_http_script_copy_code_t)
0753           + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
0754 
0755     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
0756                    "http script copy: \"%*s\"", e->pos - p, p);
0757 }
0758 
0759 
0760 static ngx_int_t
0761 ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, ngx_str_t *name)
0762 {
0763     ngx_int_t                    index, *p;
0764     ngx_http_script_var_code_t  *code;
0765 
0766     index = ngx_http_get_variable_index(sc->cf, name);
0767 
0768     if (index == NGX_ERROR) {
0769         return NGX_ERROR;
0770     }
0771 
0772     if (sc->flushes) {
0773         p = ngx_array_push(*sc->flushes);
0774         if (p == NULL) {
0775             return NGX_ERROR;
0776         }
0777 
0778         *p = index;
0779     }
0780 
0781     code = ngx_http_script_add_code(*sc->lengths,
0782                                     sizeof(ngx_http_script_var_code_t), NULL);
0783     if (code == NULL) {
0784         return NGX_ERROR;
0785     }
0786 
0787     code->code = (ngx_http_script_code_pt) ngx_http_script_copy_var_len_code;
0788     code->index = (uintptr_t) index;
0789 
0790     code = ngx_http_script_add_code(*sc->values,
0791                                     sizeof(ngx_http_script_var_code_t),
0792                                     &sc->main);
0793     if (code == NULL) {
0794         return NGX_ERROR;
0795     }
0796 
0797     code->code = ngx_http_script_copy_var_code;
0798     code->index = (uintptr_t) index;
0799 
0800     return NGX_OK;
0801 }
0802 
0803 
0804 size_t
0805 ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
0806 {
0807     ngx_http_variable_value_t   *value;
0808     ngx_http_script_var_code_t  *code;
0809 
0810     code = (ngx_http_script_var_code_t *) e->ip;
0811 
0812     e->ip += sizeof(ngx_http_script_var_code_t);
0813 
0814     if (e->flushed) {
0815         value = ngx_http_get_indexed_variable(e->request, code->index);
0816 
0817     } else {
0818         value = ngx_http_get_flushed_variable(e->request, code->index);
0819     }
0820 
0821     if (value && !value->not_found) {
0822         return value->len;
0823     }
0824 
0825     return 0;
0826 }
0827 
0828 
0829 void
0830 ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
0831 {
0832     u_char                      *p;
0833     ngx_http_variable_value_t   *value;
0834     ngx_http_script_var_code_t  *code;
0835 
0836     code = (ngx_http_script_var_code_t *) e->ip;
0837 
0838     e->ip += sizeof(ngx_http_script_var_code_t);
0839 
0840     if (!e->skip) {
0841 
0842         if (e->flushed) {
0843             value = ngx_http_get_indexed_variable(e->request, code->index);
0844 
0845         } else {
0846             value = ngx_http_get_flushed_variable(e->request, code->index);
0847         }
0848 
0849         if (value && !value->not_found) {
0850             p = e->pos;
0851             e->pos = ngx_copy(p, value->data, value->len);
0852 
0853             ngx_log_debug2(NGX_LOG_DEBUG_HTTP,
0854                            e->request->connection->log, 0,
0855                            "http script var: \"%*s\"", e->pos - p, p);
0856         }
0857     }
0858 }
0859 
0860 
0861 static ngx_int_t
0862 ngx_http_script_add_args_code(ngx_http_script_compile_t *sc)
0863 {
0864     uintptr_t   *code;
0865 
0866     code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
0867     if (code == NULL) {
0868         return NGX_ERROR;
0869     }
0870 
0871     *code = (uintptr_t) ngx_http_script_mark_args_code;
0872 
0873     code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t), &sc->main);
0874     if (code == NULL) {
0875         return NGX_ERROR;
0876     }
0877 
0878     *code = (uintptr_t) ngx_http_script_start_args_code;
0879 
0880     return NGX_OK;
0881 }
0882 
0883 
0884 size_t
0885 ngx_http_script_mark_args_code(ngx_http_script_engine_t *e)
0886 {
0887     e->is_args = 1;
0888     e->ip += sizeof(uintptr_t);
0889 
0890     return 1;
0891 }
0892 
0893 
0894 void
0895 ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
0896 {
0897     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
0898                    "http script args");
0899 
0900     e->is_args = 1;
0901     e->args = e->pos;
0902     e->ip += sizeof(uintptr_t);
0903 }
0904 
0905 
0906 #if (NGX_PCRE)
0907 
0908 void
0909 ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
0910 {
0911     size_t                         len;
0912     ngx_int_t                      rc;
0913     ngx_uint_t                     n;
0914     ngx_http_request_t            *r;
0915     ngx_http_script_engine_t       le;
0916     ngx_http_script_len_code_pt    lcode;
0917     ngx_http_script_regex_code_t  *code;
0918 
0919     code = (ngx_http_script_regex_code_t *) e->ip;
0920 
0921     r = e->request;
0922 
0923     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
0924                    "http script regex: \"%V\"", &code->name);
0925 
0926     if (code->uri) {
0927         e->line = r->uri;
0928     } else {
0929         e->sp--;
0930         e->line.len = e->sp->len;
0931         e->line.data = e->sp->data;
0932     }
0933 
0934     rc = ngx_http_regex_exec(r, code->regex, &e->line);
0935 
0936     if (rc == NGX_DECLINED) {
0937         if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
0938             ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
0939                           "\"%V\" does not match \"%V\"",
0940                           &code->name, &e->line);
0941         }
0942 
0943         r->ncaptures = 0;
0944 
0945         if (code->test) {
0946             if (code->negative_test) {
0947                 e->sp->len = 1;
0948                 e->sp->data = (u_char *) "1";
0949 
0950             } else {
0951                 e->sp->len = 0;
0952                 e->sp->data = (u_char *) "";
0953             }
0954 
0955             e->sp++;
0956 
0957             e->ip += sizeof(ngx_http_script_regex_code_t);
0958             return;
0959         }
0960 
0961         e->ip += code->next;
0962         return;
0963     }
0964 
0965     if (rc == NGX_ERROR) {
0966         e->ip = ngx_http_script_exit;
0967         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
0968         return;
0969     }
0970 
0971     if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
0972         ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
0973                       "\"%V\" matches \"%V\"", &code->name, &e->line);
0974     }
0975 
0976     if (code->test) {
0977         if (code->negative_test) {
0978             e->sp->len = 0;
0979             e->sp->data = (u_char *) "";
0980 
0981         } else {
0982             e->sp->len = 1;
0983             e->sp->data = (u_char *) "1";
0984         }
0985 
0986         e->sp++;
0987 
0988         e->ip += sizeof(ngx_http_script_regex_code_t);
0989         return;
0990     }
0991 
0992     if (code->status) {
0993         e->status = code->status;
0994 
0995         if (!code->redirect) {
0996             e->ip = ngx_http_script_exit;
0997             return;
0998         }
0999     }
1000 
1001     if (code->uri) {
1002         r->internal = 1;
1003         r->valid_unparsed_uri = 0;
1004 
1005         if (code->break_cycle) {
1006             r->valid_location = 0;
1007             r->uri_changed = 0;
1008 
1009         } else {
1010             r->uri_changed = 1;
1011         }
1012     }
1013 
1014     if (code->lengths == NULL) {
1015         e->buf.len = code->size;
1016 
1017         if (code->uri) {
1018             if (r->ncaptures && (r->quoted_uri || r->plus_in_uri)) {
1019                 e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
1020                                                  NGX_ESCAPE_ARGS);
1021             }
1022         }
1023 
1024         for (n = 2; n < r->ncaptures; n += 2) {
1025             e->buf.len += r->captures[n + 1] - r->captures[n];
1026         }
1027 
1028     } else {
1029         ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
1030 
1031         le.ip = code->lengths->elts;
1032         le.line = e->line;
1033         le.request = r;
1034         le.quote = code->redirect;
1035 
1036         len = 0;
1037 
1038         while (*(uintptr_t *) le.ip) {
1039             lcode = *(ngx_http_script_len_code_pt *) le.ip;
1040             len += lcode(&le);
1041         }
1042 
1043         e->buf.len = len;
1044     }
1045 
1046     if (code->add_args && r->args.len) {
1047         e->buf.len += r->args.len + 1;
1048     }
1049 
1050     e->buf.data = ngx_pnalloc(r->pool, e->buf.len);
1051     if (e->buf.data == NULL) {
1052         e->ip = ngx_http_script_exit;
1053         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1054         return;
1055     }
1056 
1057     e->quote = code->redirect;
1058 
1059     e->pos = e->buf.data;
1060 
1061     e->ip += sizeof(ngx_http_script_regex_code_t);
1062 }
1063 
1064 
1065 void
1066 ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
1067 {
1068     u_char                            *dst, *src;
1069     ngx_http_request_t                *r;
1070     ngx_http_script_regex_end_code_t  *code;
1071 
1072     code = (ngx_http_script_regex_end_code_t *) e->ip;
1073 
1074     r = e->request;
1075 
1076     e->quote = 0;
1077 
1078     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1079                    "http script regex end");
1080 
1081     if (code->redirect) {
1082 
1083         dst = e->buf.data;
1084         src = e->buf.data;
1085 
1086         ngx_unescape_uri(&dst, &src, e->pos - e->buf.data,
1087                          NGX_UNESCAPE_REDIRECT);
1088 
1089         if (src < e->pos) {
1090             dst = ngx_movemem(dst, src, e->pos - src);
1091         }
1092 
1093         e->pos = dst;
1094 
1095         if (code->add_args && r->args.len) {
1096             *e->pos++ = (u_char) (code->args ? '&' : '?');
1097             e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
1098         }
1099 
1100         e->buf.len = e->pos - e->buf.data;
1101 
1102         if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
1103             ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
1104                           "rewritten redirect: \"%V\"", &e->buf);
1105         }
1106 
1107         ngx_http_clear_location(r);
1108 
1109         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
1110         if (r->headers_out.location == NULL) {
1111             e->ip = ngx_http_script_exit;
1112             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1113             return;
1114         }
1115 
1116         r->headers_out.location->hash = 1;
1117         ngx_str_set(&r->headers_out.location->key, "Location");
1118         r->headers_out.location->value = e->buf;
1119 
1120         e->ip += sizeof(ngx_http_script_regex_end_code_t);
1121         return;
1122     }
1123 
1124     if (e->args) {
1125         e->buf.len = e->args - e->buf.data;
1126 
1127         if (code->add_args && r->args.len) {
1128             *e->pos++ = '&';
1129             e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
1130         }
1131 
1132         r->args.len = e->pos - e->args;
1133         r->args.data = e->args;
1134 
1135         e->args = NULL;
1136 
1137     } else {
1138         e->buf.len = e->pos - e->buf.data;
1139 
1140         if (!code->add_args) {
1141             r->args.len = 0;
1142         }
1143     }
1144 
1145     if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
1146         ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
1147                       "rewritten data: \"%V\", args: \"%V\"",
1148                       &e->buf, &r->args);
1149     }
1150 
1151     if (code->uri) {
1152         r->uri = e->buf;
1153 
1154         if (r->uri.len == 0) {
1155             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1156                           "the rewritten URI has a zero length");
1157             e->ip = ngx_http_script_exit;
1158             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1159             return;
1160         }
1161 
1162         ngx_http_set_exten(r);
1163     }
1164 
1165     e->ip += sizeof(ngx_http_script_regex_end_code_t);
1166 }
1167 
1168 
1169 static ngx_int_t
1170 ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, ngx_uint_t n)
1171 {
1172     ngx_http_script_copy_capture_code_t  *code;
1173 
1174     code = ngx_http_script_add_code(*sc->lengths,
1175                                     sizeof(ngx_http_script_copy_capture_code_t),
1176                                     NULL);
1177     if (code == NULL) {
1178         return NGX_ERROR;
1179     }
1180 
1181     code->code = (ngx_http_script_code_pt)
1182                       ngx_http_script_copy_capture_len_code;
1183     code->n = 2 * n;
1184 
1185 
1186     code = ngx_http_script_add_code(*sc->values,
1187                                     sizeof(ngx_http_script_copy_capture_code_t),
1188                                     &sc->main);
1189     if (code == NULL) {
1190         return NGX_ERROR;
1191     }
1192 
1193     code->code = ngx_http_script_copy_capture_code;
1194     code->n = 2 * n;
1195 
1196     if (sc->ncaptures < n) {
1197         sc->ncaptures = n;
1198     }
1199 
1200     return NGX_OK;
1201 }
1202 
1203 
1204 size_t
1205 ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
1206 {
1207     int                                  *cap;
1208     u_char                               *p;
1209     ngx_uint_t                            n;
1210     ngx_http_request_t                   *r;
1211     ngx_http_script_copy_capture_code_t  *code;
1212 
1213     r = e->request;
1214 
1215     code = (ngx_http_script_copy_capture_code_t *) e->ip;
1216 
1217     e->ip += sizeof(ngx_http_script_copy_capture_code_t);
1218 
1219     n = code->n;
1220 
1221     if (n < r->ncaptures) {
1222 
1223         cap = r->captures;
1224 
1225         if ((e->is_args || e->quote)
1226             && (e->request->quoted_uri || e->request->plus_in_uri))
1227         {
1228             p = r->captures_data;
1229 
1230             return cap[n + 1] - cap[n]
1231                    + 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n],
1232                                         NGX_ESCAPE_ARGS);
1233         } else {
1234             return cap[n + 1] - cap[n];
1235         }
1236     }
1237 
1238     return 0;
1239 }
1240 
1241 
1242 void
1243 ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
1244 {
1245     int                                  *cap;
1246     u_char                               *p, *pos;
1247     ngx_uint_t                            n;
1248     ngx_http_request_t                   *r;
1249     ngx_http_script_copy_capture_code_t  *code;
1250 
1251     r = e->request;
1252 
1253     code = (ngx_http_script_copy_capture_code_t *) e->ip;
1254 
1255     e->ip += sizeof(ngx_http_script_copy_capture_code_t);
1256 
1257     n = code->n;
1258 
1259     pos = e->pos;
1260 
1261     if (n < r->ncaptures) {
1262 
1263         cap = r->captures;
1264         p = r->captures_data;
1265 
1266         if ((e->is_args || e->quote)
1267             && (e->request->quoted_uri || e->request->plus_in_uri))
1268         {
1269             e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
1270                                                cap[n + 1] - cap[n],
1271                                                NGX_ESCAPE_ARGS);
1272         } else {
1273             e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
1274         }
1275     }
1276 
1277     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1278                    "http script capture: \"%*s\"", e->pos - pos, pos);
1279 }
1280 
1281 #endif
1282 
1283 
1284 static ngx_int_t
1285 ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
1286 {
1287     ngx_http_script_full_name_code_t  *code;
1288 
1289     code = ngx_http_script_add_code(*sc->lengths,
1290                                     sizeof(ngx_http_script_full_name_code_t),
1291                                     NULL);
1292     if (code == NULL) {
1293         return NGX_ERROR;
1294     }
1295 
1296     code->code = (ngx_http_script_code_pt) ngx_http_script_full_name_len_code;
1297     code->conf_prefix = sc->conf_prefix;
1298 
1299     code = ngx_http_script_add_code(*sc->values,
1300                                     sizeof(ngx_http_script_full_name_code_t),
1301                                     &sc->main);
1302     if (code == NULL) {
1303         return NGX_ERROR;
1304     }
1305 
1306     code->code = ngx_http_script_full_name_code;
1307     code->conf_prefix = sc->conf_prefix;
1308 
1309     return NGX_OK;
1310 }
1311 
1312 
1313 static size_t
1314 ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e)
1315 {
1316     ngx_http_script_full_name_code_t  *code;
1317 
1318     code = (ngx_http_script_full_name_code_t *) e->ip;
1319 
1320     e->ip += sizeof(ngx_http_script_full_name_code_t);
1321 
1322     return code->conf_prefix ? ngx_cycle->conf_prefix.len:
1323                                ngx_cycle->prefix.len;
1324 }
1325 
1326 
1327 static void
1328 ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
1329 {
1330     ngx_http_script_full_name_code_t  *code;
1331 
1332     ngx_str_t  value, *prefix;
1333 
1334     code = (ngx_http_script_full_name_code_t *) e->ip;
1335 
1336     value.data = e->buf.data;
1337     value.len = e->pos - e->buf.data;
1338 
1339     prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix:
1340                                  (ngx_str_t *) &ngx_cycle->prefix;
1341 
1342     if (ngx_get_full_name(e->request->pool, prefix, &value) != NGX_OK) {
1343         e->ip = ngx_http_script_exit;
1344         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1345         return;
1346     }
1347 
1348     e->buf = value;
1349 
1350     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1351                    "http script fullname: \"%V\"", &value);
1352 
1353     e->ip += sizeof(ngx_http_script_full_name_code_t);
1354 }
1355 
1356 
1357 void
1358 ngx_http_script_return_code(ngx_http_script_engine_t *e)
1359 {
1360     ngx_http_script_return_code_t  *code;
1361 
1362     code = (ngx_http_script_return_code_t *) e->ip;
1363 
1364     if (code->status < NGX_HTTP_BAD_REQUEST
1365         || code->text.value.len
1366         || code->text.lengths)
1367     {
1368         e->status = ngx_http_send_response(e->request, code->status, NULL,
1369                                            &code->text);
1370     } else {
1371         e->status = code->status;
1372     }
1373 
1374     e->ip = ngx_http_script_exit;
1375 }
1376 
1377 
1378 void
1379 ngx_http_script_break_code(ngx_http_script_engine_t *e)
1380 {
1381     e->request->uri_changed = 0;
1382 
1383     e->ip = ngx_http_script_exit;
1384 }
1385 
1386 
1387 void
1388 ngx_http_script_if_code(ngx_http_script_engine_t *e)
1389 {
1390     ngx_http_script_if_code_t  *code;
1391 
1392     code = (ngx_http_script_if_code_t *) e->ip;
1393 
1394     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1395                    "http script if");
1396 
1397     e->sp--;
1398 
1399     if (e->sp->len && (e->sp->len != 1 || e->sp->data[0] != '0')) {
1400         if (code->loc_conf) {
1401             e->request->loc_conf = code->loc_conf;
1402             ngx_http_update_location_config(e->request);
1403         }
1404 
1405         e->ip += sizeof(ngx_http_script_if_code_t);
1406         return;
1407     }
1408 
1409     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1410                    "http script if: false");
1411 
1412     e->ip += code->next;
1413 }
1414 
1415 
1416 void
1417 ngx_http_script_equal_code(ngx_http_script_engine_t *e)
1418 {
1419     ngx_http_variable_value_t  *val, *res;
1420 
1421     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1422                    "http script equal");
1423 
1424     e->sp--;
1425     val = e->sp;
1426     res = e->sp - 1;
1427 
1428     e->ip += sizeof(uintptr_t);
1429 
1430     if (val->len == res->len
1431         && ngx_strncmp(val->data, res->data, res->len) == 0)
1432     {
1433         *res = ngx_http_variable_true_value;
1434         return;
1435     }
1436 
1437     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1438                    "http script equal: no");
1439 
1440     *res = ngx_http_variable_null_value;
1441 }
1442 
1443 
1444 void
1445 ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
1446 {
1447     ngx_http_variable_value_t  *val, *res;
1448 
1449     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1450                    "http script not equal");
1451 
1452     e->sp--;
1453     val = e->sp;
1454     res = e->sp - 1;
1455 
1456     e->ip += sizeof(uintptr_t);
1457 
1458     if (val->len == res->len
1459         && ngx_strncmp(val->data, res->data, res->len) == 0)
1460     {
1461         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1462                        "http script not equal: no");
1463 
1464         *res = ngx_http_variable_null_value;
1465         return;
1466     }
1467 
1468     *res = ngx_http_variable_true_value;
1469 }
1470 
1471 
1472 void
1473 ngx_http_script_file_code(ngx_http_script_engine_t *e)
1474 {
1475     ngx_str_t                     path;
1476     ngx_http_request_t           *r;
1477     ngx_open_file_info_t          of;
1478     ngx_http_core_loc_conf_t     *clcf;
1479     ngx_http_variable_value_t    *value;
1480     ngx_http_script_file_code_t  *code;
1481 
1482     value = e->sp - 1;
1483 
1484     code = (ngx_http_script_file_code_t *) e->ip;
1485     e->ip += sizeof(ngx_http_script_file_code_t);
1486 
1487     path.len = value->len - 1;
1488     path.data = value->data;
1489 
1490     r = e->request;
1491 
1492     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1493                    "http script file op %p \"%V\"", (void *) code->op, &path);
1494 
1495     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1496 
1497     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
1498 
1499     of.read_ahead = clcf->read_ahead;
1500     of.directio = clcf->directio;
1501     of.valid = clcf->open_file_cache_valid;
1502     of.min_uses = clcf->open_file_cache_min_uses;
1503     of.test_only = 1;
1504     of.errors = clcf->open_file_cache_errors;
1505     of.events = clcf->open_file_cache_events;
1506 
1507     if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
1508         e->ip = ngx_http_script_exit;
1509         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1510         return;
1511     }
1512 
1513     if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
1514         != NGX_OK)
1515     {
1516         if (of.err == 0) {
1517             e->ip = ngx_http_script_exit;
1518             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1519             return;
1520         }
1521 
1522         if (of.err != NGX_ENOENT
1523             && of.err != NGX_ENOTDIR
1524             && of.err != NGX_ENAMETOOLONG)
1525         {
1526             ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
1527                           "%s \"%s\" failed", of.failed, value->data);
1528         }
1529 
1530         switch (code->op) {
1531 
1532         case ngx_http_script_file_plain:
1533         case ngx_http_script_file_dir:
1534         case ngx_http_script_file_exists:
1535         case ngx_http_script_file_exec:
1536              goto false_value;
1537 
1538         case ngx_http_script_file_not_plain:
1539         case ngx_http_script_file_not_dir:
1540         case ngx_http_script_file_not_exists:
1541         case ngx_http_script_file_not_exec:
1542              goto true_value;
1543         }
1544 
1545         goto false_value;
1546     }
1547 
1548     switch (code->op) {
1549     case ngx_http_script_file_plain:
1550         if (of.is_file) {
1551              goto true_value;
1552         }
1553         goto false_value;
1554 
1555     case ngx_http_script_file_not_plain:
1556         if (of.is_file) {
1557             goto false_value;
1558         }
1559         goto true_value;
1560 
1561     case ngx_http_script_file_dir:
1562         if (of.is_dir) {
1563              goto true_value;
1564         }
1565         goto false_value;
1566 
1567     case ngx_http_script_file_not_dir:
1568         if (of.is_dir) {
1569             goto false_value;
1570         }
1571         goto true_value;
1572 
1573     case ngx_http_script_file_exists:
1574         if (of.is_file || of.is_dir || of.is_link) {
1575              goto true_value;
1576         }
1577         goto false_value;
1578 
1579     case ngx_http_script_file_not_exists:
1580         if (of.is_file || of.is_dir || of.is_link) {
1581             goto false_value;
1582         }
1583         goto true_value;
1584 
1585     case ngx_http_script_file_exec:
1586         if (of.is_exec) {
1587              goto true_value;
1588         }
1589         goto false_value;
1590 
1591     case ngx_http_script_file_not_exec:
1592         if (of.is_exec) {
1593             goto false_value;
1594         }
1595         goto true_value;
1596     }
1597 
1598 false_value:
1599 
1600     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1601                    "http script file op false");
1602 
1603     *value = ngx_http_variable_null_value;
1604     return;
1605 
1606 true_value:
1607 
1608     *value = ngx_http_variable_true_value;
1609     return;
1610 }
1611 
1612 
1613 void
1614 ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
1615 {
1616     size_t                                 len;
1617     ngx_http_script_engine_t               le;
1618     ngx_http_script_len_code_pt            lcode;
1619     ngx_http_script_complex_value_code_t  *code;
1620 
1621     code = (ngx_http_script_complex_value_code_t *) e->ip;
1622 
1623     e->ip += sizeof(ngx_http_script_complex_value_code_t);
1624 
1625     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1626                    "http script complex value");
1627 
1628     ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
1629 
1630     le.ip = code->lengths->elts;
1631     le.line = e->line;
1632     le.request = e->request;
1633     le.quote = e->quote;
1634 
1635     for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
1636         lcode = *(ngx_http_script_len_code_pt *) le.ip;
1637     }
1638 
1639     e->buf.len = len;
1640     e->buf.data = ngx_pnalloc(e->request->pool, len);
1641     if (e->buf.data == NULL) {
1642         e->ip = ngx_http_script_exit;
1643         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1644         return;
1645     }
1646 
1647     e->pos = e->buf.data;
1648 
1649     e->sp->len = e->buf.len;
1650     e->sp->data = e->buf.data;
1651     e->sp++;
1652 }
1653 
1654 
1655 void
1656 ngx_http_script_value_code(ngx_http_script_engine_t *e)
1657 {
1658     ngx_http_script_value_code_t  *code;
1659 
1660     code = (ngx_http_script_value_code_t *) e->ip;
1661 
1662     e->ip += sizeof(ngx_http_script_value_code_t);
1663 
1664     e->sp->len = code->text_len;
1665     e->sp->data = (u_char *) code->text_data;
1666 
1667     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1668                    "http script value: \"%v\"", e->sp);
1669 
1670     e->sp++;
1671 }
1672 
1673 
1674 void
1675 ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
1676 {
1677     ngx_http_request_t          *r;
1678     ngx_http_script_var_code_t  *code;
1679 
1680     code = (ngx_http_script_var_code_t *) e->ip;
1681 
1682     e->ip += sizeof(ngx_http_script_var_code_t);
1683 
1684     r = e->request;
1685 
1686     e->sp--;
1687 
1688     r->variables[code->index].len = e->sp->len;
1689     r->variables[code->index].valid = 1;
1690     r->variables[code->index].no_cacheable = 0;
1691     r->variables[code->index].not_found = 0;
1692     r->variables[code->index].data = e->sp->data;
1693 
1694 #if (NGX_DEBUG)
1695     {
1696     ngx_http_variable_t        *v;
1697     ngx_http_core_main_conf_t  *cmcf;
1698 
1699     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1700 
1701     v = cmcf->variables.elts;
1702 
1703     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1704                    "http script set $%V", &v[code->index].name);
1705     }
1706 #endif
1707 }
1708 
1709 
1710 void
1711 ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e)
1712 {
1713     ngx_http_script_var_handler_code_t  *code;
1714 
1715     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1716                    "http script set var handler");
1717 
1718     code = (ngx_http_script_var_handler_code_t *) e->ip;
1719 
1720     e->ip += sizeof(ngx_http_script_var_handler_code_t);
1721 
1722     e->sp--;
1723 
1724     code->handler(e->request, e->sp, code->data);
1725 }
1726 
1727 
1728 void
1729 ngx_http_script_var_code(ngx_http_script_engine_t *e)
1730 {
1731     ngx_http_variable_value_t   *value;
1732     ngx_http_script_var_code_t  *code;
1733 
1734     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1735                    "http script var");
1736 
1737     code = (ngx_http_script_var_code_t *) e->ip;
1738 
1739     e->ip += sizeof(ngx_http_script_var_code_t);
1740 
1741     value = ngx_http_get_flushed_variable(e->request, code->index);
1742 
1743     if (value && !value->not_found) {
1744         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1745                        "http script var: \"%v\"", value);
1746 
1747         *e->sp = *value;
1748         e->sp++;
1749 
1750         return;
1751     }
1752 
1753     *e->sp = ngx_http_variable_null_value;
1754     e->sp++;
1755 }
1756 
1757 
1758 void
1759 ngx_http_script_nop_code(ngx_http_script_engine_t *e)
1760 {
1761     e->ip += sizeof(uintptr_t);
1762 }