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>