Annotation of embedaddon/nginx/src/http/ngx_http_script.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (C) Igor Sysoev
! 4: * Copyright (C) Nginx, Inc.
! 5: */
! 6:
! 7:
! 8: #include <ngx_config.h>
! 9: #include <ngx_core.h>
! 10: #include <ngx_http.h>
! 11:
! 12:
! 13: static ngx_int_t ngx_http_script_init_arrays(ngx_http_script_compile_t *sc);
! 14: static ngx_int_t ngx_http_script_done(ngx_http_script_compile_t *sc);
! 15: static ngx_int_t ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc,
! 16: ngx_str_t *value, ngx_uint_t last);
! 17: static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc,
! 18: ngx_str_t *name);
! 19: static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc);
! 20: #if (NGX_PCRE)
! 21: static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc,
! 22: ngx_uint_t n);
! 23: #endif
! 24: static ngx_int_t
! 25: ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc);
! 26: static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e);
! 27: static void ngx_http_script_full_name_code(ngx_http_script_engine_t *e);
! 28:
! 29:
! 30: #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
! 31:
! 32: static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL;
! 33:
! 34:
! 35: void
! 36: ngx_http_script_flush_complex_value(ngx_http_request_t *r,
! 37: ngx_http_complex_value_t *val)
! 38: {
! 39: ngx_uint_t *index;
! 40:
! 41: index = val->flushes;
! 42:
! 43: if (index) {
! 44: while (*index != (ngx_uint_t) -1) {
! 45:
! 46: if (r->variables[*index].no_cacheable) {
! 47: r->variables[*index].valid = 0;
! 48: r->variables[*index].not_found = 0;
! 49: }
! 50:
! 51: index++;
! 52: }
! 53: }
! 54: }
! 55:
! 56:
! 57: ngx_int_t
! 58: ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val,
! 59: ngx_str_t *value)
! 60: {
! 61: size_t len;
! 62: ngx_http_script_code_pt code;
! 63: ngx_http_script_len_code_pt lcode;
! 64: ngx_http_script_engine_t e;
! 65:
! 66: if (val->lengths == NULL) {
! 67: *value = val->value;
! 68: return NGX_OK;
! 69: }
! 70:
! 71: ngx_http_script_flush_complex_value(r, val);
! 72:
! 73: ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
! 74:
! 75: e.ip = val->lengths;
! 76: e.request = r;
! 77: e.flushed = 1;
! 78:
! 79: len = 0;
! 80:
! 81: while (*(uintptr_t *) e.ip) {
! 82: lcode = *(ngx_http_script_len_code_pt *) e.ip;
! 83: len += lcode(&e);
! 84: }
! 85:
! 86: value->len = len;
! 87: value->data = ngx_pnalloc(r->pool, len);
! 88: if (value->data == NULL) {
! 89: return NGX_ERROR;
! 90: }
! 91:
! 92: e.ip = val->values;
! 93: e.pos = value->data;
! 94: e.buf = *value;
! 95:
! 96: while (*(uintptr_t *) e.ip) {
! 97: code = *(ngx_http_script_code_pt *) e.ip;
! 98: code((ngx_http_script_engine_t *) &e);
! 99: }
! 100:
! 101: *value = e.buf;
! 102:
! 103: return NGX_OK;
! 104: }
! 105:
! 106:
! 107: ngx_int_t
! 108: ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
! 109: {
! 110: ngx_str_t *v;
! 111: ngx_uint_t i, n, nv, nc;
! 112: ngx_array_t flushes, lengths, values, *pf, *pl, *pv;
! 113: ngx_http_script_compile_t sc;
! 114:
! 115: v = ccv->value;
! 116:
! 117: nv = 0;
! 118: nc = 0;
! 119:
! 120: for (i = 0; i < v->len; i++) {
! 121: if (v->data[i] == '$') {
! 122: if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
! 123: nc++;
! 124:
! 125: } else {
! 126: nv++;
! 127: }
! 128: }
! 129: }
! 130:
! 131: if ((v->len == 0 || v->data[0] != '$')
! 132: && (ccv->conf_prefix || ccv->root_prefix))
! 133: {
! 134: if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
! 135: return NGX_ERROR;
! 136: }
! 137:
! 138: ccv->conf_prefix = 0;
! 139: ccv->root_prefix = 0;
! 140: }
! 141:
! 142: ccv->complex_value->value = *v;
! 143: ccv->complex_value->flushes = NULL;
! 144: ccv->complex_value->lengths = NULL;
! 145: ccv->complex_value->values = NULL;
! 146:
! 147: if (nv == 0 && nc == 0) {
! 148: return NGX_OK;
! 149: }
! 150:
! 151: n = nv + 1;
! 152:
! 153: if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
! 154: != NGX_OK)
! 155: {
! 156: return NGX_ERROR;
! 157: }
! 158:
! 159: n = nv * (2 * sizeof(ngx_http_script_copy_code_t)
! 160: + sizeof(ngx_http_script_var_code_t))
! 161: + sizeof(uintptr_t);
! 162:
! 163: if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
! 164: return NGX_ERROR;
! 165: }
! 166:
! 167: n = (nv * (2 * sizeof(ngx_http_script_copy_code_t)
! 168: + sizeof(ngx_http_script_var_code_t))
! 169: + sizeof(uintptr_t)
! 170: + v->len
! 171: + sizeof(uintptr_t) - 1)
! 172: & ~(sizeof(uintptr_t) - 1);
! 173:
! 174: if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
! 175: return NGX_ERROR;
! 176: }
! 177:
! 178: pf = &flushes;
! 179: pl = &lengths;
! 180: pv = &values;
! 181:
! 182: ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
! 183:
! 184: sc.cf = ccv->cf;
! 185: sc.source = v;
! 186: sc.flushes = &pf;
! 187: sc.lengths = &pl;
! 188: sc.values = &pv;
! 189: sc.complete_lengths = 1;
! 190: sc.complete_values = 1;
! 191: sc.zero = ccv->zero;
! 192: sc.conf_prefix = ccv->conf_prefix;
! 193: sc.root_prefix = ccv->root_prefix;
! 194:
! 195: if (ngx_http_script_compile(&sc) != NGX_OK) {
! 196: return NGX_ERROR;
! 197: }
! 198:
! 199: if (flushes.nelts) {
! 200: ccv->complex_value->flushes = flushes.elts;
! 201: ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
! 202: }
! 203:
! 204: ccv->complex_value->lengths = lengths.elts;
! 205: ccv->complex_value->values = values.elts;
! 206:
! 207: return NGX_OK;
! 208: }
! 209:
! 210:
! 211: char *
! 212: ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 213: {
! 214: char *p = conf;
! 215:
! 216: ngx_str_t *value;
! 217: ngx_http_complex_value_t **cv;
! 218: ngx_http_compile_complex_value_t ccv;
! 219:
! 220: cv = (ngx_http_complex_value_t **) (p + cmd->offset);
! 221:
! 222: if (*cv != NULL) {
! 223: return "duplicate";
! 224: }
! 225:
! 226: *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
! 227: if (*cv == NULL) {
! 228: return NGX_CONF_ERROR;
! 229: }
! 230:
! 231: value = cf->args->elts;
! 232:
! 233: ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
! 234:
! 235: ccv.cf = cf;
! 236: ccv.value = &value[1];
! 237: ccv.complex_value = *cv;
! 238:
! 239: if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
! 240: return NGX_CONF_ERROR;
! 241: }
! 242:
! 243: return NGX_CONF_OK;
! 244: }
! 245:
! 246:
! 247: ngx_int_t
! 248: ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates)
! 249: {
! 250: ngx_str_t val;
! 251: ngx_uint_t i;
! 252: ngx_http_complex_value_t *cv;
! 253:
! 254: if (predicates == NULL) {
! 255: return NGX_OK;
! 256: }
! 257:
! 258: cv = predicates->elts;
! 259:
! 260: for (i = 0; i < predicates->nelts; i++) {
! 261: if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
! 262: return NGX_ERROR;
! 263: }
! 264:
! 265: if (val.len && (val.len != 1 || val.data[0] != '0')) {
! 266: return NGX_DECLINED;
! 267: }
! 268: }
! 269:
! 270: return NGX_OK;
! 271: }
! 272:
! 273:
! 274: char *
! 275: ngx_http_set_predicate_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 276: {
! 277: char *p = conf;
! 278:
! 279: ngx_str_t *value;
! 280: ngx_uint_t i;
! 281: ngx_array_t **a;
! 282: ngx_http_complex_value_t *cv;
! 283: ngx_http_compile_complex_value_t ccv;
! 284:
! 285: a = (ngx_array_t **) (p + cmd->offset);
! 286:
! 287: if (*a == NGX_CONF_UNSET_PTR) {
! 288: *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t));
! 289: if (*a == NULL) {
! 290: return NGX_CONF_ERROR;
! 291: }
! 292: }
! 293:
! 294: value = cf->args->elts;
! 295:
! 296: for (i = 1; i < cf->args->nelts; i++) {
! 297: cv = ngx_array_push(*a);
! 298: if (cv == NULL) {
! 299: return NGX_CONF_ERROR;
! 300: }
! 301:
! 302: ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
! 303:
! 304: ccv.cf = cf;
! 305: ccv.value = &value[i];
! 306: ccv.complex_value = cv;
! 307:
! 308: if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
! 309: return NGX_CONF_ERROR;
! 310: }
! 311: }
! 312:
! 313: return NGX_CONF_OK;
! 314: }
! 315:
! 316:
! 317: ngx_uint_t
! 318: ngx_http_script_variables_count(ngx_str_t *value)
! 319: {
! 320: ngx_uint_t i, n;
! 321:
! 322: for (n = 0, i = 0; i < value->len; i++) {
! 323: if (value->data[i] == '$') {
! 324: n++;
! 325: }
! 326: }
! 327:
! 328: return n;
! 329: }
! 330:
! 331:
! 332: ngx_int_t
! 333: ngx_http_script_compile(ngx_http_script_compile_t *sc)
! 334: {
! 335: u_char ch;
! 336: ngx_str_t name;
! 337: ngx_uint_t i, bracket;
! 338:
! 339: if (ngx_http_script_init_arrays(sc) != NGX_OK) {
! 340: return NGX_ERROR;
! 341: }
! 342:
! 343: for (i = 0; i < sc->source->len; /* void */ ) {
! 344:
! 345: name.len = 0;
! 346:
! 347: if (sc->source->data[i] == '$') {
! 348:
! 349: if (++i == sc->source->len) {
! 350: goto invalid_variable;
! 351: }
! 352:
! 353: #if (NGX_PCRE)
! 354: {
! 355: ngx_uint_t n;
! 356:
! 357: if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
! 358:
! 359: n = sc->source->data[i] - '0';
! 360:
! 361: if (sc->captures_mask & (1 << n)) {
! 362: sc->dup_capture = 1;
! 363: }
! 364:
! 365: sc->captures_mask |= 1 << n;
! 366:
! 367: if (ngx_http_script_add_capture_code(sc, n) != NGX_OK) {
! 368: return NGX_ERROR;
! 369: }
! 370:
! 371: i++;
! 372:
! 373: continue;
! 374: }
! 375: }
! 376: #endif
! 377:
! 378: if (sc->source->data[i] == '{') {
! 379: bracket = 1;
! 380:
! 381: if (++i == sc->source->len) {
! 382: goto invalid_variable;
! 383: }
! 384:
! 385: name.data = &sc->source->data[i];
! 386:
! 387: } else {
! 388: bracket = 0;
! 389: name.data = &sc->source->data[i];
! 390: }
! 391:
! 392: for ( /* void */ ; i < sc->source->len; i++, name.len++) {
! 393: ch = sc->source->data[i];
! 394:
! 395: if (ch == '}' && bracket) {
! 396: i++;
! 397: bracket = 0;
! 398: break;
! 399: }
! 400:
! 401: if ((ch >= 'A' && ch <= 'Z')
! 402: || (ch >= 'a' && ch <= 'z')
! 403: || (ch >= '0' && ch <= '9')
! 404: || ch == '_')
! 405: {
! 406: continue;
! 407: }
! 408:
! 409: break;
! 410: }
! 411:
! 412: if (bracket) {
! 413: ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
! 414: "the closing bracket in \"%V\" "
! 415: "variable is missing", &name);
! 416: return NGX_ERROR;
! 417: }
! 418:
! 419: if (name.len == 0) {
! 420: goto invalid_variable;
! 421: }
! 422:
! 423: sc->variables++;
! 424:
! 425: if (ngx_http_script_add_var_code(sc, &name) != NGX_OK) {
! 426: return NGX_ERROR;
! 427: }
! 428:
! 429: continue;
! 430: }
! 431:
! 432: if (sc->source->data[i] == '?' && sc->compile_args) {
! 433: sc->args = 1;
! 434: sc->compile_args = 0;
! 435:
! 436: if (ngx_http_script_add_args_code(sc) != NGX_OK) {
! 437: return NGX_ERROR;
! 438: }
! 439:
! 440: i++;
! 441:
! 442: continue;
! 443: }
! 444:
! 445: name.data = &sc->source->data[i];
! 446:
! 447: while (i < sc->source->len) {
! 448:
! 449: if (sc->source->data[i] == '$') {
! 450: break;
! 451: }
! 452:
! 453: if (sc->source->data[i] == '?') {
! 454:
! 455: sc->args = 1;
! 456:
! 457: if (sc->compile_args) {
! 458: break;
! 459: }
! 460: }
! 461:
! 462: i++;
! 463: name.len++;
! 464: }
! 465:
! 466: sc->size += name.len;
! 467:
! 468: if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len))
! 469: != NGX_OK)
! 470: {
! 471: return NGX_ERROR;
! 472: }
! 473: }
! 474:
! 475: return ngx_http_script_done(sc);
! 476:
! 477: invalid_variable:
! 478:
! 479: ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");
! 480:
! 481: return NGX_ERROR;
! 482: }
! 483:
! 484:
! 485: u_char *
! 486: ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,
! 487: void *code_lengths, size_t len, void *code_values)
! 488: {
! 489: ngx_uint_t i;
! 490: ngx_http_script_code_pt code;
! 491: ngx_http_script_len_code_pt lcode;
! 492: ngx_http_script_engine_t e;
! 493: ngx_http_core_main_conf_t *cmcf;
! 494:
! 495: cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
! 496:
! 497: for (i = 0; i < cmcf->variables.nelts; i++) {
! 498: if (r->variables[i].no_cacheable) {
! 499: r->variables[i].valid = 0;
! 500: r->variables[i].not_found = 0;
! 501: }
! 502: }
! 503:
! 504: ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
! 505:
! 506: e.ip = code_lengths;
! 507: e.request = r;
! 508: e.flushed = 1;
! 509:
! 510: while (*(uintptr_t *) e.ip) {
! 511: lcode = *(ngx_http_script_len_code_pt *) e.ip;
! 512: len += lcode(&e);
! 513: }
! 514:
! 515:
! 516: value->len = len;
! 517: value->data = ngx_pnalloc(r->pool, len);
! 518: if (value->data == NULL) {
! 519: return NULL;
! 520: }
! 521:
! 522: e.ip = code_values;
! 523: e.pos = value->data;
! 524:
! 525: while (*(uintptr_t *) e.ip) {
! 526: code = *(ngx_http_script_code_pt *) e.ip;
! 527: code((ngx_http_script_engine_t *) &e);
! 528: }
! 529:
! 530: return e.pos;
! 531: }
! 532:
! 533:
! 534: void
! 535: ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r,
! 536: ngx_array_t *indices)
! 537: {
! 538: ngx_uint_t n, *index;
! 539:
! 540: if (indices) {
! 541: index = indices->elts;
! 542: for (n = 0; n < indices->nelts; n++) {
! 543: if (r->variables[index[n]].no_cacheable) {
! 544: r->variables[index[n]].valid = 0;
! 545: r->variables[index[n]].not_found = 0;
! 546: }
! 547: }
! 548: }
! 549: }
! 550:
! 551:
! 552: static ngx_int_t
! 553: ngx_http_script_init_arrays(ngx_http_script_compile_t *sc)
! 554: {
! 555: ngx_uint_t n;
! 556:
! 557: if (sc->flushes && *sc->flushes == NULL) {
! 558: n = sc->variables ? sc->variables : 1;
! 559: *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t));
! 560: if (*sc->flushes == NULL) {
! 561: return NGX_ERROR;
! 562: }
! 563: }
! 564:
! 565: if (*sc->lengths == NULL) {
! 566: n = sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
! 567: + sizeof(ngx_http_script_var_code_t))
! 568: + sizeof(uintptr_t);
! 569:
! 570: *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
! 571: if (*sc->lengths == NULL) {
! 572: return NGX_ERROR;
! 573: }
! 574: }
! 575:
! 576: if (*sc->values == NULL) {
! 577: n = (sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
! 578: + sizeof(ngx_http_script_var_code_t))
! 579: + sizeof(uintptr_t)
! 580: + sc->source->len
! 581: + sizeof(uintptr_t) - 1)
! 582: & ~(sizeof(uintptr_t) - 1);
! 583:
! 584: *sc->values = ngx_array_create(sc->cf->pool, n, 1);
! 585: if (*sc->values == NULL) {
! 586: return NGX_ERROR;
! 587: }
! 588: }
! 589:
! 590: sc->variables = 0;
! 591:
! 592: return NGX_OK;
! 593: }
! 594:
! 595:
! 596: static ngx_int_t
! 597: ngx_http_script_done(ngx_http_script_compile_t *sc)
! 598: {
! 599: ngx_str_t zero;
! 600: uintptr_t *code;
! 601:
! 602: if (sc->zero) {
! 603:
! 604: zero.len = 1;
! 605: zero.data = (u_char *) "\0";
! 606:
! 607: if (ngx_http_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
! 608: return NGX_ERROR;
! 609: }
! 610: }
! 611:
! 612: if (sc->conf_prefix || sc->root_prefix) {
! 613: if (ngx_http_script_add_full_name_code(sc) != NGX_OK) {
! 614: return NGX_ERROR;
! 615: }
! 616: }
! 617:
! 618: if (sc->complete_lengths) {
! 619: code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
! 620: if (code == NULL) {
! 621: return NGX_ERROR;
! 622: }
! 623:
! 624: *code = (uintptr_t) NULL;
! 625: }
! 626:
! 627: if (sc->complete_values) {
! 628: code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
! 629: &sc->main);
! 630: if (code == NULL) {
! 631: return NGX_ERROR;
! 632: }
! 633:
! 634: *code = (uintptr_t) NULL;
! 635: }
! 636:
! 637: return NGX_OK;
! 638: }
! 639:
! 640:
! 641: void *
! 642: ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
! 643: {
! 644: if (*codes == NULL) {
! 645: *codes = ngx_array_create(pool, 256, 1);
! 646: if (*codes == NULL) {
! 647: return NULL;
! 648: }
! 649: }
! 650:
! 651: return ngx_array_push_n(*codes, size);
! 652: }
! 653:
! 654:
! 655: void *
! 656: ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code)
! 657: {
! 658: u_char *elts, **p;
! 659: void *new;
! 660:
! 661: elts = codes->elts;
! 662:
! 663: new = ngx_array_push_n(codes, size);
! 664: if (new == NULL) {
! 665: return NULL;
! 666: }
! 667:
! 668: if (code) {
! 669: if (elts != codes->elts) {
! 670: p = code;
! 671: *p += (u_char *) codes->elts - elts;
! 672: }
! 673: }
! 674:
! 675: return new;
! 676: }
! 677:
! 678:
! 679: static ngx_int_t
! 680: ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value,
! 681: ngx_uint_t last)
! 682: {
! 683: u_char *p;
! 684: size_t size, len, zero;
! 685: ngx_http_script_copy_code_t *code;
! 686:
! 687: zero = (sc->zero && last);
! 688: len = value->len + zero;
! 689:
! 690: code = ngx_http_script_add_code(*sc->lengths,
! 691: sizeof(ngx_http_script_copy_code_t), NULL);
! 692: if (code == NULL) {
! 693: return NGX_ERROR;
! 694: }
! 695:
! 696: code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
! 697: code->len = len;
! 698:
! 699: size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
! 700: & ~(sizeof(uintptr_t) - 1);
! 701:
! 702: code = ngx_http_script_add_code(*sc->values, size, &sc->main);
! 703: if (code == NULL) {
! 704: return NGX_ERROR;
! 705: }
! 706:
! 707: code->code = ngx_http_script_copy_code;
! 708: code->len = len;
! 709:
! 710: p = ngx_cpymem((u_char *) code + sizeof(ngx_http_script_copy_code_t),
! 711: value->data, value->len);
! 712:
! 713: if (zero) {
! 714: *p = '\0';
! 715: sc->zero = 0;
! 716: }
! 717:
! 718: return NGX_OK;
! 719: }
! 720:
! 721:
! 722: size_t
! 723: ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
! 724: {
! 725: ngx_http_script_copy_code_t *code;
! 726:
! 727: code = (ngx_http_script_copy_code_t *) e->ip;
! 728:
! 729: e->ip += sizeof(ngx_http_script_copy_code_t);
! 730:
! 731: return code->len;
! 732: }
! 733:
! 734:
! 735: void
! 736: ngx_http_script_copy_code(ngx_http_script_engine_t *e)
! 737: {
! 738: u_char *p;
! 739: ngx_http_script_copy_code_t *code;
! 740:
! 741: code = (ngx_http_script_copy_code_t *) e->ip;
! 742:
! 743: p = e->pos;
! 744:
! 745: if (!e->skip) {
! 746: e->pos = ngx_copy(p, e->ip + sizeof(ngx_http_script_copy_code_t),
! 747: code->len);
! 748: }
! 749:
! 750: e->ip += sizeof(ngx_http_script_copy_code_t)
! 751: + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
! 752:
! 753: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 754: "http script copy: \"%*s\"", e->pos - p, p);
! 755: }
! 756:
! 757:
! 758: static ngx_int_t
! 759: ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, ngx_str_t *name)
! 760: {
! 761: ngx_int_t index, *p;
! 762: ngx_http_script_var_code_t *code;
! 763:
! 764: index = ngx_http_get_variable_index(sc->cf, name);
! 765:
! 766: if (index == NGX_ERROR) {
! 767: return NGX_ERROR;
! 768: }
! 769:
! 770: if (sc->flushes) {
! 771: p = ngx_array_push(*sc->flushes);
! 772: if (p == NULL) {
! 773: return NGX_ERROR;
! 774: }
! 775:
! 776: *p = index;
! 777: }
! 778:
! 779: code = ngx_http_script_add_code(*sc->lengths,
! 780: sizeof(ngx_http_script_var_code_t), NULL);
! 781: if (code == NULL) {
! 782: return NGX_ERROR;
! 783: }
! 784:
! 785: code->code = (ngx_http_script_code_pt) ngx_http_script_copy_var_len_code;
! 786: code->index = (uintptr_t) index;
! 787:
! 788: code = ngx_http_script_add_code(*sc->values,
! 789: sizeof(ngx_http_script_var_code_t),
! 790: &sc->main);
! 791: if (code == NULL) {
! 792: return NGX_ERROR;
! 793: }
! 794:
! 795: code->code = ngx_http_script_copy_var_code;
! 796: code->index = (uintptr_t) index;
! 797:
! 798: return NGX_OK;
! 799: }
! 800:
! 801:
! 802: size_t
! 803: ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
! 804: {
! 805: ngx_http_variable_value_t *value;
! 806: ngx_http_script_var_code_t *code;
! 807:
! 808: code = (ngx_http_script_var_code_t *) e->ip;
! 809:
! 810: e->ip += sizeof(ngx_http_script_var_code_t);
! 811:
! 812: if (e->flushed) {
! 813: value = ngx_http_get_indexed_variable(e->request, code->index);
! 814:
! 815: } else {
! 816: value = ngx_http_get_flushed_variable(e->request, code->index);
! 817: }
! 818:
! 819: if (value && !value->not_found) {
! 820: return value->len;
! 821: }
! 822:
! 823: return 0;
! 824: }
! 825:
! 826:
! 827: void
! 828: ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
! 829: {
! 830: u_char *p;
! 831: ngx_http_variable_value_t *value;
! 832: ngx_http_script_var_code_t *code;
! 833:
! 834: code = (ngx_http_script_var_code_t *) e->ip;
! 835:
! 836: e->ip += sizeof(ngx_http_script_var_code_t);
! 837:
! 838: if (!e->skip) {
! 839:
! 840: if (e->flushed) {
! 841: value = ngx_http_get_indexed_variable(e->request, code->index);
! 842:
! 843: } else {
! 844: value = ngx_http_get_flushed_variable(e->request, code->index);
! 845: }
! 846:
! 847: if (value && !value->not_found) {
! 848: p = e->pos;
! 849: e->pos = ngx_copy(p, value->data, value->len);
! 850:
! 851: ngx_log_debug2(NGX_LOG_DEBUG_HTTP,
! 852: e->request->connection->log, 0,
! 853: "http script var: \"%*s\"", e->pos - p, p);
! 854: }
! 855: }
! 856: }
! 857:
! 858:
! 859: static ngx_int_t
! 860: ngx_http_script_add_args_code(ngx_http_script_compile_t *sc)
! 861: {
! 862: uintptr_t *code;
! 863:
! 864: code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
! 865: if (code == NULL) {
! 866: return NGX_ERROR;
! 867: }
! 868:
! 869: *code = (uintptr_t) ngx_http_script_mark_args_code;
! 870:
! 871: code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t), &sc->main);
! 872: if (code == NULL) {
! 873: return NGX_ERROR;
! 874: }
! 875:
! 876: *code = (uintptr_t) ngx_http_script_start_args_code;
! 877:
! 878: return NGX_OK;
! 879: }
! 880:
! 881:
! 882: size_t
! 883: ngx_http_script_mark_args_code(ngx_http_script_engine_t *e)
! 884: {
! 885: e->is_args = 1;
! 886: e->ip += sizeof(uintptr_t);
! 887:
! 888: return 1;
! 889: }
! 890:
! 891:
! 892: void
! 893: ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
! 894: {
! 895: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 896: "http script args");
! 897:
! 898: e->is_args = 1;
! 899: e->args = e->pos;
! 900: e->ip += sizeof(uintptr_t);
! 901: }
! 902:
! 903:
! 904: #if (NGX_PCRE)
! 905:
! 906: void
! 907: ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
! 908: {
! 909: size_t len;
! 910: ngx_int_t rc;
! 911: ngx_uint_t n;
! 912: ngx_http_request_t *r;
! 913: ngx_http_script_engine_t le;
! 914: ngx_http_script_len_code_pt lcode;
! 915: ngx_http_script_regex_code_t *code;
! 916:
! 917: code = (ngx_http_script_regex_code_t *) e->ip;
! 918:
! 919: r = e->request;
! 920:
! 921: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 922: "http script regex: \"%V\"", &code->name);
! 923:
! 924: if (code->uri) {
! 925: e->line = r->uri;
! 926: } else {
! 927: e->sp--;
! 928: e->line.len = e->sp->len;
! 929: e->line.data = e->sp->data;
! 930: }
! 931:
! 932: rc = ngx_http_regex_exec(r, code->regex, &e->line);
! 933:
! 934: if (rc == NGX_DECLINED) {
! 935: if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
! 936: ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
! 937: "\"%V\" does not match \"%V\"",
! 938: &code->name, &e->line);
! 939: }
! 940:
! 941: r->ncaptures = 0;
! 942:
! 943: if (code->test) {
! 944: if (code->negative_test) {
! 945: e->sp->len = 1;
! 946: e->sp->data = (u_char *) "1";
! 947:
! 948: } else {
! 949: e->sp->len = 0;
! 950: e->sp->data = (u_char *) "";
! 951: }
! 952:
! 953: e->sp++;
! 954:
! 955: e->ip += sizeof(ngx_http_script_regex_code_t);
! 956: return;
! 957: }
! 958:
! 959: e->ip += code->next;
! 960: return;
! 961: }
! 962:
! 963: if (rc == NGX_ERROR) {
! 964: e->ip = ngx_http_script_exit;
! 965: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
! 966: return;
! 967: }
! 968:
! 969: if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
! 970: ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
! 971: "\"%V\" matches \"%V\"", &code->name, &e->line);
! 972: }
! 973:
! 974: if (code->test) {
! 975: if (code->negative_test) {
! 976: e->sp->len = 0;
! 977: e->sp->data = (u_char *) "";
! 978:
! 979: } else {
! 980: e->sp->len = 1;
! 981: e->sp->data = (u_char *) "1";
! 982: }
! 983:
! 984: e->sp++;
! 985:
! 986: e->ip += sizeof(ngx_http_script_regex_code_t);
! 987: return;
! 988: }
! 989:
! 990: if (code->status) {
! 991: e->status = code->status;
! 992:
! 993: if (!code->redirect) {
! 994: e->ip = ngx_http_script_exit;
! 995: return;
! 996: }
! 997: }
! 998:
! 999: if (code->uri) {
! 1000: r->internal = 1;
! 1001: r->valid_unparsed_uri = 0;
! 1002:
! 1003: if (code->break_cycle) {
! 1004: r->valid_location = 0;
! 1005: r->uri_changed = 0;
! 1006:
! 1007: } else {
! 1008: r->uri_changed = 1;
! 1009: }
! 1010: }
! 1011:
! 1012: if (code->lengths == NULL) {
! 1013: e->buf.len = code->size;
! 1014:
! 1015: if (code->uri) {
! 1016: if (r->ncaptures && (r->quoted_uri || r->plus_in_uri)) {
! 1017: e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
! 1018: NGX_ESCAPE_ARGS);
! 1019: }
! 1020: }
! 1021:
! 1022: for (n = 2; n < r->ncaptures; n += 2) {
! 1023: e->buf.len += r->captures[n + 1] - r->captures[n];
! 1024: }
! 1025:
! 1026: } else {
! 1027: ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
! 1028:
! 1029: le.ip = code->lengths->elts;
! 1030: le.line = e->line;
! 1031: le.request = r;
! 1032: le.quote = code->redirect;
! 1033:
! 1034: len = 0;
! 1035:
! 1036: while (*(uintptr_t *) le.ip) {
! 1037: lcode = *(ngx_http_script_len_code_pt *) le.ip;
! 1038: len += lcode(&le);
! 1039: }
! 1040:
! 1041: e->buf.len = len;
! 1042: }
! 1043:
! 1044: if (code->add_args && r->args.len) {
! 1045: e->buf.len += r->args.len + 1;
! 1046: }
! 1047:
! 1048: e->buf.data = ngx_pnalloc(r->pool, e->buf.len);
! 1049: if (e->buf.data == NULL) {
! 1050: e->ip = ngx_http_script_exit;
! 1051: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
! 1052: return;
! 1053: }
! 1054:
! 1055: e->quote = code->redirect;
! 1056:
! 1057: e->pos = e->buf.data;
! 1058:
! 1059: e->ip += sizeof(ngx_http_script_regex_code_t);
! 1060: }
! 1061:
! 1062:
! 1063: void
! 1064: ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
! 1065: {
! 1066: u_char *dst, *src;
! 1067: ngx_http_request_t *r;
! 1068: ngx_http_script_regex_end_code_t *code;
! 1069:
! 1070: code = (ngx_http_script_regex_end_code_t *) e->ip;
! 1071:
! 1072: r = e->request;
! 1073:
! 1074: e->quote = 0;
! 1075:
! 1076: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 1077: "http script regex end");
! 1078:
! 1079: if (code->redirect) {
! 1080:
! 1081: dst = e->buf.data;
! 1082: src = e->buf.data;
! 1083:
! 1084: ngx_unescape_uri(&dst, &src, e->pos - e->buf.data,
! 1085: NGX_UNESCAPE_REDIRECT);
! 1086:
! 1087: if (src < e->pos) {
! 1088: dst = ngx_movemem(dst, src, e->pos - src);
! 1089: }
! 1090:
! 1091: e->pos = dst;
! 1092:
! 1093: if (code->add_args && r->args.len) {
! 1094: *e->pos++ = (u_char) (code->args ? '&' : '?');
! 1095: e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
! 1096: }
! 1097:
! 1098: e->buf.len = e->pos - e->buf.data;
! 1099:
! 1100: if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
! 1101: ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
! 1102: "rewritten redirect: \"%V\"", &e->buf);
! 1103: }
! 1104:
! 1105: ngx_http_clear_location(r);
! 1106:
! 1107: r->headers_out.location = ngx_list_push(&r->headers_out.headers);
! 1108: if (r->headers_out.location == NULL) {
! 1109: e->ip = ngx_http_script_exit;
! 1110: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
! 1111: return;
! 1112: }
! 1113:
! 1114: r->headers_out.location->hash = 1;
! 1115: ngx_str_set(&r->headers_out.location->key, "Location");
! 1116: r->headers_out.location->value = e->buf;
! 1117:
! 1118: e->ip += sizeof(ngx_http_script_regex_end_code_t);
! 1119: return;
! 1120: }
! 1121:
! 1122: if (e->args) {
! 1123: e->buf.len = e->args - e->buf.data;
! 1124:
! 1125: if (code->add_args && r->args.len) {
! 1126: *e->pos++ = '&';
! 1127: e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
! 1128: }
! 1129:
! 1130: r->args.len = e->pos - e->args;
! 1131: r->args.data = e->args;
! 1132:
! 1133: e->args = NULL;
! 1134:
! 1135: } else {
! 1136: e->buf.len = e->pos - e->buf.data;
! 1137:
! 1138: if (!code->add_args) {
! 1139: r->args.len = 0;
! 1140: }
! 1141: }
! 1142:
! 1143: if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
! 1144: ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
! 1145: "rewritten data: \"%V\", args: \"%V\"",
! 1146: &e->buf, &r->args);
! 1147: }
! 1148:
! 1149: if (code->uri) {
! 1150: r->uri = e->buf;
! 1151:
! 1152: if (r->uri.len == 0) {
! 1153: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
! 1154: "the rewritten URI has a zero length");
! 1155: e->ip = ngx_http_script_exit;
! 1156: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
! 1157: return;
! 1158: }
! 1159:
! 1160: ngx_http_set_exten(r);
! 1161: }
! 1162:
! 1163: e->ip += sizeof(ngx_http_script_regex_end_code_t);
! 1164: }
! 1165:
! 1166:
! 1167: static ngx_int_t
! 1168: ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, ngx_uint_t n)
! 1169: {
! 1170: ngx_http_script_copy_capture_code_t *code;
! 1171:
! 1172: code = ngx_http_script_add_code(*sc->lengths,
! 1173: sizeof(ngx_http_script_copy_capture_code_t),
! 1174: NULL);
! 1175: if (code == NULL) {
! 1176: return NGX_ERROR;
! 1177: }
! 1178:
! 1179: code->code = (ngx_http_script_code_pt)
! 1180: ngx_http_script_copy_capture_len_code;
! 1181: code->n = 2 * n;
! 1182:
! 1183:
! 1184: code = ngx_http_script_add_code(*sc->values,
! 1185: sizeof(ngx_http_script_copy_capture_code_t),
! 1186: &sc->main);
! 1187: if (code == NULL) {
! 1188: return NGX_ERROR;
! 1189: }
! 1190:
! 1191: code->code = ngx_http_script_copy_capture_code;
! 1192: code->n = 2 * n;
! 1193:
! 1194: if (sc->ncaptures < n) {
! 1195: sc->ncaptures = n;
! 1196: }
! 1197:
! 1198: return NGX_OK;
! 1199: }
! 1200:
! 1201:
! 1202: size_t
! 1203: ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
! 1204: {
! 1205: int *cap;
! 1206: u_char *p;
! 1207: ngx_uint_t n;
! 1208: ngx_http_request_t *r;
! 1209: ngx_http_script_copy_capture_code_t *code;
! 1210:
! 1211: r = e->request;
! 1212:
! 1213: code = (ngx_http_script_copy_capture_code_t *) e->ip;
! 1214:
! 1215: e->ip += sizeof(ngx_http_script_copy_capture_code_t);
! 1216:
! 1217: n = code->n;
! 1218:
! 1219: if (n < r->ncaptures) {
! 1220:
! 1221: cap = r->captures;
! 1222:
! 1223: if ((e->is_args || e->quote)
! 1224: && (e->request->quoted_uri || e->request->plus_in_uri))
! 1225: {
! 1226: p = r->captures_data;
! 1227:
! 1228: return cap[n + 1] - cap[n]
! 1229: + 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n],
! 1230: NGX_ESCAPE_ARGS);
! 1231: } else {
! 1232: return cap[n + 1] - cap[n];
! 1233: }
! 1234: }
! 1235:
! 1236: return 0;
! 1237: }
! 1238:
! 1239:
! 1240: void
! 1241: ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
! 1242: {
! 1243: int *cap;
! 1244: u_char *p, *pos;
! 1245: ngx_uint_t n;
! 1246: ngx_http_request_t *r;
! 1247: ngx_http_script_copy_capture_code_t *code;
! 1248:
! 1249: r = e->request;
! 1250:
! 1251: code = (ngx_http_script_copy_capture_code_t *) e->ip;
! 1252:
! 1253: e->ip += sizeof(ngx_http_script_copy_capture_code_t);
! 1254:
! 1255: n = code->n;
! 1256:
! 1257: pos = e->pos;
! 1258:
! 1259: if (n < r->ncaptures) {
! 1260:
! 1261: cap = r->captures;
! 1262: p = r->captures_data;
! 1263:
! 1264: if ((e->is_args || e->quote)
! 1265: && (e->request->quoted_uri || e->request->plus_in_uri))
! 1266: {
! 1267: e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
! 1268: cap[n + 1] - cap[n],
! 1269: NGX_ESCAPE_ARGS);
! 1270: } else {
! 1271: e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
! 1272: }
! 1273: }
! 1274:
! 1275: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1276: "http script capture: \"%*s\"", e->pos - pos, pos);
! 1277: }
! 1278:
! 1279: #endif
! 1280:
! 1281:
! 1282: static ngx_int_t
! 1283: ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
! 1284: {
! 1285: ngx_http_script_full_name_code_t *code;
! 1286:
! 1287: code = ngx_http_script_add_code(*sc->lengths,
! 1288: sizeof(ngx_http_script_full_name_code_t),
! 1289: NULL);
! 1290: if (code == NULL) {
! 1291: return NGX_ERROR;
! 1292: }
! 1293:
! 1294: code->code = (ngx_http_script_code_pt) ngx_http_script_full_name_len_code;
! 1295: code->conf_prefix = sc->conf_prefix;
! 1296:
! 1297: code = ngx_http_script_add_code(*sc->values,
! 1298: sizeof(ngx_http_script_full_name_code_t),
! 1299: &sc->main);
! 1300: if (code == NULL) {
! 1301: return NGX_ERROR;
! 1302: }
! 1303:
! 1304: code->code = ngx_http_script_full_name_code;
! 1305: code->conf_prefix = sc->conf_prefix;
! 1306:
! 1307: return NGX_OK;
! 1308: }
! 1309:
! 1310:
! 1311: static size_t
! 1312: ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e)
! 1313: {
! 1314: ngx_http_script_full_name_code_t *code;
! 1315:
! 1316: code = (ngx_http_script_full_name_code_t *) e->ip;
! 1317:
! 1318: e->ip += sizeof(ngx_http_script_full_name_code_t);
! 1319:
! 1320: return code->conf_prefix ? ngx_cycle->conf_prefix.len:
! 1321: ngx_cycle->prefix.len;
! 1322: }
! 1323:
! 1324:
! 1325: static void
! 1326: ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
! 1327: {
! 1328: ngx_http_script_full_name_code_t *code;
! 1329:
! 1330: ngx_str_t value;
! 1331:
! 1332: code = (ngx_http_script_full_name_code_t *) e->ip;
! 1333:
! 1334: value.data = e->buf.data;
! 1335: value.len = e->pos - e->buf.data;
! 1336:
! 1337: if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &value, code->conf_prefix)
! 1338: != NGX_OK)
! 1339: {
! 1340: e->ip = ngx_http_script_exit;
! 1341: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
! 1342: return;
! 1343: }
! 1344:
! 1345: e->buf = value;
! 1346:
! 1347: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1348: "http script fullname: \"%V\"", &value);
! 1349:
! 1350: e->ip += sizeof(ngx_http_script_full_name_code_t);
! 1351: }
! 1352:
! 1353:
! 1354: void
! 1355: ngx_http_script_return_code(ngx_http_script_engine_t *e)
! 1356: {
! 1357: ngx_http_script_return_code_t *code;
! 1358:
! 1359: code = (ngx_http_script_return_code_t *) e->ip;
! 1360:
! 1361: if (code->status < NGX_HTTP_BAD_REQUEST
! 1362: || code->text.value.len
! 1363: || code->text.lengths)
! 1364: {
! 1365: e->status = ngx_http_send_response(e->request, code->status, NULL,
! 1366: &code->text);
! 1367: } else {
! 1368: e->status = code->status;
! 1369: }
! 1370:
! 1371: e->ip = ngx_http_script_exit;
! 1372: }
! 1373:
! 1374:
! 1375: void
! 1376: ngx_http_script_break_code(ngx_http_script_engine_t *e)
! 1377: {
! 1378: e->request->uri_changed = 0;
! 1379:
! 1380: e->ip = ngx_http_script_exit;
! 1381: }
! 1382:
! 1383:
! 1384: void
! 1385: ngx_http_script_if_code(ngx_http_script_engine_t *e)
! 1386: {
! 1387: ngx_http_script_if_code_t *code;
! 1388:
! 1389: code = (ngx_http_script_if_code_t *) e->ip;
! 1390:
! 1391: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1392: "http script if");
! 1393:
! 1394: e->sp--;
! 1395:
! 1396: if (e->sp->len && (e->sp->len !=1 || e->sp->data[0] != '0')) {
! 1397: if (code->loc_conf) {
! 1398: e->request->loc_conf = code->loc_conf;
! 1399: ngx_http_update_location_config(e->request);
! 1400: }
! 1401:
! 1402: e->ip += sizeof(ngx_http_script_if_code_t);
! 1403: return;
! 1404: }
! 1405:
! 1406: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1407: "http script if: false");
! 1408:
! 1409: e->ip += code->next;
! 1410: }
! 1411:
! 1412:
! 1413: void
! 1414: ngx_http_script_equal_code(ngx_http_script_engine_t *e)
! 1415: {
! 1416: ngx_http_variable_value_t *val, *res;
! 1417:
! 1418: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1419: "http script equal");
! 1420:
! 1421: e->sp--;
! 1422: val = e->sp;
! 1423: res = e->sp - 1;
! 1424:
! 1425: e->ip += sizeof(uintptr_t);
! 1426:
! 1427: if (val->len == res->len
! 1428: && ngx_strncmp(val->data, res->data, res->len) == 0)
! 1429: {
! 1430: *res = ngx_http_variable_true_value;
! 1431: return;
! 1432: }
! 1433:
! 1434: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1435: "http script equal: no");
! 1436:
! 1437: *res = ngx_http_variable_null_value;
! 1438: }
! 1439:
! 1440:
! 1441: void
! 1442: ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
! 1443: {
! 1444: ngx_http_variable_value_t *val, *res;
! 1445:
! 1446: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1447: "http script not equal");
! 1448:
! 1449: e->sp--;
! 1450: val = e->sp;
! 1451: res = e->sp - 1;
! 1452:
! 1453: e->ip += sizeof(uintptr_t);
! 1454:
! 1455: if (val->len == res->len
! 1456: && ngx_strncmp(val->data, res->data, res->len) == 0)
! 1457: {
! 1458: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1459: "http script not equal: no");
! 1460:
! 1461: *res = ngx_http_variable_null_value;
! 1462: return;
! 1463: }
! 1464:
! 1465: *res = ngx_http_variable_true_value;
! 1466: }
! 1467:
! 1468:
! 1469: void
! 1470: ngx_http_script_file_code(ngx_http_script_engine_t *e)
! 1471: {
! 1472: ngx_str_t path;
! 1473: ngx_http_request_t *r;
! 1474: ngx_open_file_info_t of;
! 1475: ngx_http_core_loc_conf_t *clcf;
! 1476: ngx_http_variable_value_t *value;
! 1477: ngx_http_script_file_code_t *code;
! 1478:
! 1479: value = e->sp - 1;
! 1480:
! 1481: code = (ngx_http_script_file_code_t *) e->ip;
! 1482: e->ip += sizeof(ngx_http_script_file_code_t);
! 1483:
! 1484: path.len = value->len - 1;
! 1485: path.data = value->data;
! 1486:
! 1487: r = e->request;
! 1488:
! 1489: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 1490: "http script file op %p \"%V\"", code->op, &path);
! 1491:
! 1492: clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
! 1493:
! 1494: ngx_memzero(&of, sizeof(ngx_open_file_info_t));
! 1495:
! 1496: of.read_ahead = clcf->read_ahead;
! 1497: of.directio = clcf->directio;
! 1498: of.valid = clcf->open_file_cache_valid;
! 1499: of.min_uses = clcf->open_file_cache_min_uses;
! 1500: of.test_only = 1;
! 1501: of.errors = clcf->open_file_cache_errors;
! 1502: of.events = clcf->open_file_cache_events;
! 1503:
! 1504: if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
! 1505: e->ip = ngx_http_script_exit;
! 1506: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
! 1507: return;
! 1508: }
! 1509:
! 1510: if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
! 1511: != NGX_OK)
! 1512: {
! 1513: if (of.err != NGX_ENOENT
! 1514: && of.err != NGX_ENOTDIR
! 1515: && of.err != NGX_ENAMETOOLONG)
! 1516: {
! 1517: ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
! 1518: "%s \"%s\" failed", of.failed, value->data);
! 1519: }
! 1520:
! 1521: switch (code->op) {
! 1522:
! 1523: case ngx_http_script_file_plain:
! 1524: case ngx_http_script_file_dir:
! 1525: case ngx_http_script_file_exists:
! 1526: case ngx_http_script_file_exec:
! 1527: goto false_value;
! 1528:
! 1529: case ngx_http_script_file_not_plain:
! 1530: case ngx_http_script_file_not_dir:
! 1531: case ngx_http_script_file_not_exists:
! 1532: case ngx_http_script_file_not_exec:
! 1533: goto true_value;
! 1534: }
! 1535:
! 1536: goto false_value;
! 1537: }
! 1538:
! 1539: switch (code->op) {
! 1540: case ngx_http_script_file_plain:
! 1541: if (of.is_file) {
! 1542: goto true_value;
! 1543: }
! 1544: goto false_value;
! 1545:
! 1546: case ngx_http_script_file_not_plain:
! 1547: if (of.is_file) {
! 1548: goto false_value;
! 1549: }
! 1550: goto true_value;
! 1551:
! 1552: case ngx_http_script_file_dir:
! 1553: if (of.is_dir) {
! 1554: goto true_value;
! 1555: }
! 1556: goto false_value;
! 1557:
! 1558: case ngx_http_script_file_not_dir:
! 1559: if (of.is_dir) {
! 1560: goto false_value;
! 1561: }
! 1562: goto true_value;
! 1563:
! 1564: case ngx_http_script_file_exists:
! 1565: if (of.is_file || of.is_dir || of.is_link) {
! 1566: goto true_value;
! 1567: }
! 1568: goto false_value;
! 1569:
! 1570: case ngx_http_script_file_not_exists:
! 1571: if (of.is_file || of.is_dir || of.is_link) {
! 1572: goto false_value;
! 1573: }
! 1574: goto true_value;
! 1575:
! 1576: case ngx_http_script_file_exec:
! 1577: if (of.is_exec) {
! 1578: goto true_value;
! 1579: }
! 1580: goto false_value;
! 1581:
! 1582: case ngx_http_script_file_not_exec:
! 1583: if (of.is_exec) {
! 1584: goto false_value;
! 1585: }
! 1586: goto true_value;
! 1587: }
! 1588:
! 1589: false_value:
! 1590:
! 1591: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
! 1592: "http script file op false");
! 1593:
! 1594: *value = ngx_http_variable_null_value;
! 1595: return;
! 1596:
! 1597: true_value:
! 1598:
! 1599: *value = ngx_http_variable_true_value;
! 1600: return;
! 1601: }
! 1602:
! 1603:
! 1604: void
! 1605: ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
! 1606: {
! 1607: size_t len;
! 1608: ngx_http_script_engine_t le;
! 1609: ngx_http_script_len_code_pt lcode;
! 1610: ngx_http_script_complex_value_code_t *code;
! 1611:
! 1612: code = (ngx_http_script_complex_value_code_t *) e->ip;
! 1613:
! 1614: e->ip += sizeof(ngx_http_script_complex_value_code_t);
! 1615:
! 1616: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1617: "http script complex value");
! 1618:
! 1619: ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
! 1620:
! 1621: le.ip = code->lengths->elts;
! 1622: le.line = e->line;
! 1623: le.request = e->request;
! 1624: le.quote = e->quote;
! 1625:
! 1626: for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
! 1627: lcode = *(ngx_http_script_len_code_pt *) le.ip;
! 1628: }
! 1629:
! 1630: e->buf.len = len;
! 1631: e->buf.data = ngx_pnalloc(e->request->pool, len);
! 1632: if (e->buf.data == NULL) {
! 1633: e->ip = ngx_http_script_exit;
! 1634: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
! 1635: return;
! 1636: }
! 1637:
! 1638: e->pos = e->buf.data;
! 1639:
! 1640: e->sp->len = e->buf.len;
! 1641: e->sp->data = e->buf.data;
! 1642: e->sp++;
! 1643: }
! 1644:
! 1645:
! 1646: void
! 1647: ngx_http_script_value_code(ngx_http_script_engine_t *e)
! 1648: {
! 1649: ngx_http_script_value_code_t *code;
! 1650:
! 1651: code = (ngx_http_script_value_code_t *) e->ip;
! 1652:
! 1653: e->ip += sizeof(ngx_http_script_value_code_t);
! 1654:
! 1655: e->sp->len = code->text_len;
! 1656: e->sp->data = (u_char *) code->text_data;
! 1657:
! 1658: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1659: "http script value: \"%v\"", e->sp);
! 1660:
! 1661: e->sp++;
! 1662: }
! 1663:
! 1664:
! 1665: void
! 1666: ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
! 1667: {
! 1668: ngx_http_request_t *r;
! 1669: ngx_http_script_var_code_t *code;
! 1670:
! 1671: code = (ngx_http_script_var_code_t *) e->ip;
! 1672:
! 1673: e->ip += sizeof(ngx_http_script_var_code_t);
! 1674:
! 1675: r = e->request;
! 1676:
! 1677: e->sp--;
! 1678:
! 1679: r->variables[code->index].len = e->sp->len;
! 1680: r->variables[code->index].valid = 1;
! 1681: r->variables[code->index].no_cacheable = 0;
! 1682: r->variables[code->index].not_found = 0;
! 1683: r->variables[code->index].data = e->sp->data;
! 1684:
! 1685: #if (NGX_DEBUG)
! 1686: {
! 1687: ngx_http_variable_t *v;
! 1688: ngx_http_core_main_conf_t *cmcf;
! 1689:
! 1690: cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
! 1691:
! 1692: v = cmcf->variables.elts;
! 1693:
! 1694: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1695: "http script set $%V", &v[code->index].name);
! 1696: }
! 1697: #endif
! 1698: }
! 1699:
! 1700:
! 1701: void
! 1702: ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e)
! 1703: {
! 1704: ngx_http_script_var_handler_code_t *code;
! 1705:
! 1706: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1707: "http script set var handler");
! 1708:
! 1709: code = (ngx_http_script_var_handler_code_t *) e->ip;
! 1710:
! 1711: e->ip += sizeof(ngx_http_script_var_handler_code_t);
! 1712:
! 1713: e->sp--;
! 1714:
! 1715: code->handler(e->request, e->sp, code->data);
! 1716: }
! 1717:
! 1718:
! 1719: void
! 1720: ngx_http_script_var_code(ngx_http_script_engine_t *e)
! 1721: {
! 1722: ngx_http_variable_value_t *value;
! 1723: ngx_http_script_var_code_t *code;
! 1724:
! 1725: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1726: "http script var");
! 1727:
! 1728: code = (ngx_http_script_var_code_t *) e->ip;
! 1729:
! 1730: e->ip += sizeof(ngx_http_script_var_code_t);
! 1731:
! 1732: value = ngx_http_get_flushed_variable(e->request, code->index);
! 1733:
! 1734: if (value && !value->not_found) {
! 1735: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
! 1736: "http script var: \"%v\"", value);
! 1737:
! 1738: *e->sp = *value;
! 1739: e->sp++;
! 1740:
! 1741: return;
! 1742: }
! 1743:
! 1744: *e->sp = ngx_http_variable_null_value;
! 1745: e->sp++;
! 1746: }
! 1747:
! 1748:
! 1749: void
! 1750: ngx_http_script_nop_code(ngx_http_script_engine_t *e)
! 1751: {
! 1752: e->ip += sizeof(uintptr_t);
! 1753: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>