Mercurial > hg > nginx-ranges
comparison src/http/ngx_http_script.c @ 473:c8cfb6c462ef NGINX_0_7_44
nginx 0.7.44
*) Feature: the ngx_http_proxy_module preliminary cache support.
*) Feature: the --with-pcre option in the configure.
*) Feature: the "try_files" directive is now allowed on the server
block level.
*) Bugfix: the "try_files" directive handled incorrectly a query string
in a fallback parameter.
*) Bugfix: the "try_files" directive might test incorrectly directories.
*) Bugfix: if there is the single server for given address:port pair,
then captures in regular expressions in a "server_name" directive
did not work.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 23 Mar 2009 00:00:00 +0300 |
parents | ca8f7f6cab16 |
children | 56baf312c1b5 |
comparison
equal
deleted
inserted
replaced
472:51cb914e6d3a | 473:c8cfb6c462ef |
---|---|
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 static ngx_int_t ngx_http_script_init_arrays(ngx_http_script_compile_t *sc); | |
13 static ngx_int_t ngx_http_script_done(ngx_http_script_compile_t *sc); | |
14 static ngx_int_t ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, | |
15 ngx_str_t *value, ngx_uint_t last); | |
16 static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, | |
17 ngx_str_t *name); | |
18 static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc); | |
19 #if (NGX_PCRE) | |
20 static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, | |
21 ngx_uint_t n); | |
22 #endif | |
23 static ngx_int_t | |
24 ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc); | |
25 static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e); | |
26 static void ngx_http_script_full_name_code(ngx_http_script_engine_t *e); | |
27 | |
28 | |
12 #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code | 29 #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code |
13 | 30 |
14 static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL; | 31 static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL; |
32 | |
33 | |
34 void | |
35 ngx_http_scrip_flush_complex_value(ngx_http_request_t *r, | |
36 ngx_http_complex_value_t *val) | |
37 { | |
38 ngx_uint_t *index; | |
39 | |
40 index = val->flushes; | |
41 | |
42 if (index) { | |
43 while (*index != (ngx_uint_t) -1) { | |
44 | |
45 if (r->variables[*index].no_cacheable) { | |
46 r->variables[*index].valid = 0; | |
47 r->variables[*index].not_found = 0; | |
48 } | |
49 | |
50 index++; | |
51 } | |
52 } | |
53 } | |
54 | |
55 | |
56 ngx_int_t | |
57 ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val, | |
58 ngx_str_t *value) | |
59 { | |
60 size_t len; | |
61 ngx_http_script_code_pt code; | |
62 ngx_http_script_len_code_pt lcode; | |
63 ngx_http_script_engine_t e; | |
64 | |
65 if (val->lengths == NULL) { | |
66 *value = val->value; | |
67 return NGX_OK; | |
68 } | |
69 | |
70 ngx_http_scrip_flush_complex_value(r, val); | |
71 | |
72 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); | |
73 | |
74 e.ip = val->lengths; | |
75 e.request = r; | |
76 e.flushed = 1; | |
77 | |
78 len = 0; | |
79 | |
80 while (*(uintptr_t *) e.ip) { | |
81 lcode = *(ngx_http_script_len_code_pt *) e.ip; | |
82 len += lcode(&e); | |
83 } | |
84 | |
85 value->len = len; | |
86 value->data = ngx_pnalloc(r->pool, len); | |
87 if (value->data == NULL) { | |
88 return NGX_ERROR; | |
89 } | |
90 | |
91 e.ip = val->values; | |
92 e.pos = value->data; | |
93 e.buf = *value; | |
94 | |
95 while (*(uintptr_t *) e.ip) { | |
96 code = *(ngx_http_script_code_pt *) e.ip; | |
97 code((ngx_http_script_engine_t *) &e); | |
98 } | |
99 | |
100 *value = e.buf; | |
101 | |
102 return NGX_OK; | |
103 } | |
104 | |
105 | |
106 ngx_int_t | |
107 ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv) | |
108 { | |
109 ngx_str_t *v; | |
110 ngx_uint_t i, n, nv, nc; | |
111 ngx_array_t flushes, lengths, values, *pf, *pl, *pv; | |
112 ngx_http_script_compile_t sc; | |
113 | |
114 v = ccv->value; | |
115 | |
116 if (v->len == 0) { | |
117 ngx_conf_log_error(NGX_LOG_EMERG, ccv->cf, 0, "empty parameter"); | |
118 return NGX_ERROR; | |
119 } | |
120 | |
121 ccv->complex_value->value = *v; | |
122 ccv->complex_value->flushes = NULL; | |
123 ccv->complex_value->lengths = NULL; | |
124 ccv->complex_value->values = NULL; | |
125 | |
126 nv = 0; | |
127 nc = 0; | |
128 | |
129 for (i = 0; i < v->len; i++) { | |
130 if (v->data[i] == '$') { | |
131 if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') { | |
132 nc++; | |
133 | |
134 } else { | |
135 nv++; | |
136 } | |
137 } | |
138 } | |
139 | |
140 if (v->data[0] != '$' && (ccv->conf_prefix || ccv->root_prefix)) { | |
141 | |
142 if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) { | |
143 return NGX_ERROR; | |
144 } | |
145 | |
146 ccv->conf_prefix = 0; | |
147 ccv->root_prefix = 0; | |
148 } | |
149 | |
150 if (nv == 0 && nc == 0) { | |
151 return NGX_OK; | |
152 } | |
153 | |
154 n = nv + 1; | |
155 | |
156 if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t)) | |
157 != NGX_OK) | |
158 { | |
159 return NGX_ERROR; | |
160 } | |
161 | |
162 n = nv * (2 * sizeof(ngx_http_script_copy_code_t) | |
163 + sizeof(ngx_http_script_var_code_t)) | |
164 + sizeof(uintptr_t); | |
165 | |
166 if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) { | |
167 return NGX_ERROR; | |
168 } | |
169 | |
170 n = (nv * (2 * sizeof(ngx_http_script_copy_code_t) | |
171 + sizeof(ngx_http_script_var_code_t)) | |
172 + sizeof(uintptr_t) | |
173 + v->len | |
174 + sizeof(uintptr_t) - 1) | |
175 & ~(sizeof(uintptr_t) - 1); | |
176 | |
177 if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) { | |
178 return NGX_ERROR; | |
179 } | |
180 | |
181 pf = &flushes; | |
182 pl = &lengths; | |
183 pv = &values; | |
184 | |
185 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
186 | |
187 sc.cf = ccv->cf; | |
188 sc.source = v; | |
189 sc.flushes = &pf; | |
190 sc.lengths = &pl; | |
191 sc.values = &pv; | |
192 sc.complete_lengths = 1; | |
193 sc.complete_values = 1; | |
194 sc.zero = ccv->zero; | |
195 sc.conf_prefix = ccv->conf_prefix; | |
196 sc.root_prefix = ccv->root_prefix; | |
197 | |
198 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
199 return NGX_ERROR; | |
200 } | |
201 | |
202 if (flushes.nelts) { | |
203 ccv->complex_value->flushes = flushes.elts; | |
204 ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1; | |
205 } | |
206 | |
207 ccv->complex_value->lengths = lengths.elts; | |
208 ccv->complex_value->values = values.elts; | |
209 | |
210 return NGX_OK; | |
211 } | |
15 | 212 |
16 | 213 |
17 ngx_uint_t | 214 ngx_uint_t |
18 ngx_http_script_variables_count(ngx_str_t *value) | 215 ngx_http_script_variables_count(ngx_str_t *value) |
19 { | 216 { |
30 | 227 |
31 | 228 |
32 ngx_int_t | 229 ngx_int_t |
33 ngx_http_script_compile(ngx_http_script_compile_t *sc) | 230 ngx_http_script_compile(ngx_http_script_compile_t *sc) |
34 { | 231 { |
35 u_char ch; | 232 u_char ch; |
36 size_t size; | 233 ngx_str_t name; |
37 ngx_int_t index, *p; | 234 ngx_uint_t i, bracket; |
38 ngx_str_t name; | 235 |
39 uintptr_t *code; | 236 if (ngx_http_script_init_arrays(sc) != NGX_OK) { |
40 ngx_uint_t i, n, bracket; | 237 return NGX_ERROR; |
41 ngx_http_script_var_code_t *var_code; | 238 } |
42 ngx_http_script_copy_code_t *copy; | 239 |
240 for (i = 0; i < sc->source->len; /* void */ ) { | |
241 | |
242 name.len = 0; | |
243 | |
244 if (sc->source->data[i] == '$') { | |
245 | |
246 if (++i == sc->source->len) { | |
247 goto invalid_variable; | |
248 } | |
249 | |
43 #if (NGX_PCRE) | 250 #if (NGX_PCRE) |
44 ngx_http_script_copy_capture_code_t *copy_capture; | 251 { |
252 ngx_uint_t n; | |
253 | |
254 /* NGX_HTTP_MAX_CAPTURES is 9 */ | |
255 | |
256 if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') { | |
257 | |
258 n = sc->source->data[i] - '0'; | |
259 | |
260 if (sc->captures_mask & (1 << n)) { | |
261 sc->dup_capture = 1; | |
262 } | |
263 | |
264 sc->captures_mask |= 1 << n; | |
265 | |
266 if (ngx_http_script_add_capture_code(sc, n) != NGX_OK) { | |
267 return NGX_ERROR; | |
268 } | |
269 | |
270 i++; | |
271 | |
272 continue; | |
273 } | |
274 } | |
45 #endif | 275 #endif |
276 | |
277 if (sc->source->data[i] == '{') { | |
278 bracket = 1; | |
279 | |
280 if (++i == sc->source->len) { | |
281 goto invalid_variable; | |
282 } | |
283 | |
284 name.data = &sc->source->data[i]; | |
285 | |
286 } else { | |
287 bracket = 0; | |
288 name.data = &sc->source->data[i]; | |
289 } | |
290 | |
291 for ( /* void */ ; i < sc->source->len; i++, name.len++) { | |
292 ch = sc->source->data[i]; | |
293 | |
294 if (ch == '}' && bracket) { | |
295 i++; | |
296 bracket = 0; | |
297 break; | |
298 } | |
299 | |
300 if ((ch >= 'A' && ch <= 'Z') | |
301 || (ch >= 'a' && ch <= 'z') | |
302 || (ch >= '0' && ch <= '9') | |
303 || ch == '_') | |
304 { | |
305 continue; | |
306 } | |
307 | |
308 break; | |
309 } | |
310 | |
311 if (bracket) { | |
312 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, | |
313 "the closing bracket in \"%V\" " | |
314 "variable is missing", &name); | |
315 return NGX_ERROR; | |
316 } | |
317 | |
318 if (name.len == 0) { | |
319 goto invalid_variable; | |
320 } | |
321 | |
322 sc->variables++; | |
323 | |
324 if (ngx_http_script_add_var_code(sc, &name) != NGX_OK) { | |
325 return NGX_ERROR; | |
326 } | |
327 | |
328 continue; | |
329 } | |
330 | |
331 if (sc->source->data[i] == '?' && sc->compile_args) { | |
332 sc->args = 1; | |
333 sc->compile_args = 0; | |
334 | |
335 if (ngx_http_script_add_args_code(sc) != NGX_OK) { | |
336 return NGX_ERROR; | |
337 } | |
338 | |
339 i++; | |
340 | |
341 continue; | |
342 } | |
343 | |
344 name.data = &sc->source->data[i]; | |
345 | |
346 while (i < sc->source->len) { | |
347 | |
348 if (sc->source->data[i] == '$') { | |
349 break; | |
350 } | |
351 | |
352 if (sc->source->data[i] == '?') { | |
353 | |
354 sc->args = 1; | |
355 | |
356 if (sc->compile_args) { | |
357 break; | |
358 } | |
359 } | |
360 | |
361 i++; | |
362 name.len++; | |
363 } | |
364 | |
365 sc->size += name.len; | |
366 | |
367 if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len)) | |
368 != NGX_OK) | |
369 { | |
370 return NGX_ERROR; | |
371 } | |
372 } | |
373 | |
374 return ngx_http_script_done(sc); | |
375 | |
376 invalid_variable: | |
377 | |
378 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name"); | |
379 | |
380 return NGX_ERROR; | |
381 } | |
382 | |
383 | |
384 u_char * | |
385 ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value, | |
386 void *code_lengths, size_t len, void *code_values) | |
387 { | |
388 ngx_uint_t i; | |
389 ngx_http_script_code_pt code; | |
390 ngx_http_script_len_code_pt lcode; | |
391 ngx_http_script_engine_t e; | |
392 ngx_http_core_main_conf_t *cmcf; | |
393 | |
394 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
395 | |
396 for (i = 0; i < cmcf->variables.nelts; i++) { | |
397 if (r->variables[i].no_cacheable) { | |
398 r->variables[i].valid = 0; | |
399 r->variables[i].not_found = 0; | |
400 } | |
401 } | |
402 | |
403 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); | |
404 | |
405 e.ip = code_lengths; | |
406 e.request = r; | |
407 e.flushed = 1; | |
408 | |
409 while (*(uintptr_t *) e.ip) { | |
410 lcode = *(ngx_http_script_len_code_pt *) e.ip; | |
411 len += lcode(&e); | |
412 } | |
413 | |
414 | |
415 value->len = len; | |
416 value->data = ngx_pnalloc(r->pool, len); | |
417 if (value->data == NULL) { | |
418 return NULL; | |
419 } | |
420 | |
421 e.ip = code_values; | |
422 e.pos = value->data; | |
423 | |
424 while (*(uintptr_t *) e.ip) { | |
425 code = *(ngx_http_script_code_pt *) e.ip; | |
426 code((ngx_http_script_engine_t *) &e); | |
427 } | |
428 | |
429 return e.pos; | |
430 } | |
431 | |
432 | |
433 void | |
434 ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r, | |
435 ngx_array_t *indices) | |
436 { | |
437 ngx_uint_t n, *index; | |
438 | |
439 if (indices) { | |
440 index = indices->elts; | |
441 for (n = 0; n < indices->nelts; n++) { | |
442 if (r->variables[index[n]].no_cacheable) { | |
443 r->variables[index[n]].valid = 0; | |
444 r->variables[index[n]].not_found = 0; | |
445 } | |
446 } | |
447 } | |
448 } | |
449 | |
450 | |
451 static ngx_int_t | |
452 ngx_http_script_init_arrays(ngx_http_script_compile_t *sc) | |
453 { | |
454 ngx_uint_t n; | |
46 | 455 |
47 if (sc->flushes && *sc->flushes == NULL) { | 456 if (sc->flushes && *sc->flushes == NULL) { |
48 n = sc->variables ? sc->variables : 1; | 457 n = sc->variables ? sc->variables : 1; |
49 *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t)); | 458 *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t)); |
50 if (*sc->flushes == NULL) { | 459 if (*sc->flushes == NULL) { |
51 return NGX_ERROR; | 460 return NGX_ERROR; |
52 } | 461 } |
53 } | 462 } |
54 | 463 |
55 | |
56 if (*sc->lengths == NULL) { | 464 if (*sc->lengths == NULL) { |
57 n = sc->variables * (2 * sizeof(ngx_http_script_copy_code_t) | 465 n = sc->variables * (2 * sizeof(ngx_http_script_copy_code_t) |
58 + sizeof(ngx_http_script_var_code_t)) | 466 + sizeof(ngx_http_script_var_code_t)) |
59 + sizeof(uintptr_t); | 467 + sizeof(uintptr_t); |
60 | 468 |
61 *sc->lengths = ngx_array_create(sc->cf->pool, n, 1); | 469 *sc->lengths = ngx_array_create(sc->cf->pool, n, 1); |
62 if (*sc->lengths == NULL) { | 470 if (*sc->lengths == NULL) { |
63 return NGX_ERROR; | 471 return NGX_ERROR; |
64 } | 472 } |
65 } | 473 } |
66 | |
67 | 474 |
68 if (*sc->values == NULL) { | 475 if (*sc->values == NULL) { |
69 n = (sc->variables * (2 * sizeof(ngx_http_script_copy_code_t) | 476 n = (sc->variables * (2 * sizeof(ngx_http_script_copy_code_t) |
70 + sizeof(ngx_http_script_var_code_t)) | 477 + sizeof(ngx_http_script_var_code_t)) |
71 + sizeof(uintptr_t) | 478 + sizeof(uintptr_t) |
79 } | 486 } |
80 } | 487 } |
81 | 488 |
82 sc->variables = 0; | 489 sc->variables = 0; |
83 | 490 |
84 for (i = 0; i < sc->source->len; /* void */ ) { | 491 return NGX_OK; |
85 | 492 } |
86 name.len = 0; | 493 |
87 | 494 |
88 if (sc->source->data[i] == '$') { | 495 static ngx_int_t |
89 | 496 ngx_http_script_done(ngx_http_script_compile_t *sc) |
90 if (++i == sc->source->len) { | 497 { |
91 goto invalid_variable; | 498 ngx_str_t zero; |
92 } | 499 uintptr_t *code; |
93 | 500 |
94 #if (NGX_PCRE) | 501 if (sc->zero) { |
95 | 502 |
96 /* NGX_HTTP_MAX_CAPTURES is 9 */ | 503 zero.len = 1; |
97 | 504 zero.data = (u_char *) "\0"; |
98 if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') { | 505 |
99 | 506 if (ngx_http_script_add_copy_code(sc, &zero, 0) != NGX_OK) { |
100 n = sc->source->data[i] - '0'; | |
101 | |
102 if (sc->captures_mask & (1 << n)) { | |
103 sc->dup_capture = 1; | |
104 } | |
105 | |
106 sc->captures_mask |= 1 << n; | |
107 | |
108 copy_capture = ngx_http_script_add_code(*sc->lengths, | |
109 sizeof(ngx_http_script_copy_capture_code_t), | |
110 NULL); | |
111 if (copy_capture == NULL) { | |
112 return NGX_ERROR; | |
113 } | |
114 | |
115 copy_capture->code = (ngx_http_script_code_pt) | |
116 ngx_http_script_copy_capture_len_code; | |
117 copy_capture->n = 2 * n; | |
118 | |
119 | |
120 copy_capture = ngx_http_script_add_code(*sc->values, | |
121 sizeof(ngx_http_script_copy_capture_code_t), | |
122 &sc->main); | |
123 if (copy_capture == NULL) { | |
124 return NGX_ERROR; | |
125 } | |
126 | |
127 copy_capture->code = ngx_http_script_copy_capture_code; | |
128 copy_capture->n = 2 * n; | |
129 | |
130 if (sc->ncaptures < n) { | |
131 sc->ncaptures = n; | |
132 } | |
133 | |
134 i++; | |
135 | |
136 continue; | |
137 } | |
138 | |
139 #endif | |
140 | |
141 if (sc->source->data[i] == '{') { | |
142 bracket = 1; | |
143 | |
144 if (++i == sc->source->len) { | |
145 goto invalid_variable; | |
146 } | |
147 | |
148 name.data = &sc->source->data[i]; | |
149 | |
150 } else { | |
151 bracket = 0; | |
152 name.data = &sc->source->data[i]; | |
153 } | |
154 | |
155 for ( /* void */ ; i < sc->source->len; i++, name.len++) { | |
156 ch = sc->source->data[i]; | |
157 | |
158 if (ch == '}' && bracket) { | |
159 i++; | |
160 bracket = 0; | |
161 break; | |
162 } | |
163 | |
164 if ((ch >= 'A' && ch <= 'Z') | |
165 || (ch >= 'a' && ch <= 'z') | |
166 || (ch >= '0' && ch <= '9') | |
167 || ch == '_') | |
168 { | |
169 continue; | |
170 } | |
171 | |
172 break; | |
173 } | |
174 | |
175 if (bracket) { | |
176 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, | |
177 "the closing bracket in \"%V\" " | |
178 "variable is missing", &name); | |
179 return NGX_ERROR; | |
180 } | |
181 | |
182 if (name.len == 0) { | |
183 goto invalid_variable; | |
184 } | |
185 | |
186 sc->variables++; | |
187 | |
188 index = ngx_http_get_variable_index(sc->cf, &name); | |
189 | |
190 if (index == NGX_ERROR) { | |
191 return NGX_ERROR; | |
192 } | |
193 | |
194 if (sc->flushes) { | |
195 p = ngx_array_push(*sc->flushes); | |
196 if (p == NULL) { | |
197 return NGX_ERROR; | |
198 } | |
199 | |
200 *p = index; | |
201 } | |
202 | |
203 var_code = ngx_http_script_add_code(*sc->lengths, | |
204 sizeof(ngx_http_script_var_code_t), | |
205 NULL); | |
206 if (var_code == NULL) { | |
207 return NGX_ERROR; | |
208 } | |
209 | |
210 var_code->code = (ngx_http_script_code_pt) | |
211 ngx_http_script_copy_var_len_code; | |
212 var_code->index = (uintptr_t) index; | |
213 | |
214 | |
215 var_code = ngx_http_script_add_code(*sc->values, | |
216 sizeof(ngx_http_script_var_code_t), | |
217 &sc->main); | |
218 if (var_code == NULL) { | |
219 return NGX_ERROR; | |
220 } | |
221 | |
222 var_code->code = ngx_http_script_copy_var_code; | |
223 var_code->index = (uintptr_t) index; | |
224 | |
225 continue; | |
226 } | |
227 | |
228 if (sc->source->data[i] == '?' && sc->compile_args) { | |
229 sc->args = 1; | |
230 sc->compile_args = 0; | |
231 | |
232 code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), | |
233 NULL); | |
234 if (code == NULL) { | |
235 return NGX_ERROR; | |
236 } | |
237 | |
238 *code = (uintptr_t) ngx_http_script_mark_args_code; | |
239 | |
240 code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t), | |
241 &sc->main); | |
242 if (code == NULL) { | |
243 return NGX_ERROR; | |
244 } | |
245 | |
246 *code = (uintptr_t) ngx_http_script_start_args_code; | |
247 | |
248 i++; | |
249 | |
250 continue; | |
251 } | |
252 | |
253 name.data = &sc->source->data[i]; | |
254 | |
255 while (i < sc->source->len) { | |
256 | |
257 if (sc->source->data[i] == '$') { | |
258 break; | |
259 } | |
260 | |
261 if (sc->source->data[i] == '?') { | |
262 | |
263 sc->args = 1; | |
264 | |
265 if (sc->compile_args) { | |
266 break; | |
267 } | |
268 } | |
269 | |
270 i++; | |
271 name.len++; | |
272 } | |
273 | |
274 sc->size += name.len; | |
275 | |
276 copy = ngx_http_script_add_code(*sc->lengths, | |
277 sizeof(ngx_http_script_copy_code_t), | |
278 NULL); | |
279 if (copy == NULL) { | |
280 return NGX_ERROR; | 507 return NGX_ERROR; |
281 } | 508 } |
282 | 509 } |
283 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; | 510 |
284 copy->len = name.len; | 511 if (sc->conf_prefix || sc->root_prefix) { |
285 | 512 if (ngx_http_script_add_full_name_code(sc) != NGX_OK) { |
286 size = (sizeof(ngx_http_script_copy_code_t) + name.len | |
287 + sizeof(uintptr_t) - 1) | |
288 & ~(sizeof(uintptr_t) - 1); | |
289 | |
290 copy = ngx_http_script_add_code(*sc->values, size, &sc->main); | |
291 if (copy == NULL) { | |
292 return NGX_ERROR; | 513 return NGX_ERROR; |
293 } | 514 } |
294 | |
295 copy->code = ngx_http_script_copy_code; | |
296 copy->len = name.len; | |
297 | |
298 ngx_memcpy((u_char *) copy + sizeof(ngx_http_script_copy_code_t), | |
299 name.data, name.len); | |
300 } | 515 } |
301 | 516 |
302 if (sc->complete_lengths) { | 517 if (sc->complete_lengths) { |
303 code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL); | 518 code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL); |
304 if (code == NULL) { | 519 if (code == NULL) { |
317 | 532 |
318 *code = (uintptr_t) NULL; | 533 *code = (uintptr_t) NULL; |
319 } | 534 } |
320 | 535 |
321 return NGX_OK; | 536 return NGX_OK; |
322 | |
323 invalid_variable: | |
324 | |
325 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name"); | |
326 | |
327 return NGX_ERROR; | |
328 } | |
329 | |
330 | |
331 u_char * | |
332 ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value, | |
333 void *code_lengths, size_t len, void *code_values) | |
334 { | |
335 ngx_uint_t i; | |
336 ngx_http_script_code_pt code; | |
337 ngx_http_script_len_code_pt lcode; | |
338 ngx_http_script_engine_t e; | |
339 ngx_http_core_main_conf_t *cmcf; | |
340 | |
341 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
342 | |
343 for (i = 0; i < cmcf->variables.nelts; i++) { | |
344 if (r->variables[i].no_cacheable) { | |
345 r->variables[i].valid = 0; | |
346 r->variables[i].not_found = 0; | |
347 } | |
348 } | |
349 | |
350 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); | |
351 | |
352 e.ip = code_lengths; | |
353 e.request = r; | |
354 e.flushed = 1; | |
355 | |
356 while (*(uintptr_t *) e.ip) { | |
357 lcode = *(ngx_http_script_len_code_pt *) e.ip; | |
358 len += lcode(&e); | |
359 } | |
360 | |
361 | |
362 value->len = len; | |
363 value->data = ngx_pnalloc(r->pool, len); | |
364 if (value->data == NULL) { | |
365 return NULL; | |
366 } | |
367 | |
368 e.ip = code_values; | |
369 e.pos = value->data; | |
370 | |
371 while (*(uintptr_t *) e.ip) { | |
372 code = *(ngx_http_script_code_pt *) e.ip; | |
373 code((ngx_http_script_engine_t *) &e); | |
374 } | |
375 | |
376 return e.pos; | |
377 } | |
378 | |
379 | |
380 void | |
381 ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r, | |
382 ngx_array_t *indices) | |
383 { | |
384 ngx_uint_t n, *index; | |
385 | |
386 if (indices) { | |
387 index = indices->elts; | |
388 for (n = 0; n < indices->nelts; n++) { | |
389 if (r->variables[index[n]].no_cacheable) { | |
390 r->variables[index[n]].valid = 0; | |
391 r->variables[index[n]].not_found = 0; | |
392 } | |
393 } | |
394 } | |
395 } | 537 } |
396 | 538 |
397 | 539 |
398 void * | 540 void * |
399 ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size) | 541 ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size) |
431 | 573 |
432 return new; | 574 return new; |
433 } | 575 } |
434 | 576 |
435 | 577 |
578 static ngx_int_t | |
579 ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value, | |
580 ngx_uint_t last) | |
581 { | |
582 u_char *p; | |
583 size_t size, len, zero; | |
584 ngx_http_script_copy_code_t *code; | |
585 | |
586 zero = (sc->zero && last); | |
587 len = value->len + zero; | |
588 | |
589 code = ngx_http_script_add_code(*sc->lengths, | |
590 sizeof(ngx_http_script_copy_code_t), NULL); | |
591 if (code == NULL) { | |
592 return NGX_ERROR; | |
593 } | |
594 | |
595 code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; | |
596 code->len = len; | |
597 | |
598 size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1) | |
599 & ~(sizeof(uintptr_t) - 1); | |
600 | |
601 code = ngx_http_script_add_code(*sc->values, size, &sc->main); | |
602 if (code == NULL) { | |
603 return NGX_ERROR; | |
604 } | |
605 | |
606 code->code = ngx_http_script_copy_code; | |
607 code->len = len; | |
608 | |
609 p = ngx_cpymem((u_char *) code + sizeof(ngx_http_script_copy_code_t), | |
610 value->data, value->len); | |
611 | |
612 if (zero) { | |
613 *p = '\0'; | |
614 sc->zero = 0; | |
615 } | |
616 | |
617 return NGX_OK; | |
618 } | |
619 | |
620 | |
436 size_t | 621 size_t |
437 ngx_http_script_copy_len_code(ngx_http_script_engine_t *e) | 622 ngx_http_script_copy_len_code(ngx_http_script_engine_t *e) |
438 { | 623 { |
439 ngx_http_script_copy_code_t *code; | 624 ngx_http_script_copy_code_t *code; |
440 | 625 |
467 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, | 652 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, |
468 "http script copy: \"%*s\"", e->pos - p, p); | 653 "http script copy: \"%*s\"", e->pos - p, p); |
469 } | 654 } |
470 | 655 |
471 | 656 |
657 static ngx_int_t | |
658 ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, ngx_str_t *name) | |
659 { | |
660 ngx_int_t index, *p; | |
661 ngx_http_script_var_code_t *code; | |
662 | |
663 index = ngx_http_get_variable_index(sc->cf, name); | |
664 | |
665 if (index == NGX_ERROR) { | |
666 return NGX_ERROR; | |
667 } | |
668 | |
669 if (sc->flushes) { | |
670 p = ngx_array_push(*sc->flushes); | |
671 if (p == NULL) { | |
672 return NGX_ERROR; | |
673 } | |
674 | |
675 *p = index; | |
676 } | |
677 | |
678 code = ngx_http_script_add_code(*sc->lengths, | |
679 sizeof(ngx_http_script_var_code_t), NULL); | |
680 if (code == NULL) { | |
681 return NGX_ERROR; | |
682 } | |
683 | |
684 code->code = (ngx_http_script_code_pt) ngx_http_script_copy_var_len_code; | |
685 code->index = (uintptr_t) index; | |
686 | |
687 code = ngx_http_script_add_code(*sc->values, | |
688 sizeof(ngx_http_script_var_code_t), | |
689 &sc->main); | |
690 if (code == NULL) { | |
691 return NGX_ERROR; | |
692 } | |
693 | |
694 code->code = ngx_http_script_copy_var_code; | |
695 code->index = (uintptr_t) index; | |
696 | |
697 return NGX_OK; | |
698 } | |
699 | |
700 | |
472 size_t | 701 size_t |
473 ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e) | 702 ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e) |
474 { | 703 { |
475 ngx_http_variable_value_t *value; | 704 ngx_http_variable_value_t *value; |
476 ngx_http_script_var_code_t *code; | 705 ngx_http_script_var_code_t *code; |
521 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, | 750 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, |
522 e->request->connection->log, 0, | 751 e->request->connection->log, 0, |
523 "http script var: \"%*s\"", e->pos - p, p); | 752 "http script var: \"%*s\"", e->pos - p, p); |
524 } | 753 } |
525 } | 754 } |
755 } | |
756 | |
757 | |
758 static ngx_int_t | |
759 ngx_http_script_add_args_code(ngx_http_script_compile_t *sc) | |
760 { | |
761 uintptr_t *code; | |
762 | |
763 code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL); | |
764 if (code == NULL) { | |
765 return NGX_ERROR; | |
766 } | |
767 | |
768 *code = (uintptr_t) ngx_http_script_mark_args_code; | |
769 | |
770 code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t), &sc->main); | |
771 if (code == NULL) { | |
772 return NGX_ERROR; | |
773 } | |
774 | |
775 *code = (uintptr_t) ngx_http_script_start_args_code; | |
776 | |
777 return NGX_OK; | |
526 } | 778 } |
527 | 779 |
528 | 780 |
529 size_t | 781 size_t |
530 ngx_http_script_mark_args_code(ngx_http_script_engine_t *e) | 782 ngx_http_script_mark_args_code(ngx_http_script_engine_t *e) |
828 return; | 1080 return; |
829 } | 1081 } |
830 } | 1082 } |
831 | 1083 |
832 e->ip += sizeof(ngx_http_script_regex_end_code_t); | 1084 e->ip += sizeof(ngx_http_script_regex_end_code_t); |
1085 } | |
1086 | |
1087 | |
1088 static ngx_int_t | |
1089 ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, ngx_uint_t n) | |
1090 { | |
1091 ngx_http_script_copy_capture_code_t *code; | |
1092 | |
1093 code = ngx_http_script_add_code(*sc->lengths, | |
1094 sizeof(ngx_http_script_copy_capture_code_t), | |
1095 NULL); | |
1096 if (code == NULL) { | |
1097 return NGX_ERROR; | |
1098 } | |
1099 | |
1100 code->code = (ngx_http_script_code_pt) | |
1101 ngx_http_script_copy_capture_len_code; | |
1102 code->n = 2 * n; | |
1103 | |
1104 | |
1105 code = ngx_http_script_add_code(*sc->values, | |
1106 sizeof(ngx_http_script_copy_capture_code_t), | |
1107 &sc->main); | |
1108 if (code == NULL) { | |
1109 return NGX_ERROR; | |
1110 } | |
1111 | |
1112 code->code = ngx_http_script_copy_capture_code; | |
1113 code->n = 2 * n; | |
1114 | |
1115 if (sc->ncaptures < n) { | |
1116 sc->ncaptures = n; | |
1117 } | |
1118 | |
1119 return NGX_OK; | |
833 } | 1120 } |
834 | 1121 |
835 | 1122 |
836 size_t | 1123 size_t |
837 ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e) | 1124 ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e) |
911 } | 1198 } |
912 | 1199 |
913 #endif | 1200 #endif |
914 | 1201 |
915 | 1202 |
1203 static ngx_int_t | |
1204 ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc) | |
1205 { | |
1206 ngx_http_script_full_name_code_t *code; | |
1207 | |
1208 code = ngx_http_script_add_code(*sc->lengths, | |
1209 sizeof(ngx_http_script_full_name_code_t), | |
1210 NULL); | |
1211 if (code == NULL) { | |
1212 return NGX_ERROR; | |
1213 } | |
1214 | |
1215 code->code = (ngx_http_script_code_pt) ngx_http_script_full_name_len_code; | |
1216 code->prefix = sc->conf_prefix; | |
1217 | |
1218 code = ngx_http_script_add_code(*sc->values, | |
1219 sizeof(ngx_http_script_full_name_code_t), | |
1220 &sc->main); | |
1221 if (code == NULL) { | |
1222 return NGX_ERROR; | |
1223 } | |
1224 | |
1225 code->code = ngx_http_script_full_name_code; | |
1226 code->prefix = sc->conf_prefix; | |
1227 | |
1228 return NGX_OK; | |
1229 } | |
1230 | |
1231 | |
1232 static size_t | |
1233 ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e) | |
1234 { | |
1235 ngx_http_script_full_name_code_t *code; | |
1236 | |
1237 code = (ngx_http_script_full_name_code_t *) e->ip; | |
1238 | |
1239 e->ip += sizeof(ngx_http_script_full_name_code_t); | |
1240 | |
1241 return code->prefix ? sizeof(NGX_CONF_PREFIX) : ngx_cycle->root.len; | |
1242 } | |
1243 | |
1244 | |
1245 static void | |
1246 ngx_http_script_full_name_code(ngx_http_script_engine_t *e) | |
1247 { | |
1248 ngx_http_script_full_name_code_t *code; | |
1249 | |
1250 ngx_str_t value; | |
1251 | |
1252 code = (ngx_http_script_full_name_code_t *) e->ip; | |
1253 | |
1254 value.data = e->buf.data; | |
1255 value.len = e->pos - e->buf.data; | |
1256 | |
1257 if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &value, code->prefix) | |
1258 != NGX_OK) | |
1259 { | |
1260 e->ip = ngx_http_script_exit; | |
1261 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
1262 return; | |
1263 } | |
1264 | |
1265 e->buf = value; | |
1266 | |
1267 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, | |
1268 "http script fullname: \"%V\"", &value); | |
1269 | |
1270 e->ip += sizeof(ngx_http_script_full_name_code_t); | |
1271 } | |
1272 | |
1273 | |
916 void | 1274 void |
917 ngx_http_script_return_code(ngx_http_script_engine_t *e) | 1275 ngx_http_script_return_code(ngx_http_script_engine_t *e) |
918 { | 1276 { |
919 ngx_http_script_return_code_t *code; | 1277 ngx_http_script_return_code_t *code; |
920 | 1278 |