0001
0002
0003
0004
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; ) {
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 ( ; 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 }