~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/ngx_http_script.c

Version: ~ [ nginx-0.6.26 ] ~ [ nginx-0.5.35 ] ~ [ nginx-0.5.20 ] ~ [ nginx-0.5.19 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  */
  5 
  6 
  7 #include <ngx_config.h>
  8 #include <ngx_core.h>
  9 #include <ngx_http.h>
 10 
 11 
 12 #define ngx_http_script_exit  (u_char *) &ngx_http_script_exit_code
 13 
 14 static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL;
 15 
 16 
 17 ngx_uint_t
 18 ngx_http_script_variables_count(ngx_str_t *value)
 19 {
 20     ngx_uint_t  i, n;
 21 
 22     for (n = 0, i = 0; i < value->len; i++) {
 23         if (value->data[i] == '$') {
 24             n++;
 25         }
 26     }
 27 
 28     return n;
 29 }
 30 
 31 
 32 ngx_int_t
 33 ngx_http_script_compile(ngx_http_script_compile_t *sc)
 34 {
 35     u_char                                ch;
 36     size_t                                size;
 37     ngx_int_t                             index, *p;
 38     ngx_str_t                             name;
 39     uintptr_t                            *code;
 40     ngx_uint_t                            i, n, bracket;
 41     ngx_http_script_var_code_t           *var_code;
 42     ngx_http_script_copy_code_t          *copy;
 43     ngx_http_script_copy_capture_code_t  *copy_capture;
 44 
 45     if (sc->flushes && *sc->flushes == NULL) {
 46         n = sc->variables ? sc->variables : 1;
 47         *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t));
 48         if (*sc->flushes == NULL) {
 49             return NGX_ERROR;
 50         }
 51     }
 52 
 53 
 54     if (*sc->lengths == NULL) {
 55         n = sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
 56                              + sizeof(ngx_http_script_var_code_t))
 57             + sizeof(uintptr_t);
 58 
 59         *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
 60         if (*sc->lengths == NULL) {
 61             return NGX_ERROR;
 62         }
 63     }
 64 
 65 
 66     if (*sc->values == NULL) {
 67         n = (sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
 68                               + sizeof(ngx_http_script_var_code_t))
 69                 + sizeof(uintptr_t)
 70                 + sc->source->len
 71                 + sizeof(uintptr_t) - 1)
 72             & ~(sizeof(uintptr_t) - 1);
 73 
 74         *sc->values = ngx_array_create(sc->cf->pool, n, 1);
 75         if (*sc->values == NULL) {
 76             return NGX_ERROR;
 77         }
 78     }
 79 
 80     sc->variables = 0;
 81 
 82     for (i = 0; i < sc->source->len; /* void */ ) {
 83 
 84         name.len = 0;
 85 
 86         if (sc->source->data[i] == '$') {
 87 
 88             if (++i == sc->source->len) {
 89                 goto invalid_variable;
 90             }
 91 
 92             if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
 93 
 94                 n = sc->source->data[i] - '';
 95 
 96                 if (sc->captures_mask & (1 << n)) {
 97                     sc->dup_capture = 1;
 98                 }
 99 
100                 sc->captures_mask |= 1 << n;
101 
102                 copy_capture = ngx_http_script_add_code(*sc->lengths,
103                                    sizeof(ngx_http_script_copy_capture_code_t),
104                                    NULL);
105                 if (copy_capture == NULL) {
106                     return NGX_ERROR;
107                 }
108 
109                 copy_capture->code = (ngx_http_script_code_pt)
110                                          ngx_http_script_copy_capture_len_code;
111                 copy_capture->n = 2 * n;
112 
113 
114                 copy_capture = ngx_http_script_add_code(*sc->values,
115                                    sizeof(ngx_http_script_copy_capture_code_t),
116                                    &sc->main);
117                 if (copy_capture == NULL) {
118                     return NGX_ERROR;
119                 }
120 
121                 copy_capture->code = ngx_http_script_copy_capture_code;
122                 copy_capture->n = 2 * n;
123 
124                 if (sc->ncaptures < n) {
125                     sc->ncaptures = n;
126                 }
127 
128                 i++;
129 
130                 continue;
131             }
132 
133             if (sc->source->data[i] == '{') {
134                 bracket = 1;
135 
136                 if (++i == sc->source->len) {
137                     goto invalid_variable;
138                 }
139 
140                 name.data = &sc->source->data[i];
141 
142             } else {
143                 bracket = 0;
144                 name.data = &sc->source->data[i];
145             }
146 
147             for ( /* void */ ; i < sc->source->len; i++, name.len++) {
148                 ch = sc->source->data[i];
149 
150                 if (ch == '}' && bracket) {
151                     i++;
152                     bracket = 0;
153                     break;
154                 }
155 
156                 if ((ch >= 'A' && ch <= 'Z')
157                     || (ch >= 'a' && ch <= 'z')
158                     || (ch >= '' && ch <= '9')
159                     || ch == '_')
160                 {
161                     continue;
162                 }
163 
164                 break;
165             }
166 
167             if (bracket) {
168                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
169                                    "the closing bracket in \"%V\" "
170                                    "variable is missing", &name);
171                 return NGX_ERROR;
172             }
173 
174             if (name.len == 0) {
175                 goto invalid_variable;
176             }
177 
178             sc->variables++;
179 
180             index = ngx_http_get_variable_index(sc->cf, &name);
181 
182             if (index == NGX_ERROR) {
183                 return NGX_ERROR;
184             }
185 
186             if (sc->flushes) {
187                 p = ngx_array_push(*sc->flushes);
188                 if (p == NULL) {
189                     return NGX_ERROR;
190                 }
191 
192                 *p = index;
193             }
194 
195             var_code = ngx_http_script_add_code(*sc->lengths,
196                                             sizeof(ngx_http_script_var_code_t),
197                                             NULL);
198             if (var_code == NULL) {
199                 return NGX_ERROR;
200             }
201 
202             var_code->code = (ngx_http_script_code_pt)
203                                             ngx_http_script_copy_var_len_code;
204             var_code->index = (uintptr_t) index;
205 
206 
207             var_code = ngx_http_script_add_code(*sc->values,
208                                             sizeof(ngx_http_script_var_code_t),
209                                             &sc->main);
210             if (var_code == NULL) {
211                 return NGX_ERROR;
212             }
213 
214             var_code->code = ngx_http_script_copy_var_code;
215             var_code->index = (uintptr_t) index;
216 
217             continue;
218         }
219 
220         if (sc->source->data[i] == '?' && sc->compile_args) {
221             sc->args = 1;
222             sc->compile_args = 0;
223 
224             code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
225                                             &sc->main);
226             if (code == NULL) {
227                 return NGX_ERROR;
228             }
229 
230             *code = (uintptr_t) ngx_http_script_start_args_code;
231 
232             i++;
233 
234             continue;
235         }
236 
237         name.data = &sc->source->data[i];
238 
239         while (i < sc->source->len
240                && sc->source->data[i] != '$'
241                && !(sc->source->data[i] == '?' && sc->compile_args))
242         {
243             i++;
244             name.len++;
245         }
246 
247         sc->size += name.len;
248 
249         copy = ngx_http_script_add_code(*sc->lengths,
250                                         sizeof(ngx_http_script_copy_code_t),
251                                         NULL);
252         if (copy == NULL) {
253             return NGX_ERROR;
254         }
255 
256         copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
257         copy->len = name.len;
258 
259         size = (sizeof(ngx_http_script_copy_code_t) + name.len
260                    + sizeof(uintptr_t) - 1)
261                 & ~(sizeof(uintptr_t) - 1);
262 
263         copy = ngx_http_script_add_code(*sc->values, size, &sc->main);
264         if (copy == NULL) {
265             return NGX_ERROR;
266         }
267 
268         copy->code = ngx_http_script_copy_code;
269         copy->len = name.len;
270 
271         ngx_memcpy((u_char *) copy + sizeof(ngx_http_script_copy_code_t),
272                    name.data, name.len);
273     }
274 
275     if (sc->complete_lengths) {
276         code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
277         if (code == NULL) {
278             return NGX_ERROR;
279         }
280 
281         *code = (uintptr_t) NULL;
282     }
283 
284     if (sc->complete_values) {
285         code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
286                                         &sc->main);
287         if (code == NULL) {
288             return NGX_ERROR;
289         }
290 
291         *code = (uintptr_t) NULL;
292     }
293 
294     return NGX_OK;
295 
296 invalid_variable:
297 
298     ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");
299 
300     return NGX_ERROR;
301 }
302 
303 
304 u_char *
305 ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,
306     void *code_lengths, size_t len, void *code_values)
307 {
308     ngx_uint_t                    i;
309     ngx_http_script_code_pt       code;
310     ngx_http_script_len_code_pt   lcode;
311     ngx_http_script_engine_t      e;
312     ngx_http_core_main_conf_t    *cmcf;
313 
314     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
315 
316     for (i = 0; i < cmcf->variables.nelts; i++) {
317         if (r->variables[i].no_cacheable) {
318             r->variables[i].valid = 0;
319             r->variables[i].not_found = 0;
320         }
321     }
322 
323     ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
324 
325     e.ip = code_lengths;
326     e.request = r;
327     e.flushed = 1;
328 
329     while (*(uintptr_t *) e.ip) {
330         lcode = *(ngx_http_script_len_code_pt *) e.ip;
331         len += lcode(&e);
332     }
333 
334 
335     value->len = len;
336     value->data = ngx_palloc(r->pool, len);
337     if (value->data == NULL) {
338         return NULL;
339     }
340 
341     e.ip = code_values;
342     e.pos = value->data;
343 
344     while (*(uintptr_t *) e.ip) {
345         code = *(ngx_http_script_code_pt *) e.ip;
346         code((ngx_http_script_engine_t *) &e);
347     }
348 
349     return e.pos;
350 }
351 
352 
353 void
354 ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r,
355     ngx_array_t *indices)
356 {
357     ngx_uint_t  n, *index;
358 
359     if (indices) {
360         index = indices->elts;
361         for (n = 0; n < indices->nelts; n++) {
362             if (r->variables[index[n]].no_cacheable) {
363                 r->variables[index[n]].valid = 0;
364                 r->variables[index[n]].not_found = 0;
365             }
366         }
367     }
368 }
369 
370 
371 void *
372 ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
373 {
374     if (*codes == NULL) {
375         *codes = ngx_array_create(pool, 256, 1);
376         if (*codes == NULL) {
377             return NULL;
378         }
379     }
380 
381     return ngx_array_push_n(*codes, size);
382 }
383 
384 
385 void *
386 ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code)
387 {
388     u_char  *elts, **p;
389     void    *new;
390 
391     elts = codes->elts;
392 
393     new = ngx_array_push_n(codes, size);
394     if (new == NULL) {
395         return NGX_CONF_ERROR;
396     }
397 
398     if (code) {
399         if (elts != codes->elts) {
400             p = code;
401             *p += (u_char *) codes->elts - elts;
402         }
403     }
404 
405     return new;
406 }
407 
408 
409 size_t
410 ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
411 {
412     ngx_http_script_copy_code_t  *code;
413 
414     code = (ngx_http_script_copy_code_t *) e->ip;
415 
416     e->ip += sizeof(ngx_http_script_copy_code_t);
417 
418     return code->len;
419 }
420 
421 
422 void
423 ngx_http_script_copy_code(ngx_http_script_engine_t *e)
424 {
425     ngx_http_script_copy_code_t  *code;
426 
427     code = (ngx_http_script_copy_code_t *) e->ip;
428 
429     if (!e->skip) {
430         e->pos = ngx_copy(e->pos, e->ip + sizeof(ngx_http_script_copy_code_t),
431                           code->len);
432     }
433 
434     e->ip += sizeof(ngx_http_script_copy_code_t)
435           + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
436 
437     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
438                    "http script copy: \"%V\"", &e->buf);
439 }
440 
441 
442 size_t
443 ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
444 {
445     ngx_http_variable_value_t   *value;
446     ngx_http_script_var_code_t  *code;
447 
448     code = (ngx_http_script_var_code_t *) e->ip;
449 
450     e->ip += sizeof(ngx_http_script_var_code_t);
451 
452     if (e->flushed) {
453         value = ngx_http_get_indexed_variable(e->request, code->index);
454 
455     } else {
456         value = ngx_http_get_flushed_variable(e->request, code->index);
457     }
458 
459     if (value && !value->not_found) {
460         return value->len;
461     }
462 
463     return 0;
464 }
465 
466 
467 void
468 ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
469 {
470     ngx_http_variable_value_t   *value;
471     ngx_http_script_var_code_t  *code;
472 
473     code = (ngx_http_script_var_code_t *) e->ip;
474 
475     e->ip += sizeof(ngx_http_script_var_code_t);
476 
477     if (!e->skip) {
478 
479         if (e->flushed) {
480             value = ngx_http_get_indexed_variable(e->request, code->index);
481 
482         } else {
483             value = ngx_http_get_flushed_variable(e->request, code->index);
484         }
485 
486         if (value && !value->not_found) {
487             e->pos = ngx_copy(e->pos, value->data, value->len);
488 
489             ngx_log_debug1(NGX_LOG_DEBUG_HTTP,
490                            e->request->connection->log, 0,
491                            "http script var: \"%V\"", &e->buf);
492         }
493     }
494 }
495 
496 
497 size_t
498 ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
499 {
500     ngx_http_script_copy_capture_code_t  *code;
501 
502     code = (ngx_http_script_copy_capture_code_t *) e->ip;
503 
504     e->ip += sizeof(ngx_http_script_copy_capture_code_t);
505 
506     if (code->n < e->ncaptures) {
507         if ((e->args || e->quote)
508             && (e->request->quoted_uri || e->request->plus_in_uri))
509         {
510             return e->captures[code->n + 1] - e->captures[code->n]
511                    + 2 * ngx_escape_uri(NULL,
512                                 &e->line.data[e->captures[code->n]],
513                                 e->captures[code->n + 1] - e->captures[code->n],
514                                 NGX_ESCAPE_ARGS);
515         } else {
516             return e->captures[code->n + 1] - e->captures[code->n];
517         }
518     }
519 
520     return 0;
521 }
522 
523 
524 void
525 ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
526 {
527     ngx_http_script_copy_capture_code_t  *code;
528 
529     code = (ngx_http_script_copy_capture_code_t *) e->ip;
530 
531     e->ip += sizeof(ngx_http_script_copy_capture_code_t);
532 
533     if (code->n < e->ncaptures) {
534         if ((e->args || e->quote)
535             && (e->request->quoted_uri || e->request->plus_in_uri))
536         {
537             e->pos = (u_char *) ngx_escape_uri(e->pos,
538                                 &e->line.data[e->captures[code->n]],
539                                 e->captures[code->n + 1] - e->captures[code->n],
540                                 NGX_ESCAPE_ARGS);
541         } else {
542             e->pos = ngx_copy(e->pos,
543                               &e->line.data[e->captures[code->n]],
544                               e->captures[code->n + 1] - e->captures[code->n]);
545         }
546     }
547 
548     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
549                    "http script capture: \"%V\"", &e->buf);
550 }
551 
552 
553 void
554 ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
555 {
556     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
557                    "http script args");
558 
559     e->args = e->pos;
560     e->ip += sizeof(uintptr_t);
561 }
562 
563 
564 
565 #if (NGX_PCRE)
566 
567 void
568 ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
569 {
570     size_t                         len;
571     ngx_int_t                      rc;
572     ngx_uint_t                     n;
573     ngx_http_request_t            *r;
574     ngx_http_script_engine_t       le;
575     ngx_http_script_len_code_pt    lcode;
576     ngx_http_script_regex_code_t  *code;
577 
578     code = (ngx_http_script_regex_code_t *) e->ip;
579 
580     r = e->request;
581 
582     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
583                    "http script regex: \"%V\"", &code->name);
584 
585     if (code->uri) {
586         e->line = r->uri;
587     } else {
588         e->sp--;
589         e->line.len = e->sp->len;
590         e->line.data = e->sp->data;
591     }
592 
593     rc = ngx_regex_exec(code->regex, &e->line, e->captures, code->ncaptures);
594 
595     if (rc == NGX_REGEX_NO_MATCHED) {
596         if (e->log) {
597             ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
598                           "\"%V\" does not match \"%V\"",
599                           &code->name, &e->line);
600         }
601 
602         e->ncaptures = 0;
603 
604         if (code->test) {
605             if (code->negative_test) {
606                 e->sp->len = 1;
607                 e->sp->data = (u_char *) "1";
608 
609             } else {
610                 e->sp->len = 0;
611                 e->sp->data = (u_char *) "";
612             }
613 
614             e->sp++;
615 
616             e->ip += sizeof(ngx_http_script_regex_code_t);
617             return;
618         }
619 
620         e->ip += code->next;
621         return;
622     }
623 
624     if (rc < 0) {
625         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
626                       ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
627                       rc, &e->line, &code->name);
628 
629         e->ip = ngx_http_script_exit;
630         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
631         return;
632     }
633 
634     if (e->log) {
635         ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
636                       "\"%V\" matches \"%V\"", &code->name, &e->line);
637     }
638 
639     e->ncaptures = code->ncaptures;
640 
641     if (code->test) {
642         if (code->negative_test) {
643             e->sp->len = 0;
644             e->sp->data = (u_char *) "";
645 
646         } else {
647             e->sp->len = 1;
648             e->sp->data = (u_char *) "1";
649         }
650 
651         e->sp++;
652 
653         e->ip += sizeof(ngx_http_script_regex_code_t);
654         return;
655     }
656 
657     if (code->status) {
658         e->status = code->status;
659 
660         if (!code->redirect) {
661             e->ip = ngx_http_script_exit;
662             return;
663         }
664     }
665 
666     if (code->uri) {
667         r->internal = 1;
668         r->valid_unparsed_uri = 0;
669 
670         if (code->break_cycle) {
671             r->valid_location = 0;
672             r->uri_changed = 0;
673 
674         } else {
675             r->uri_changed = 1;
676         }
677     }
678 
679     if (code->lengths == NULL) {
680         e->buf.len = code->size;
681 
682         if (code->uri) {
683             if (rc && (r->quoted_uri || r->plus_in_uri)) {
684                 e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
685                                                  NGX_ESCAPE_ARGS);
686             }
687         }
688 
689         for (n = 1; n < (ngx_uint_t) rc; n++) {
690             e->buf.len += e->captures[2 * n + 1] - e->captures[2 * n];
691         }
692 
693     } else {
694         ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
695 
696         le.ip = code->lengths->elts;
697         le.line = e->line;
698         le.request = r;
699         le.captures = e->captures;
700         le.ncaptures = e->ncaptures;
701         le.quote = code->redirect;
702 
703         len = 1;  /* reserve 1 byte for possible "?" */
704 
705         while (*(uintptr_t *) le.ip) {
706             lcode = *(ngx_http_script_len_code_pt *) le.ip;
707             len += lcode(&le);
708         }
709 
710         e->buf.len = len;
711     }
712 
713     if (code->add_args && r->args.len) {
714         e->buf.len += r->args.len + 1;
715     }
716 
717     e->buf.data = ngx_palloc(r->pool, e->buf.len);
718     if (e->buf.data == NULL) {
719         e->ip = ngx_http_script_exit;
720         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
721         return;
722     }
723 
724     e->quote = code->redirect;
725 
726     e->pos = e->buf.data;
727 
728     e->ip += sizeof(ngx_http_script_regex_code_t);
729 }
730 
731 
732 void
733 ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
734 {
735     u_char                            *dst, *src;
736     ngx_http_request_t                *r;
737     ngx_http_script_regex_end_code_t  *code;
738 
739     code = (ngx_http_script_regex_end_code_t *) e->ip;
740 
741     r = e->request;
742 
743     e->quote = 0;
744 
745     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
746                    "http script regex end");
747 
748     if (code->redirect) {
749 
750         dst = e->buf.data;
751         src = e->buf.data;
752 
753         ngx_unescape_uri(&dst, &src, e->pos - e->buf.data,
754                          NGX_UNESCAPE_REDIRECT);
755 
756         if (src < e->pos) {
757             dst = ngx_copy(dst, src, e->pos - src);
758         }
759 
760         e->pos = dst;
761 
762         if (code->add_args && r->args.len) {
763             *e->pos++ = (u_char) (code->args ? '&' : '?');
764             e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
765         }
766 
767         e->buf.len = e->pos - e->buf.data;
768 
769         if (e->log) {
770             ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
771                           "rewritten redirect: \"%V\"", &e->buf);
772         }
773 
774         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
775         if (r->headers_out.location == NULL) {
776             e->ip = ngx_http_script_exit;
777             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
778             return;
779         }
780 
781         r->headers_out.location->hash = 1;
782         r->headers_out.location->key.len = sizeof("Location") - 1;
783         r->headers_out.location->key.data = (u_char *) "Location";
784         r->headers_out.location->value = e->buf;
785 
786         e->ip += sizeof(ngx_http_script_regex_end_code_t);
787         return;
788     }
789 
790     if (e->args) {
791         e->buf.len = e->args - e->buf.data;
792 
793         if (code->add_args && r->args.len) {
794             *e->pos++ = '&';
795             e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
796         }
797 
798         r->args.len = e->pos - e->args;
799         r->args.data = e->args;
800 
801         e->args = NULL;
802 
803     } else {
804         e->buf.len = e->pos - e->buf.data;
805 
806         if (!code->add_args) {
807             r->args.len = 0;
808         }
809     }
810 
811     if (e->log) {
812         ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
813                       "rewritten data: \"%V\", args: \"%V\"",
814                       &e->buf, &r->args);
815     }
816 
817     if (code->uri) {
818         r->uri = e->buf;
819 
820         if (r->uri.len == 0) {
821             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
822                           "the rewritten URI has a zero length");
823             e->ip = ngx_http_script_exit;
824             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
825             return;
826         }
827 
828         if (ngx_http_set_exten(r) != NGX_OK) {
829             e->ip = ngx_http_script_exit;
830             e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
831             return;
832         }
833     }
834 
835     e->ip += sizeof(ngx_http_script_regex_end_code_t);
836 }
837 
838 #endif
839 
840 
841 void
842 ngx_http_script_return_code(ngx_http_script_engine_t *e)
843 {
844     ngx_http_script_return_code_t  *code;
845 
846     code = (ngx_http_script_return_code_t *) e->ip;
847 
848     e->status = code->status;
849 
850     if (code->status == NGX_HTTP_NO_CONTENT) {
851         e->request->header_only = 1;
852         e->request->zero_body = 1;
853     }
854 
855     e->ip += sizeof(ngx_http_script_return_code_t) - sizeof(uintptr_t);
856 }
857 
858 
859 void
860 ngx_http_script_break_code(ngx_http_script_engine_t *e)
861 {
862     e->request->uri_changed = 0;
863 
864     e->ip = ngx_http_script_exit;
865 }
866 
867 
868 void
869 ngx_http_script_if_code(ngx_http_script_engine_t *e)
870 {
871     ngx_http_script_if_code_t  *code;
872 
873     code = (ngx_http_script_if_code_t *) e->ip;
874 
875     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
876                    "http script if");
877 
878     e->sp--;
879 
880     if (e->sp->len && e->sp->data[0] != '') {
881         if (code->loc_conf) {
882             e->request->loc_conf = code->loc_conf;
883             ngx_http_update_location_config(e->request);
884         }
885 
886         e->ip += sizeof(ngx_http_script_if_code_t);
887         return;
888     }
889 
890     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
891                    "http script if: false");
892 
893     e->ip += code->next;
894 }
895 
896 
897 void
898 ngx_http_script_equal_code(ngx_http_script_engine_t *e)
899 {
900     ngx_http_variable_value_t  *val, *res;
901 
902     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
903                    "http script equal");
904 
905     e->sp--;
906     val = e->sp;
907     res = e->sp - 1;
908 
909     e->ip += sizeof(uintptr_t);
910 
911     if (val->len == res->len && ngx_strncmp(val->data, res->data, res->len)
912         == 0)
913     {
914         *res = ngx_http_variable_true_value;
915         return;
916     }
917 
918     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
919                    "http script equal: no");
920 
921     *res = ngx_http_variable_null_value;
922 }
923 
924 
925 void
926 ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
927 {
928     ngx_http_variable_value_t  *val, *res;
929 
930     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
931                    "http script not equal");
932 
933     e->sp--;
934     val = e->sp;
935     res = e->sp - 1;
936 
937     e->ip += sizeof(uintptr_t);
938 
939     if (val->len == res->len && ngx_strncmp(val->data, res->data, res->len)
940         == 0)
941     {
942         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
943                        "http script not equal: no");
944 
945         *res = ngx_http_variable_null_value;
946         return;
947     }
948 
949     *res = ngx_http_variable_true_value;
950 }
951 
952 
953 void
954 ngx_http_script_file_code(ngx_http_script_engine_t *e)
955 {
956     ngx_str_t                     path;
957     ngx_http_request_t           *r;
958     ngx_open_file_info_t          of;
959     ngx_http_core_loc_conf_t     *clcf;
960     ngx_http_variable_value_t    *value;
961     ngx_http_script_file_code_t  *code;
962 
963     value = e->sp - 1;
964 
965     code = (ngx_http_script_file_code_t *) e->ip;
966     e->ip += sizeof(ngx_http_script_file_code_t);
967 
968     path.len = value->len - 1;
969     path.data = value->data;
970 
971     r = e->request;
972 
973     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
974                    "http script file op %p \"%V\"", code->op, &path);
975 
976     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
977 
978     of.test_dir = 0;
979     of.valid = clcf->open_file_cache_valid;
980     of.min_uses = clcf->open_file_cache_min_uses;
981     of.errors = clcf->open_file_cache_errors;
982     of.events = clcf->open_file_cache_events;
983 
984     if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
985         != NGX_OK)
986     {
987         if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) {
988             ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
989                           ngx_file_info_n " \"%s\" failed", value->data);
990         }
991 
992         switch (code->op) {
993 
994         case ngx_http_script_file_plain:
995         case ngx_http_script_file_dir:
996         case ngx_http_script_file_exists:
997         case ngx_http_script_file_exec:
998              goto false;
999 
1000         case ngx_http_script_file_not_plain:
1001         case ngx_http_script_file_not_dir:
1002         case ngx_http_script_file_not_exists:
1003         case ngx_http_script_file_not_exec:
1004              goto true;
1005         }
1006 
1007         goto false;
1008     }
1009 
1010     switch (code->op) {
1011     case ngx_http_script_file_plain:
1012         if (of.is_file) {
1013              goto true;
1014         }
1015         goto false;
1016 
1017     case ngx_http_script_file_not_plain:
1018         if (of.is_file) {
1019             goto false;
1020         }
1021         goto true;
1022 
1023     case ngx_http_script_file_dir:
1024         if (of.is_dir) {
1025              goto true;
1026         }
1027         goto false;
1028 
1029     case ngx_http_script_file_not_dir:
1030         if (of.is_dir) {
1031             goto false;
1032         }
1033         goto true;
1034 
1035     case ngx_http_script_file_exists:
1036         if (of.is_file || of.is_dir || of.is_link) {
1037              goto true;
1038         }
1039         goto false;
1040 
1041     case ngx_http_script_file_not_exists:
1042         if (of.is_file || of.is_dir || of.is_link) {
1043             goto false;
1044         }
1045         goto true;
1046 
1047     case ngx_http_script_file_exec:
1048         if (of.is_exec) {
1049              goto true;
1050         }
1051         goto false;
1052 
1053     case ngx_http_script_file_not_exec:
1054         if (of.is_exec) {
1055             goto false;
1056         }
1057         goto true;
1058     }
1059 
1060 false:
1061 
1062     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1063                    "http script file op false");
1064 
1065     *value = ngx_http_variable_null_value;
1066     return;
1067 
1068 true:
1069 
1070     *value = ngx_http_variable_true_value;
1071     return;
1072 }
1073 
1074 
1075 void
1076 ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
1077 {
1078     size_t                                 len;
1079     ngx_http_script_engine_t               le;
1080     ngx_http_script_len_code_pt            lcode;
1081     ngx_http_script_complex_value_code_t  *code;
1082 
1083     code = (ngx_http_script_complex_value_code_t *) e->ip;
1084 
1085     e->ip += sizeof(ngx_http_script_complex_value_code_t);
1086 
1087     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1088                    "http script complex value");
1089 
1090     ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
1091 
1092     le.ip = code->lengths->elts;
1093     le.line = e->line;
1094     le.request = e->request;
1095     le.captures = e->captures;
1096     le.ncaptures = e->ncaptures;
1097     le.quote = e->quote;
1098 
1099     for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
1100         lcode = *(ngx_http_script_len_code_pt *) le.ip;
1101     }
1102 
1103     e->buf.len = len;
1104     e->buf.data = ngx_palloc(e->request->pool, len);
1105     if (e->buf.data == NULL) {
1106         e->ip = ngx_http_script_exit;
1107         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1108         return;
1109     }
1110 
1111     e->pos = e->buf.data;
1112 
1113     e->sp->len = e->buf.len;
1114     e->sp->data = e->buf.data;
1115     e->sp++;
1116 }
1117 
1118 
1119 void
1120 ngx_http_script_value_code(ngx_http_script_engine_t *e)
1121 {
1122     ngx_http_script_value_code_t  *code;
1123