Annotation of embedaddon/nginx/src/http/ngx_http_script.c, revision 1.1.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>