comparison src/http/ngx_http_script.c @ 509:9b8c906f6e63 release-0.1.29

nginx-0.1.29-RELEASE import *) Feature: the ngx_http_ssi_module supports "include virtual" command. *) Feature: the ngx_http_ssi_module supports the condition command like 'if expr="$NAME"' and "else" and "endif" commands. Only one nested level is supported. *) Feature: the ngx_http_ssi_module supports the DATE_LOCAL and DATE_GMT variables and "config timefmt" command. *) Feature: the "ssi_ignore_recycled_buffers" directive. *) Bugfix: the "echo" command did not show the default value for the empty QUERY_STRING variable. *) Change: the ngx_http_proxy_module was rewritten. *) Feature: the "proxy_redirect", "proxy_pass_request_headers", "proxy_pass_request_body", and "proxy_method" directives. *) Feature: the "proxy_set_header" directive. The "proxy_x_var" was canceled and must be replaced with the proxy_set_header directive. *) Change: the "proxy_preserve_host" is canceled and must be replaced with the "proxy_set_header Host $host" and the "proxy_redirect off" directives, the "proxy_set_header Host $host:$proxy_port" directive and the appropriate proxy_redirect directives. *) Change: the "proxy_set_x_real_ip" is canceled and must be replaced with the "proxy_set_header X-Real-IP $remote_addr" directive. *) Change: the "proxy_add_x_forwarded_for" is canceled and must be replaced with the "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for" directive. *) Change: the "proxy_set_x_url" is canceled and must be replaced with the "proxy_set_header X-URL http://$host:$server_port$request_uri" directive. *) Feature: the "fastcgi_param" directive. *) Change: the "fastcgi_root", "fastcgi_set_var" and "fastcgi_params" directive are canceled and must be replaced with the fastcgi_param directives. *) Feature: the "index" directive can use the variables. *) Feature: the "index" directive can be used at http and server levels. *) Change: the last index only in the "index" directive can be absolute. *) Feature: the "rewrite" directive can use the variables. *) Feature: the "internal" directive. *) Feature: the CONTENT_LENGTH, CONTENT_TYPE, REMOTE_PORT, SERVER_ADDR, SERVER_PORT, SERVER_PROTOCOL, DOCUMENT_ROOT, SERVER_NAME, REQUEST_METHOD, REQUEST_URI, and REMOTE_USER variables. *) Change: nginx now passes the invalid lines in a client request headers or a backend response header. *) Bugfix: if the backend did not transfer response for a long time and the "send_timeout" was less than "proxy_read_timeout", then nginx returned the 408 response. *) Bugfix: the segmentation fault was occurred if the backend sent an invalid line in response header; the bug had appeared in 0.1.26. *) Bugfix: the segmentation fault may occurred in FastCGI fault tolerance configuration. *) Bugfix: the "expires" directive did not remove the previous "Expires" and "Cache-Control" headers. *) Bugfix: nginx did not take into account trailing dot in "Host" header line. *) Bugfix: the ngx_http_auth_module did not work under Linux. *) Bugfix: the rewrite directive worked incorrectly, if the arguments were in a request. *) Bugfix: nginx could not be built on MacOS X.
author Igor Sysoev <igor@sysoev.ru>
date Thu, 12 May 2005 14:58:06 +0000
parents cd3117ad9aab
children 417a087c9c4d
comparison
equal deleted inserted replaced
508:ca1020ce99ba 509:9b8c906f6e63
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_http.h> 9 #include <ngx_http.h>
10 10
11 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
12 ngx_int_t 32 ngx_int_t
13 ngx_http_script_compile_lite(ngx_conf_t *cf, ngx_array_t *sources, 33 ngx_http_script_compile(ngx_http_script_compile_t *sc)
14 ngx_array_t **lengths, ngx_array_t **values, 34 {
15 ngx_http_script_compile_lite_start_pt start, 35 u_char ch;
16 ngx_http_script_compile_lite_end_pt end) 36 size_t size;
17 { 37 ngx_int_t index;
18 uintptr_t *code; 38 ngx_str_t name;
19 ngx_uint_t i; 39 uintptr_t *code;
20 ngx_table_elt_t *src; 40 ngx_uint_t i, n, bracket;
21 ngx_http_variable_t *var; 41 ngx_http_script_var_code_t *var_code;
22 ngx_http_script_var_code_t *var_code; 42 ngx_http_script_copy_code_t *copy;
23 43 ngx_http_script_copy_capture_code_t *copy_capture;
24 if (sources->nelts == 0) { 44
25 return NGX_OK; 45 if (*sc->lengths == NULL) {
26 } 46 n = sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
27 47 + sizeof(ngx_http_script_var_code_t))
28 if (*lengths == NULL) { 48 + sizeof(uintptr_t);
29 *lengths = ngx_array_create(cf->pool, 64, 1); 49
30 if (*lengths == NULL) { 50 *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
51 if (*sc->lengths == NULL) {
31 return NGX_ERROR; 52 return NGX_ERROR;
32 } 53 }
33 } 54 }
34 55
35 if (*values == NULL) { 56
36 *values = ngx_array_create(cf->pool, 256, 1); 57 if (*sc->values == NULL) {
37 if (*values == NULL) { 58 n = (sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
59 + sizeof(ngx_http_script_var_code_t))
60 + sizeof(uintptr_t)
61 + sc->source->len
62 + sizeof(uintptr_t) - 1)
63 & ~(sizeof(uintptr_t) - 1);
64
65 *sc->values = ngx_array_create(sc->cf->pool, n, 1);
66 if (*sc->values == NULL) {
38 return NGX_ERROR; 67 return NGX_ERROR;
39 } 68 }
40 } 69 }
41 70
42 src = sources->elts; 71 sc->variables = 0;
43 for (i = 0; i < sources->nelts; i++) { 72
44 73 for (i = 0; i < sc->source->len; /* void */ ) {
45 if (src[i].value.data[0] == '$') { 74
46 if (start(&src[i], *lengths, *values, 0) != NGX_OK) { 75 name.len = 0;
76
77 if (sc->source->data[i] == '$') {
78
79 if (++i == sc->source->len) {
80 goto invalid_variable;
81 }
82
83 if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
84
85 copy_capture = ngx_http_script_add_code(*sc->lengths,
86 sizeof(ngx_http_script_copy_capture_code_t),
87 NULL);
88 if (copy_capture == NULL) {
89 return NGX_ERROR;
90 }
91
92 copy_capture->code = (ngx_http_script_code_pt)
93 ngx_http_script_copy_capture_len_code;
94 copy_capture->n = 2 * (sc->source->data[i] - '0');
95
96 copy_capture = ngx_http_script_add_code(*sc->values,
97 sizeof(ngx_http_script_copy_capture_code_t),
98 &sc->main);
99 if (copy_capture == NULL) {
100 return NGX_ERROR;
101 }
102
103 copy_capture->code = ngx_http_script_copy_capture_code;
104 copy_capture->n = sc->source->data[i] - '0';
105
106 if (sc->ncaptures < copy_capture->n) {
107 sc->ncaptures = copy_capture->n;
108 }
109
110 copy_capture->n *= 2;
111
112 i++;
113
114 continue;
115 }
116
117 if (sc->source->data[i] == '{') {
118 bracket = 1;
119
120 if (++i == sc->source->len) {
121 goto invalid_variable;
122 }
123
124 name.data = &sc->source->data[i];
125
126 } else {
127 bracket = 0;
128 name.data = &sc->source->data[i];
129 }
130
131 for ( /* void */ ; i < sc->source->len; i++, name.len++) {
132 ch = sc->source->data[i];
133
134 if (ch == '}' && bracket) {
135 i++;
136 bracket = 0;
137 break;
138 }
139
140 if ((ch >= 'A' && ch <= 'Z')
141 || (ch >= 'a' && ch <= 'z')
142 || (ch >= '0' && ch <= '9')
143 || ch == '_')
144 {
145 continue;
146 }
147
148 break;
149 }
150
151 if (bracket) {
152 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
153 "the closing bracket in \"%V\" "
154 "variable is missing", &name);
47 return NGX_ERROR; 155 return NGX_ERROR;
48 } 156 }
49 157
50 src[i].value.len--; 158 if (name.len == 0) {
51 src[i].value.data++; 159 goto invalid_variable;
52 160 }
53 var = ngx_http_add_variable(cf, &src[i].value, 0); 161
54 162 sc->variables++;
55 if (var == NULL) { 163
164 index = ngx_http_get_variable_index(sc->cf, &name);
165
166 if (index == NGX_ERROR) {
56 return NGX_ERROR; 167 return NGX_ERROR;
57 } 168 }
58 169
59 var_code = ngx_array_push_n(*lengths, 170 var_code = ngx_http_script_add_code(*sc->lengths,
60 sizeof(ngx_http_script_var_code_t)); 171 sizeof(ngx_http_script_var_code_t),
172 NULL);
61 if (var_code == NULL) { 173 if (var_code == NULL) {
62 return NGX_ERROR; 174 return NGX_ERROR;
63 } 175 }
64 176
65 var_code->code = (ngx_http_script_code_pt) 177 var_code->code = (ngx_http_script_code_pt)
66 ngx_http_script_copy_var_len; 178 ngx_http_script_copy_var_len_code;
67 var_code->index = var->index; 179 var_code->index = (uintptr_t) index;
68 180
69 181
70 var_code = ngx_array_push_n(*values, 182 var_code = ngx_http_script_add_code(*sc->values,
71 sizeof(ngx_http_script_var_code_t)); 183 sizeof(ngx_http_script_var_code_t),
184 &sc->main);
72 if (var_code == NULL) { 185 if (var_code == NULL) {
73 return NGX_ERROR; 186 return NGX_ERROR;
74 } 187 }
75 188
76 var_code->code = ngx_http_script_copy_var; 189 var_code->code = ngx_http_script_copy_var_code;
77 var_code->index = var->index; 190 var_code->index = (uintptr_t) index;
78 191
79 192 continue;
80 if (end(*lengths, *values) != NGX_OK) { 193 }
194
195 if (sc->source->data[i] == '?' && sc->compile_args) {
196 sc->args = 1;
197 sc->compile_args = 0;
198
199 code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
200 &sc->main);
201 if (code == NULL) {
81 return NGX_ERROR; 202 return NGX_ERROR;
82 } 203 }
83 204
205 *code = (uintptr_t) ngx_http_script_start_args_code;
206
207 i++;
208
84 continue; 209 continue;
85 } 210 }
86 211
87 if (start(&src[i], *lengths, *values, 1) != NGX_OK) { 212 name.data = &sc->source->data[i];
213
214 while (i < sc->source->len
215 && sc->source->data[i] != '$'
216 && !(sc->source->data[i] == '?' && sc->compile_args))
217 {
218 i++;
219 name.len++;
220 }
221
222 sc->size += name.len;
223
224 copy = ngx_http_script_add_code(*sc->lengths,
225 sizeof(ngx_http_script_copy_code_t),
226 NULL);
227 if (copy == NULL) {
88 return NGX_ERROR; 228 return NGX_ERROR;
89 } 229 }
90 } 230
91 231 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
92 code = ngx_array_push_n(*lengths, sizeof(uintptr_t)); 232 copy->len = name.len;
93 if (code == NULL) { 233
94 return NGX_ERROR; 234 size = (sizeof(ngx_http_script_copy_code_t) + name.len
95 } 235 + sizeof(uintptr_t) - 1)
96 236 & ~(sizeof(uintptr_t) - 1);
97 *code = (uintptr_t) NULL; 237
98 238 copy = ngx_http_script_add_code(*sc->values, size, &sc->main);
99 code = ngx_array_push_n(*values, sizeof(uintptr_t)); 239 if (copy == NULL) {
100 if (code == NULL) { 240 return NGX_ERROR;
101 return NGX_ERROR; 241 }
102 } 242
103 243 copy->code = ngx_http_script_copy_code;
104 *code = (uintptr_t) NULL; 244 copy->len = name.len;
245
246 ngx_memcpy((u_char *) copy + sizeof(ngx_http_script_copy_code_t),
247 name.data, name.len);
248 }
249
250 if (sc->complete_lengths) {
251 code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
252 if (code == NULL) {
253 return NGX_ERROR;
254 }
255
256 *code = (uintptr_t) NULL;
257 }
258
259 if (sc->complete_values) {
260 code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
261 &sc->main);
262 if (code == NULL) {
263 return NGX_ERROR;
264 }
265
266 *code = (uintptr_t) NULL;
267 }
105 268
106 return NGX_OK; 269 return NGX_OK;
107 } 270
108 271 invalid_variable:
109 272
110 #if 0 273 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");
111 274
112 static void * 275 return NGX_ERROR;
276 }
277
278
279 void *
113 ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size) 280 ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
114 { 281 {
115 if (*codes == NULL) { 282 if (*codes == NULL) {
116 *codes = ngx_array_create(pool, 256, 1); 283 *codes = ngx_array_create(pool, 256, 1);
117 if (*codes == NULL) { 284 if (*codes == NULL) {
120 } 287 }
121 288
122 return ngx_array_push_n(*codes, size); 289 return ngx_array_push_n(*codes, size);
123 } 290 }
124 291
125 #endif 292
293 void *
294 ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code)
295 {
296 u_char *elts, **p;
297 void *new;
298
299 elts = codes->elts;
300
301 new = ngx_array_push_n(codes, size);
302 if (new == NULL) {
303 return NGX_CONF_ERROR;
304 }
305
306 if (code) {
307 if (elts != codes->elts) {
308 p = code;
309 *p += (u_char *) codes->elts - elts;
310 }
311 }
312
313 return new;
314 }
126 315
127 316
128 size_t 317 size_t
129 ngx_http_script_copy_len(ngx_http_script_engine_t *e) 318 ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
130 { 319 {
131 ngx_http_script_copy_code_t *code; 320 ngx_http_script_copy_code_t *code;
132 321
133 code = (ngx_http_script_copy_code_t *) e->lite.ip; 322 code = (ngx_http_script_copy_code_t *) e->ip;
134 323
135 e->lite.ip += sizeof(ngx_http_script_copy_code_t); 324 e->ip += sizeof(ngx_http_script_copy_code_t);
136 325
137 return code->len; 326 return code->len;
138 } 327 }
139 328
140 329
141 void 330 void
142 ngx_http_script_copy(ngx_http_script_engine_t *e) 331 ngx_http_script_copy_code(ngx_http_script_engine_t *e)
143 { 332 {
144 ngx_http_script_copy_code_t *code; 333 ngx_http_script_copy_code_t *code;
145 334
146 code = (ngx_http_script_copy_code_t *) e->lite.ip; 335 code = (ngx_http_script_copy_code_t *) e->ip;
147 336
148 e->lite.pos = ngx_cpymem(e->lite.pos, 337 if (!e->skip) {
149 e->lite.ip + sizeof(ngx_http_script_copy_code_t), 338 e->pos = ngx_cpymem(e->pos, e->ip + sizeof(ngx_http_script_copy_code_t),
150 code->len); 339 code->len);
151 340 }
152 e->lite.ip += sizeof(ngx_http_script_copy_code_t) 341
153 + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1)); 342 e->ip += sizeof(ngx_http_script_copy_code_t)
343 + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
344
345 if (e->log) {
346 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
347 "http script copy: \"%V\"", &e->buf);
348 }
154 } 349 }
155 350
156 351
157 size_t 352 size_t
158 ngx_http_script_copy_var_len(ngx_http_script_engine_t *e) 353 ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
159 { 354 {
160 ngx_http_variable_value_t *value; 355 ngx_http_variable_value_t *value;
161 ngx_http_script_var_code_t *code; 356 ngx_http_script_var_code_t *code;
162 357
163 code = (ngx_http_script_var_code_t *) e->lite.ip; 358 code = (ngx_http_script_var_code_t *) e->ip;
164 359
165 e->lite.ip += sizeof(ngx_http_script_var_code_t); 360 e->ip += sizeof(ngx_http_script_var_code_t);
166 361
167 value = ngx_http_get_indexed_variable(e->lite.request, code->index); 362 value = ngx_http_get_indexed_variable(e->request, code->index);
168 363
169 if (value == NULL || value == NGX_HTTP_VARIABLE_NOT_FOUND) { 364 if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
170 return 0; 365 return 0;
171 } 366 }
172 367
173 return value->text.len; 368 return value->text.len;
174 } 369 }
175 370
176 371
177 void 372 void
178 ngx_http_script_copy_var(ngx_http_script_engine_t *e) 373 ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
179 { 374 {
180 ngx_http_variable_value_t *value; 375 ngx_http_variable_value_t *value;
181 ngx_http_script_var_code_t *code; 376 ngx_http_script_var_code_t *code;
182 377
183 code = (ngx_http_script_var_code_t *) e->lite.ip; 378 code = (ngx_http_script_var_code_t *) e->ip;
184 379
185 e->lite.ip += sizeof(ngx_http_script_var_code_t); 380 e->ip += sizeof(ngx_http_script_var_code_t);
186 381
187 value = ngx_http_get_indexed_variable(e->lite.request, code->index); 382 if (!e->skip) {
188 383 value = ngx_http_get_indexed_variable(e->request, code->index);
189 if (value == NULL || value == NGX_HTTP_VARIABLE_NOT_FOUND) { 384
385 if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
386 return;
387 }
388
389 e->pos = ngx_cpymem(e->pos, value->text.data, value->text.len);
390
391 if (e->log) {
392 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
393 "http script var: \"%V\"", &e->buf);
394 }
395 }
396 }
397
398
399 size_t
400 ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
401 {
402 ngx_http_script_copy_capture_code_t *code;
403
404 code = (ngx_http_script_copy_capture_code_t *) e->ip;
405
406 e->ip += sizeof(ngx_http_script_copy_capture_code_t);
407
408 if ((e->args || e->quote)
409 && (e->request->quoted_uri || e->request->plus_in_uri))
410 {
411 return e->captures[code->n + 1] - e->captures[code->n]
412 + ngx_escape_uri(NULL,
413 &e->line->data[e->captures[code->n]],
414 e->captures[code->n + 1] - e->captures[code->n],
415 NGX_ESCAPE_ARGS);
416 } else {
417 return e->captures[code->n + 1] - e->captures[code->n];
418 }
419 }
420
421
422 void
423 ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
424 {
425 ngx_http_script_copy_capture_code_t *code;
426
427 code = (ngx_http_script_copy_capture_code_t *) e->ip;
428
429 e->ip += sizeof(ngx_http_script_copy_capture_code_t);
430
431 if ((e->args || e->quote)
432 && (e->request->quoted_uri || e->request->plus_in_uri))
433 {
434 e->pos = (u_char *) ngx_escape_uri(e->pos,
435 &e->line->data[e->captures[code->n]],
436 e->captures[code->n + 1] - e->captures[code->n],
437 NGX_ESCAPE_ARGS);
438 } else {
439 e->pos = ngx_cpymem(e->pos,
440 &e->line->data[e->captures[code->n]],
441 e->captures[code->n + 1] - e->captures[code->n]);
442 }
443
444 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
445 "http script capture: \"%V\"", &e->buf);
446 }
447
448
449 void
450 ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
451 {
452 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
453 "http script args");
454
455 e->args = e->pos;
456 e->ip += sizeof(uintptr_t);
457 }
458
459
460 void
461 ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
462 {
463 size_t len;
464 ngx_int_t rc;
465 ngx_uint_t n;
466 ngx_http_request_t *r;
467 ngx_http_script_engine_t le;
468 ngx_http_script_len_code_pt lcode;
469 ngx_http_script_regex_code_t *code;
470
471 code = (ngx_http_script_regex_code_t *) e->ip;
472
473 r = e->request;
474
475 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
476 "http script regex: \"%V\"", &code->name);
477
478 if (code->uri) {
479 e->line = &r->uri;
480 } else {
481 e->sp--;
482 e->line = &e->sp->text;
483 }
484
485 rc = ngx_regex_exec(code->regex, e->line, e->captures, code->ncaptures);
486
487 if (rc == NGX_REGEX_NO_MATCHED) {
488 if (e->log) {
489 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
490 "\"%V\" does not match \"%V\"", &code->name, e->line);
491 }
492
493 if (code->test) {
494 e->sp->value = 0;
495 e->sp->text.len = 0;
496 e->sp->text.data = (u_char *) "";
497 e->sp++;
498
499 e->ip += sizeof(ngx_http_script_regex_code_t);
500 return;
501 }
502
503 e->ip += code->next;
190 return; 504 return;
191 } 505 }
192 506
193 e->lite.pos = ngx_cpymem(e->lite.pos, value->text.data, value->text.len); 507 if (rc < 0) {
194 } 508 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
509 ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
510 rc, e->line, &code->name);
511
512 e->ip = ngx_http_script_exit;
513 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
514 return;
515 }
516
517 if (e->log) {
518 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
519 "\"%V\" matches \"%V\"", &code->name, e->line);
520 }
521
522 if (code->test) {
523 e->sp->value = 1;
524 e->sp->text.len = 1;
525 e->sp->text.data = (u_char *) "1";
526 e->sp++;
527
528 e->ip += sizeof(ngx_http_script_regex_code_t);
529 return;
530 }
531
532 if (code->status) {
533 e->status = code->status;
534
535 if (!code->redirect) {
536 e->ip = ngx_http_script_exit;
537 return;
538 }
539 }
540
541 if (code->uri) {
542 r->internal = 1;
543 r->valid_unparsed_uri = 0;
544
545 if (code->break_cycle) {
546 r->valid_location = 0;
547
548 } else {
549 r->uri_changed = 1;
550 }
551 }
552
553 if (code->lengths == NULL) {
554 e->buf.len = code->size;
555
556 if (code->uri) {
557 if (rc && (r->quoted_uri || r->plus_in_uri)) {
558 e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
559 NGX_ESCAPE_ARGS);
560 }
561 }
562
563 for (n = 1; n < (ngx_uint_t) rc; n++) {
564 e->buf.len += e->captures[2 * n + 1] - e->captures[2 * n];
565 }
566
567 } else {
568 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
569
570 le.ip = code->lengths->elts;
571 le.request = r;
572 le.captures = e->captures;
573
574 len = 1; /* reserve 1 byte for possible "?" */
575
576 while (*(uintptr_t *) le.ip) {
577 lcode = *(ngx_http_script_len_code_pt *) le.ip;
578 len += lcode(&le);
579 }
580
581 e->buf.len = len;
582 }
583
584 if (code->args && code->add_args && r->args.len) {
585 e->buf.len += r->args.len + 1;
586 }
587
588 e->buf.data = ngx_palloc(r->pool, e->buf.len);
589 if (e->buf.data == NULL) {
590 e->ip = ngx_http_script_exit;
591 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
592 return;
593 }
594
595 e->quote = code->redirect;
596
597 e->pos = e->buf.data;
598
599 e->ip += sizeof(ngx_http_script_regex_code_t);
600 }
601
602
603 void
604 ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
605 {
606 ngx_http_request_t *r;
607 ngx_http_script_regex_end_code_t *code;
608
609 code = (ngx_http_script_regex_end_code_t *) e->ip;
610
611 r = e->request;
612
613 e->quote = 0;
614
615 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
616 "http script regex end");
617
618 if (code->redirect) {
619
620 if (code->add_args && r->args.len) {
621 *e->pos++ = (u_char) (code->args ? '&' : '?');
622 e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len);
623 }
624
625 e->buf.len = e->pos - e->buf.data;
626
627 if (e->log) {
628 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
629 "rewritten redirect: \"%V\"", &e->buf);
630 }
631
632 r->headers_out.location = ngx_list_push(&r->headers_out.headers);
633 if (r->headers_out.location == NULL) {
634 e->ip = ngx_http_script_exit;
635 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
636 return;
637 }
638
639 r->headers_out.location->hash = 1;
640 r->headers_out.location->key.len = sizeof("Location") - 1;
641 r->headers_out.location->key.data = (u_char *) "Location";
642 r->headers_out.location->value = e->buf;
643
644 e->ip += sizeof(ngx_http_script_regex_end_code_t);
645 return;
646 }
647
648 if (e->args) {
649 e->buf.len = e->args - e->buf.data;
650
651 if (code->add_args && r->args.len) {
652 *e->pos++ = '&';
653 e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len);
654 }
655
656 r->args.len = e->pos - e->args;
657 r->args.data = e->args;
658
659 e->args = NULL;
660
661 } else {
662 e->buf.len = e->pos - e->buf.data;
663 }
664
665 if (e->log) {
666 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
667 "rewritten data: \"%V\", args: \"%V\"",
668 &e->buf, &r->args);
669 }
670
671 if (code->uri) {
672 r->uri = e->buf;
673
674 if (ngx_http_set_exten(r) != NGX_OK) {
675 e->ip = ngx_http_script_exit;
676 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
677 return;
678 }
679 }
680
681 e->ip += sizeof(ngx_http_script_regex_end_code_t);
682 }
683
684
685 void
686 ngx_http_script_return_code(ngx_http_script_engine_t *e)
687 {
688 ngx_http_script_return_code_t *code;
689
690 code = (ngx_http_script_return_code_t *) e->ip;
691
692 e->status = code->status;
693
694 e->ip += sizeof(ngx_http_script_return_code_t) - sizeof(uintptr_t);
695 }
696
697
698 void
699 ngx_http_script_if_code(ngx_http_script_engine_t *e)
700 {
701 ngx_http_script_if_code_t *code;
702
703 code = (ngx_http_script_if_code_t *) e->ip;
704
705 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
706 "http script if");
707
708 e->sp--;
709
710 if (e->sp->value) {
711 if (code->loc_conf) {
712 e->request->loc_conf = code->loc_conf;
713 }
714
715 e->ip += sizeof(ngx_http_script_if_code_t);
716 return;
717 }
718
719 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
720 "http script if false");
721
722 e->ip += code->next;
723 }
724
725
726 void
727 ngx_http_script_value_code(ngx_http_script_engine_t *e)
728 {
729 ngx_http_script_value_code_t *code;
730
731 code = (ngx_http_script_value_code_t *) e->ip;
732
733 e->ip += sizeof(ngx_http_script_value_code_t);
734
735 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
736 "http script value");
737
738 e->sp->value = (ngx_uint_t) code->value;
739 e->sp->text.len = (size_t) code->text_len;
740 e->sp->text.data = (u_char *) code->text_data;
741 e->sp++;
742 }
743
744
745 void
746 ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
747 {
748 ngx_http_request_t *r;
749 ngx_http_variable_value_t *value;
750 ngx_http_core_main_conf_t *cmcf;
751 ngx_http_script_var_code_t *code;
752
753 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
754 "http script set var");
755
756 code = (ngx_http_script_var_code_t *) e->ip;
757
758 e->ip += sizeof(ngx_http_script_var_code_t);
759
760 r = e->request;
761
762 if (r->variables == NULL) {
763 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
764
765 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
766 * sizeof(ngx_http_variable_value_t *));
767 if (r->variables == NULL) {
768 e->ip = ngx_http_script_exit;
769 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
770 return;
771 }
772 }
773
774 value = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
775 if (value == NULL) {
776 e->ip = ngx_http_script_exit;
777 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
778 return;
779 }
780
781 e->sp--;
782
783 *value = *e->sp;
784
785 r->variables[code->index] = value;
786 }
787
788
789 void
790 ngx_http_script_var_code(ngx_http_script_engine_t *e)
791 {
792 ngx_http_variable_value_t *value;
793 ngx_http_script_var_code_t *code;
794
795 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
796 "http script var");
797
798 code = (ngx_http_script_var_code_t *) e->ip;
799
800 e->ip += sizeof(ngx_http_script_var_code_t);
801
802 value = ngx_http_get_indexed_variable(e->request, code->index);
803
804 if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
805 e->sp->value = 0;
806 e->sp->text.len = 0;
807 e->sp->text.data = (u_char *) "";
808 e->sp++;
809
810 return;
811 }
812
813 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
814 "http script var: %ui, \"%V\"", value->value, &value->text);
815
816 *e->sp = *value;
817 e->sp++;
818 }
819
820
821 void
822 ngx_http_script_nop_code(ngx_http_script_engine_t *e)
823 {
824 e->ip += sizeof(uintptr_t);
825 }