Line data Source code
1 :
2 : /*
3 : * Copyright (C) Xiaozhe Wang (chaoslawful)
4 : * Copyright (C) Yichun Zhang (agentzh)
5 : */
6 :
7 :
8 : #ifndef DDEBUG
9 : #define DDEBUG 0
10 : #endif
11 : #include "ddebug.h"
12 :
13 :
14 : #include "ngx_http_lua_common.h"
15 : #include "ngx_http_lua_directive.h"
16 : #include "ngx_http_lua_util.h"
17 : #include "ngx_http_lua_cache.h"
18 : #include "ngx_http_lua_contentby.h"
19 : #include "ngx_http_lua_accessby.h"
20 : #include "ngx_http_lua_rewriteby.h"
21 : #include "ngx_http_lua_logby.h"
22 : #include "ngx_http_lua_headerfilterby.h"
23 : #include "ngx_http_lua_bodyfilterby.h"
24 : #include "ngx_http_lua_initby.h"
25 : #include "ngx_http_lua_initworkerby.h"
26 : #include "ngx_http_lua_shdict.h"
27 : #include "ngx_http_lua_ssl_certby.h"
28 : #include "ngx_http_lua_lex.h"
29 : #include "api/ngx_http_lua_api.h"
30 : #include "ngx_http_lua_log_ringbuf.h"
31 : #include "ngx_http_lua_log.h"
32 :
33 :
34 : typedef struct ngx_http_lua_block_parser_ctx_s
35 : ngx_http_lua_block_parser_ctx_t;
36 :
37 :
38 : #if defined(NDK) && NDK
39 : #include "ngx_http_lua_setby.h"
40 :
41 :
42 : static ngx_int_t ngx_http_lua_set_by_lua_init(ngx_http_request_t *r);
43 : #endif
44 :
45 : static u_char *ngx_http_lua_gen_chunk_name(ngx_conf_t *cf, const char *tag,
46 : size_t tag_len);
47 : static ngx_int_t ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf,
48 : ngx_http_lua_block_parser_ctx_t *ctx);
49 : static u_char *ngx_http_lua_strlstrn(u_char *s1, u_char *last, u_char *s2,
50 : size_t n);
51 :
52 :
53 : struct ngx_http_lua_block_parser_ctx_s {
54 : ngx_uint_t start_line;
55 : int token_len;
56 : };
57 :
58 :
59 : enum {
60 : FOUND_LEFT_CURLY = 0,
61 : FOUND_RIGHT_CURLY,
62 : FOUND_LEFT_LBRACKET_STR,
63 : FOUND_LBRACKET_STR = FOUND_LEFT_LBRACKET_STR,
64 : FOUND_LEFT_LBRACKET_CMT,
65 : FOUND_LBRACKET_CMT = FOUND_LEFT_LBRACKET_CMT,
66 : FOUND_RIGHT_LBRACKET,
67 : FOUND_COMMENT_LINE,
68 : FOUND_DOUBLE_QUOTED,
69 : FOUND_SINGLE_QUOTED
70 : };
71 :
72 :
73 : char *
74 0 : ngx_http_lua_shared_dict(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
75 : {
76 0 : ngx_http_lua_main_conf_t *lmcf = conf;
77 :
78 : ngx_str_t *value, name;
79 : ngx_shm_zone_t *zone;
80 : ngx_shm_zone_t **zp;
81 : ngx_http_lua_shdict_ctx_t *ctx;
82 : ssize_t size;
83 :
84 0 : if (lmcf->shdict_zones == NULL) {
85 0 : lmcf->shdict_zones = ngx_palloc(cf->pool, sizeof(ngx_array_t));
86 0 : if (lmcf->shdict_zones == NULL) {
87 0 : return NGX_CONF_ERROR;
88 : }
89 :
90 0 : if (ngx_array_init(lmcf->shdict_zones, cf->pool, 2,
91 : sizeof(ngx_shm_zone_t *))
92 : != NGX_OK)
93 : {
94 0 : return NGX_CONF_ERROR;
95 : }
96 : }
97 :
98 0 : value = cf->args->elts;
99 :
100 0 : ctx = NULL;
101 :
102 0 : if (value[1].len == 0) {
103 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
104 : "invalid lua shared dict name \"%V\"", &value[1]);
105 0 : return NGX_CONF_ERROR;
106 : }
107 :
108 0 : name = value[1];
109 :
110 0 : size = ngx_parse_size(&value[2]);
111 :
112 0 : if (size <= 8191) {
113 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
114 : "invalid lua shared dict size \"%V\"", &value[2]);
115 0 : return NGX_CONF_ERROR;
116 : }
117 :
118 0 : ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_lua_shdict_ctx_t));
119 0 : if (ctx == NULL) {
120 0 : return NGX_CONF_ERROR;
121 : }
122 :
123 0 : ctx->name = name;
124 0 : ctx->main_conf = lmcf;
125 0 : ctx->log = &cf->cycle->new_log;
126 :
127 0 : zone = ngx_http_lua_shared_memory_add(cf, &name, (size_t) size,
128 : &ngx_http_lua_module);
129 0 : if (zone == NULL) {
130 0 : return NGX_CONF_ERROR;
131 : }
132 :
133 0 : if (zone->data) {
134 0 : ctx = zone->data;
135 :
136 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
137 : "lua_shared_dict \"%V\" is already defined as "
138 : "\"%V\"", &name, &ctx->name);
139 0 : return NGX_CONF_ERROR;
140 : }
141 :
142 0 : zone->init = ngx_http_lua_shdict_init_zone;
143 0 : zone->data = ctx;
144 :
145 0 : zp = ngx_array_push(lmcf->shdict_zones);
146 0 : if (zp == NULL) {
147 0 : return NGX_CONF_ERROR;
148 : }
149 :
150 0 : *zp = zone;
151 :
152 0 : lmcf->requires_shm = 1;
153 :
154 0 : return NGX_CONF_OK;
155 : }
156 :
157 :
158 : char *
159 0 : ngx_http_lua_code_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
160 : {
161 0 : char *p = conf;
162 : ngx_flag_t *fp;
163 : char *ret;
164 :
165 0 : ret = ngx_conf_set_flag_slot(cf, cmd, conf);
166 0 : if (ret != NGX_CONF_OK) {
167 0 : return ret;
168 : }
169 :
170 0 : fp = (ngx_flag_t *) (p + cmd->offset);
171 :
172 0 : if (!*fp) {
173 0 : ngx_conf_log_error(NGX_LOG_ALERT, cf, 0,
174 : "lua_code_cache is off; this will hurt "
175 : "performance");
176 : }
177 :
178 0 : return NGX_CONF_OK;
179 : }
180 :
181 :
182 : char *
183 0 : ngx_http_lua_package_cpath(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
184 : {
185 0 : ngx_http_lua_main_conf_t *lmcf = conf;
186 : ngx_str_t *value;
187 :
188 0 : if (lmcf->lua_cpath.len != 0) {
189 0 : return "is duplicate";
190 : }
191 :
192 : dd("enter");
193 :
194 0 : value = cf->args->elts;
195 :
196 0 : lmcf->lua_cpath.len = value[1].len;
197 0 : lmcf->lua_cpath.data = value[1].data;
198 :
199 0 : return NGX_CONF_OK;
200 : }
201 :
202 :
203 : char *
204 0 : ngx_http_lua_package_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
205 : {
206 0 : ngx_http_lua_main_conf_t *lmcf = conf;
207 : ngx_str_t *value;
208 :
209 0 : if (lmcf->lua_path.len != 0) {
210 0 : return "is duplicate";
211 : }
212 :
213 : dd("enter");
214 :
215 0 : value = cf->args->elts;
216 :
217 0 : lmcf->lua_path.len = value[1].len;
218 0 : lmcf->lua_path.data = value[1].data;
219 :
220 0 : return NGX_CONF_OK;
221 : }
222 :
223 :
224 : #if defined(NDK) && NDK
225 : char *
226 0 : ngx_http_lua_set_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
227 : void *conf)
228 : {
229 : char *rv;
230 : ngx_conf_t save;
231 :
232 0 : save = *cf;
233 0 : cf->handler = ngx_http_lua_set_by_lua;
234 0 : cf->handler_conf = conf;
235 :
236 0 : rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
237 :
238 0 : *cf = save;
239 :
240 0 : return rv;
241 : }
242 :
243 :
244 : char *
245 0 : ngx_http_lua_set_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
246 : {
247 : u_char *p;
248 : ngx_str_t *value;
249 : ngx_str_t target;
250 : ndk_set_var_t filter;
251 :
252 : ngx_http_lua_set_var_data_t *filter_data;
253 :
254 : /*
255 : * value[0] = "set_by_lua"
256 : * value[1] = target variable name
257 : * value[2] = lua script source to be executed
258 : * value[3..] = real params
259 : * */
260 0 : value = cf->args->elts;
261 0 : target = value[1];
262 :
263 0 : filter.type = NDK_SET_VAR_MULTI_VALUE_DATA;
264 0 : filter.func = cmd->post;
265 0 : filter.size = cf->args->nelts - 3; /* get number of real params */
266 :
267 0 : filter_data = ngx_palloc(cf->pool, sizeof(ngx_http_lua_set_var_data_t));
268 0 : if (filter_data == NULL) {
269 0 : return NGX_CONF_ERROR;
270 : }
271 :
272 0 : filter_data->size = filter.size;
273 :
274 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1);
275 0 : if (p == NULL) {
276 0 : return NGX_CONF_ERROR;
277 : }
278 :
279 0 : filter_data->key = p;
280 :
281 0 : p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN);
282 0 : p = ngx_http_lua_digest_hex(p, value[2].data, value[2].len);
283 0 : *p = '\0';
284 :
285 0 : filter_data->script = value[2];
286 :
287 0 : filter.data = filter_data;
288 :
289 0 : return ndk_set_var_multi_value_core(cf, &target, &value[3], &filter);
290 : }
291 :
292 :
293 : char *
294 0 : ngx_http_lua_set_by_lua_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
295 : {
296 : u_char *p;
297 : ngx_str_t *value;
298 : ngx_str_t target;
299 : ndk_set_var_t filter;
300 :
301 : ngx_http_lua_set_var_data_t *filter_data;
302 :
303 : /*
304 : * value[0] = "set_by_lua_file"
305 : * value[1] = target variable name
306 : * value[2] = lua script file path to be executed
307 : * value[3..] = real params
308 : * */
309 0 : value = cf->args->elts;
310 0 : target = value[1];
311 :
312 0 : filter.type = NDK_SET_VAR_MULTI_VALUE_DATA;
313 0 : filter.func = cmd->post;
314 0 : filter.size = cf->args->nelts - 2; /* get number of real params and
315 : lua script */
316 :
317 0 : filter_data = ngx_palloc(cf->pool, sizeof(ngx_http_lua_set_var_data_t));
318 0 : if (filter_data == NULL) {
319 0 : return NGX_CONF_ERROR;
320 : }
321 :
322 0 : filter_data->size = filter.size;
323 :
324 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1);
325 0 : if (p == NULL) {
326 0 : return NGX_CONF_ERROR;
327 : }
328 :
329 0 : filter_data->key = p;
330 :
331 0 : p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN);
332 0 : p = ngx_http_lua_digest_hex(p, value[2].data, value[2].len);
333 0 : *p = '\0';
334 :
335 0 : ngx_str_null(&filter_data->script);
336 :
337 0 : filter.data = filter_data;
338 :
339 0 : return ndk_set_var_multi_value_core(cf, &target, &value[2], &filter);
340 : }
341 :
342 :
343 : ngx_int_t
344 0 : ngx_http_lua_filter_set_by_lua_inline(ngx_http_request_t *r, ngx_str_t *val,
345 : ngx_http_variable_value_t *v, void *data)
346 : {
347 : lua_State *L;
348 : ngx_int_t rc;
349 :
350 0 : ngx_http_lua_set_var_data_t *filter_data = data;
351 :
352 0 : if (ngx_http_lua_set_by_lua_init(r) != NGX_OK) {
353 0 : return NGX_ERROR;
354 : }
355 :
356 0 : L = ngx_http_lua_get_lua_vm(r, NULL);
357 :
358 : /* load Lua inline script (w/ cache) sp = 1 */
359 0 : rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L,
360 0 : filter_data->script.data,
361 : filter_data->script.len,
362 0 : filter_data->key, "=set_by_lua");
363 0 : if (rc != NGX_OK) {
364 0 : return NGX_ERROR;
365 : }
366 :
367 0 : rc = ngx_http_lua_set_by_chunk(L, r, val, v, filter_data->size,
368 : &filter_data->script);
369 0 : if (rc != NGX_OK) {
370 0 : return NGX_ERROR;
371 : }
372 :
373 0 : return NGX_OK;
374 : }
375 :
376 :
377 : ngx_int_t
378 0 : ngx_http_lua_filter_set_by_lua_file(ngx_http_request_t *r, ngx_str_t *val,
379 : ngx_http_variable_value_t *v, void *data)
380 : {
381 : lua_State *L;
382 : ngx_int_t rc;
383 : u_char *script_path;
384 : size_t nargs;
385 :
386 0 : ngx_http_lua_set_var_data_t *filter_data = data;
387 :
388 : dd("set by lua file");
389 :
390 0 : if (ngx_http_lua_set_by_lua_init(r) != NGX_OK) {
391 0 : return NGX_ERROR;
392 : }
393 :
394 0 : filter_data->script.data = v[0].data;
395 0 : filter_data->script.len = v[0].len;
396 :
397 : /* skip the lua file path argument */
398 0 : v++;
399 0 : nargs = filter_data->size - 1;
400 :
401 : dd("script: %.*s", (int) filter_data->script.len, filter_data->script.data);
402 : dd("nargs: %d", (int) nargs);
403 :
404 0 : script_path = ngx_http_lua_rebase_path(r->pool, filter_data->script.data,
405 : filter_data->script.len);
406 0 : if (script_path == NULL) {
407 0 : return NGX_ERROR;
408 : }
409 :
410 0 : L = ngx_http_lua_get_lua_vm(r, NULL);
411 :
412 : /* load Lua script file (w/ cache) sp = 1 */
413 0 : rc = ngx_http_lua_cache_loadfile(r->connection->log, L, script_path,
414 0 : filter_data->key);
415 0 : if (rc != NGX_OK) {
416 0 : return NGX_ERROR;
417 : }
418 :
419 0 : rc = ngx_http_lua_set_by_chunk(L, r, val, v, nargs, &filter_data->script);
420 0 : if (rc != NGX_OK) {
421 0 : return NGX_ERROR;
422 : }
423 :
424 0 : return NGX_OK;
425 : }
426 : #endif /* defined(NDK) && NDK */
427 :
428 :
429 : char *
430 0 : ngx_http_lua_rewrite_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
431 : void *conf)
432 : {
433 : char *rv;
434 : ngx_conf_t save;
435 :
436 0 : save = *cf;
437 0 : cf->handler = ngx_http_lua_rewrite_by_lua;
438 0 : cf->handler_conf = conf;
439 :
440 0 : rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
441 :
442 0 : *cf = save;
443 :
444 0 : return rv;
445 : }
446 :
447 :
448 : char *
449 0 : ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
450 : {
451 : u_char *p, *chunkname;
452 : ngx_str_t *value;
453 : ngx_http_lua_main_conf_t *lmcf;
454 0 : ngx_http_lua_loc_conf_t *llcf = conf;
455 :
456 : ngx_http_compile_complex_value_t ccv;
457 :
458 : dd("enter");
459 :
460 : #if defined(nginx_version) && nginx_version >= 8042 && nginx_version <= 8053
461 : return "does not work with " NGINX_VER;
462 : #endif
463 :
464 : /* must specify a content handler */
465 0 : if (cmd->post == NULL) {
466 0 : return NGX_CONF_ERROR;
467 : }
468 :
469 0 : if (llcf->rewrite_handler) {
470 0 : return "is duplicate";
471 : }
472 :
473 0 : value = cf->args->elts;
474 :
475 0 : if (value[1].len == 0) {
476 : /* Oops...Invalid location conf */
477 0 : ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
478 : "invalid location config: no runnable Lua code");
479 :
480 0 : return NGX_CONF_ERROR;
481 : }
482 :
483 0 : if (cmd->post == ngx_http_lua_rewrite_handler_inline) {
484 0 : chunkname = ngx_http_lua_gen_chunk_name(cf, "rewrite_by_lua",
485 : sizeof("rewrite_by_lua") - 1);
486 0 : if (chunkname == NULL) {
487 0 : return NGX_CONF_ERROR;
488 : }
489 :
490 0 : llcf->rewrite_chunkname = chunkname;
491 :
492 : /* Don't eval nginx variables for inline lua code */
493 :
494 0 : llcf->rewrite_src.value = value[1];
495 :
496 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1);
497 0 : if (p == NULL) {
498 0 : return NGX_CONF_ERROR;
499 : }
500 :
501 0 : llcf->rewrite_src_key = p;
502 :
503 0 : p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN);
504 0 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
505 0 : *p = '\0';
506 :
507 : } else {
508 0 : ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
509 0 : ccv.cf = cf;
510 0 : ccv.value = &value[1];
511 0 : ccv.complex_value = &llcf->rewrite_src;
512 :
513 0 : if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
514 0 : return NGX_CONF_ERROR;
515 : }
516 :
517 0 : if (llcf->rewrite_src.lengths == NULL) {
518 : /* no variable found */
519 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1);
520 0 : if (p == NULL) {
521 0 : return NGX_CONF_ERROR;
522 : }
523 :
524 0 : llcf->rewrite_src_key = p;
525 :
526 0 : p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN);
527 0 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
528 0 : *p = '\0';
529 : }
530 : }
531 :
532 0 : llcf->rewrite_handler = (ngx_http_handler_pt) cmd->post;
533 :
534 0 : lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module);
535 :
536 0 : lmcf->requires_rewrite = 1;
537 0 : lmcf->requires_capture_filter = 1;
538 :
539 0 : return NGX_CONF_OK;
540 : }
541 :
542 :
543 : char *
544 0 : ngx_http_lua_access_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
545 : void *conf)
546 : {
547 : char *rv;
548 : ngx_conf_t save;
549 :
550 0 : save = *cf;
551 0 : cf->handler = ngx_http_lua_access_by_lua;
552 0 : cf->handler_conf = conf;
553 :
554 0 : rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
555 :
556 0 : *cf = save;
557 :
558 0 : return rv;
559 : }
560 :
561 :
562 : char *
563 0 : ngx_http_lua_access_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
564 : {
565 : u_char *p, *chunkname;
566 : ngx_str_t *value;
567 : ngx_http_lua_main_conf_t *lmcf;
568 0 : ngx_http_lua_loc_conf_t *llcf = conf;
569 :
570 : ngx_http_compile_complex_value_t ccv;
571 :
572 : dd("enter");
573 :
574 : /* must specify a content handler */
575 0 : if (cmd->post == NULL) {
576 0 : return NGX_CONF_ERROR;
577 : }
578 :
579 0 : if (llcf->access_handler) {
580 0 : return "is duplicate";
581 : }
582 :
583 0 : value = cf->args->elts;
584 :
585 0 : if (value[1].len == 0) {
586 : /* Oops...Invalid location conf */
587 0 : ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
588 : "invalid location config: no runnable Lua code");
589 :
590 0 : return NGX_CONF_ERROR;
591 : }
592 :
593 0 : if (cmd->post == ngx_http_lua_access_handler_inline) {
594 0 : chunkname = ngx_http_lua_gen_chunk_name(cf, "access_by_lua",
595 : sizeof("access_by_lua") - 1);
596 0 : if (chunkname == NULL) {
597 0 : return NGX_CONF_ERROR;
598 : }
599 :
600 0 : llcf->access_chunkname = chunkname;
601 :
602 : /* Don't eval nginx variables for inline lua code */
603 :
604 0 : llcf->access_src.value = value[1];
605 :
606 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1);
607 0 : if (p == NULL) {
608 0 : return NGX_CONF_ERROR;
609 : }
610 :
611 0 : llcf->access_src_key = p;
612 :
613 0 : p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN);
614 0 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
615 0 : *p = '\0';
616 :
617 : } else {
618 0 : ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
619 0 : ccv.cf = cf;
620 0 : ccv.value = &value[1];
621 0 : ccv.complex_value = &llcf->access_src;
622 :
623 0 : if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
624 0 : return NGX_CONF_ERROR;
625 : }
626 :
627 0 : if (llcf->access_src.lengths == NULL) {
628 : /* no variable found */
629 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1);
630 0 : if (p == NULL) {
631 0 : return NGX_CONF_ERROR;
632 : }
633 :
634 0 : llcf->access_src_key = p;
635 :
636 0 : p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN);
637 0 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
638 0 : *p = '\0';
639 : }
640 : }
641 :
642 0 : llcf->access_handler = (ngx_http_handler_pt) cmd->post;
643 :
644 0 : lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module);
645 :
646 0 : lmcf->requires_access = 1;
647 0 : lmcf->requires_capture_filter = 1;
648 :
649 0 : return NGX_CONF_OK;
650 : }
651 :
652 :
653 : char *
654 1 : ngx_http_lua_content_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
655 : void *conf)
656 : {
657 : char *rv;
658 : ngx_conf_t save;
659 :
660 1 : save = *cf;
661 1 : cf->handler = ngx_http_lua_content_by_lua;
662 1 : cf->handler_conf = conf;
663 :
664 1 : rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
665 :
666 1 : *cf = save;
667 :
668 1 : return rv;
669 : }
670 :
671 :
672 : char *
673 1 : ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
674 : {
675 : u_char *p;
676 : u_char *chunkname;
677 : ngx_str_t *value;
678 : ngx_http_core_loc_conf_t *clcf;
679 : ngx_http_lua_main_conf_t *lmcf;
680 1 : ngx_http_lua_loc_conf_t *llcf = conf;
681 :
682 : ngx_http_compile_complex_value_t ccv;
683 :
684 : dd("enter");
685 :
686 : /* must specify a content handler */
687 1 : if (cmd->post == NULL) {
688 0 : return NGX_CONF_ERROR;
689 : }
690 :
691 1 : if (llcf->content_handler) {
692 0 : return "is duplicate";
693 : }
694 :
695 1 : value = cf->args->elts;
696 :
697 : dd("value[0]: %.*s", (int) value[0].len, value[0].data);
698 : dd("value[1]: %.*s", (int) value[1].len, value[1].data);
699 :
700 1 : if (value[1].len == 0) {
701 : /* Oops...Invalid location conf */
702 0 : ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
703 : "invalid location config: no runnable Lua code");
704 0 : return NGX_CONF_ERROR;
705 : }
706 :
707 1 : if (cmd->post == ngx_http_lua_content_handler_inline) {
708 1 : chunkname = ngx_http_lua_gen_chunk_name(cf, "content_by_lua",
709 : sizeof("content_by_lua") - 1);
710 1 : if (chunkname == NULL) {
711 0 : return NGX_CONF_ERROR;
712 : }
713 :
714 1 : llcf->content_chunkname = chunkname;
715 :
716 : dd("chunkname: %s", chunkname);
717 :
718 : /* Don't eval nginx variables for inline lua code */
719 :
720 1 : llcf->content_src.value = value[1];
721 :
722 1 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1);
723 1 : if (p == NULL) {
724 0 : return NGX_CONF_ERROR;
725 : }
726 :
727 1 : llcf->content_src_key = p;
728 :
729 1 : p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN);
730 1 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
731 1 : *p = '\0';
732 :
733 : } else {
734 0 : ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
735 0 : ccv.cf = cf;
736 0 : ccv.value = &value[1];
737 0 : ccv.complex_value = &llcf->content_src;
738 :
739 0 : if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
740 0 : return NGX_CONF_ERROR;
741 : }
742 :
743 0 : if (llcf->content_src.lengths == NULL) {
744 : /* no variable found */
745 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1);
746 0 : if (p == NULL) {
747 0 : return NGX_CONF_ERROR;
748 : }
749 :
750 0 : llcf->content_src_key = p;
751 :
752 0 : p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN);
753 0 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
754 0 : *p = '\0';
755 : }
756 : }
757 :
758 1 : llcf->content_handler = (ngx_http_handler_pt) cmd->post;
759 :
760 1 : lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module);
761 :
762 1 : lmcf->requires_capture_filter = 1;
763 :
764 : /* register location content handler */
765 1 : clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
766 1 : if (clcf == NULL) {
767 0 : return NGX_CONF_ERROR;
768 : }
769 :
770 1 : clcf->handler = ngx_http_lua_content_handler;
771 :
772 1 : return NGX_CONF_OK;
773 : }
774 :
775 :
776 : char *
777 0 : ngx_http_lua_log_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
778 : void *conf)
779 : {
780 : char *rv;
781 : ngx_conf_t save;
782 :
783 0 : save = *cf;
784 0 : cf->handler = ngx_http_lua_log_by_lua;
785 0 : cf->handler_conf = conf;
786 :
787 0 : rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
788 :
789 0 : *cf = save;
790 :
791 0 : return rv;
792 : }
793 :
794 :
795 : char *
796 0 : ngx_http_lua_log_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
797 : {
798 : u_char *p, *chunkname;
799 : ngx_str_t *value;
800 : ngx_http_lua_main_conf_t *lmcf;
801 0 : ngx_http_lua_loc_conf_t *llcf = conf;
802 :
803 : ngx_http_compile_complex_value_t ccv;
804 :
805 : dd("enter");
806 :
807 : /* must specify a content handler */
808 0 : if (cmd->post == NULL) {
809 0 : return NGX_CONF_ERROR;
810 : }
811 :
812 0 : if (llcf->log_handler) {
813 0 : return "is duplicate";
814 : }
815 :
816 0 : value = cf->args->elts;
817 :
818 0 : if (value[1].len == 0) {
819 : /* Oops...Invalid location conf */
820 0 : ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
821 : "invalid location config: no runnable Lua code");
822 :
823 0 : return NGX_CONF_ERROR;
824 : }
825 :
826 0 : if (cmd->post == ngx_http_lua_log_handler_inline) {
827 0 : chunkname = ngx_http_lua_gen_chunk_name(cf, "log_by_lua",
828 : sizeof("log_by_lua") - 1);
829 0 : if (chunkname == NULL) {
830 0 : return NGX_CONF_ERROR;
831 : }
832 :
833 0 : llcf->log_chunkname = chunkname;
834 :
835 : /* Don't eval nginx variables for inline lua code */
836 :
837 0 : llcf->log_src.value = value[1];
838 :
839 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1);
840 0 : if (p == NULL) {
841 0 : return NGX_CONF_ERROR;
842 : }
843 :
844 0 : llcf->log_src_key = p;
845 :
846 0 : p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN);
847 0 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
848 0 : *p = '\0';
849 :
850 : } else {
851 0 : ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
852 0 : ccv.cf = cf;
853 0 : ccv.value = &value[1];
854 0 : ccv.complex_value = &llcf->log_src;
855 :
856 0 : if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
857 0 : return NGX_CONF_ERROR;
858 : }
859 :
860 0 : if (llcf->log_src.lengths == NULL) {
861 : /* no variable found */
862 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1);
863 0 : if (p == NULL) {
864 0 : return NGX_CONF_ERROR;
865 : }
866 :
867 0 : llcf->log_src_key = p;
868 :
869 0 : p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN);
870 0 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
871 0 : *p = '\0';
872 : }
873 : }
874 :
875 0 : llcf->log_handler = (ngx_http_handler_pt) cmd->post;
876 :
877 0 : lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module);
878 :
879 0 : lmcf->requires_log = 1;
880 :
881 0 : return NGX_CONF_OK;
882 : }
883 :
884 :
885 : char *
886 0 : ngx_http_lua_header_filter_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
887 : void *conf)
888 : {
889 : char *rv;
890 : ngx_conf_t save;
891 :
892 0 : save = *cf;
893 0 : cf->handler = ngx_http_lua_header_filter_by_lua;
894 0 : cf->handler_conf = conf;
895 :
896 0 : rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
897 :
898 0 : *cf = save;
899 :
900 0 : return rv;
901 : }
902 :
903 :
904 : char *
905 0 : ngx_http_lua_header_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
906 : void *conf)
907 : {
908 : u_char *p;
909 : ngx_str_t *value;
910 : ngx_http_lua_main_conf_t *lmcf;
911 0 : ngx_http_lua_loc_conf_t *llcf = conf;
912 :
913 : ngx_http_compile_complex_value_t ccv;
914 :
915 : dd("enter");
916 :
917 : /* must specify a content handler */
918 0 : if (cmd->post == NULL) {
919 0 : return NGX_CONF_ERROR;
920 : }
921 :
922 0 : if (llcf->header_filter_handler) {
923 0 : return "is duplicate";
924 : }
925 :
926 0 : value = cf->args->elts;
927 :
928 0 : if (value[1].len == 0) {
929 : /* Oops...Invalid location conf */
930 0 : ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
931 : "invalid location config: no runnable Lua code");
932 0 : return NGX_CONF_ERROR;
933 : }
934 :
935 0 : if (cmd->post == ngx_http_lua_header_filter_inline) {
936 : /* Don't eval nginx variables for inline lua code */
937 0 : llcf->header_filter_src.value = value[1];
938 :
939 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1);
940 0 : if (p == NULL) {
941 0 : return NGX_CONF_ERROR;
942 : }
943 :
944 0 : llcf->header_filter_src_key = p;
945 :
946 0 : p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN);
947 0 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
948 0 : *p = '\0';
949 :
950 : } else {
951 0 : ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
952 0 : ccv.cf = cf;
953 0 : ccv.value = &value[1];
954 0 : ccv.complex_value = &llcf->header_filter_src;
955 :
956 0 : if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
957 0 : return NGX_CONF_ERROR;
958 : }
959 :
960 0 : if (llcf->header_filter_src.lengths == NULL) {
961 : /* no variable found */
962 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1);
963 0 : if (p == NULL) {
964 0 : return NGX_CONF_ERROR;
965 : }
966 :
967 0 : llcf->header_filter_src_key = p;
968 :
969 0 : p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN);
970 0 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
971 0 : *p = '\0';
972 : }
973 : }
974 :
975 0 : llcf->header_filter_handler = (ngx_http_handler_pt) cmd->post;
976 :
977 0 : lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module);
978 :
979 0 : lmcf->requires_header_filter = 1;
980 :
981 0 : return NGX_CONF_OK;
982 : }
983 :
984 :
985 : char *
986 0 : ngx_http_lua_body_filter_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
987 : void *conf)
988 : {
989 : char *rv;
990 : ngx_conf_t save;
991 :
992 0 : save = *cf;
993 0 : cf->handler = ngx_http_lua_body_filter_by_lua;
994 0 : cf->handler_conf = conf;
995 :
996 0 : rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
997 :
998 0 : *cf = save;
999 :
1000 0 : return rv;
1001 : }
1002 :
1003 :
1004 : char *
1005 0 : ngx_http_lua_body_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
1006 : void *conf)
1007 : {
1008 : u_char *p;
1009 : ngx_str_t *value;
1010 : ngx_http_lua_main_conf_t *lmcf;
1011 0 : ngx_http_lua_loc_conf_t *llcf = conf;
1012 :
1013 : ngx_http_compile_complex_value_t ccv;
1014 :
1015 : dd("enter");
1016 :
1017 : /* must specify a content handler */
1018 0 : if (cmd->post == NULL) {
1019 0 : return NGX_CONF_ERROR;
1020 : }
1021 :
1022 0 : if (llcf->body_filter_handler) {
1023 0 : return "is duplicate";
1024 : }
1025 :
1026 0 : value = cf->args->elts;
1027 :
1028 0 : if (value[1].len == 0) {
1029 : /* Oops...Invalid location conf */
1030 0 : ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
1031 : "invalid location config: no runnable Lua code");
1032 0 : return NGX_CONF_ERROR;
1033 : }
1034 :
1035 0 : if (cmd->post == ngx_http_lua_body_filter_inline) {
1036 : /* Don't eval nginx variables for inline lua code */
1037 0 : llcf->body_filter_src.value = value[1];
1038 :
1039 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1);
1040 0 : if (p == NULL) {
1041 0 : return NGX_CONF_ERROR;
1042 : }
1043 :
1044 0 : llcf->body_filter_src_key = p;
1045 :
1046 0 : p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN);
1047 0 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
1048 0 : *p = '\0';
1049 :
1050 : } else {
1051 0 : ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
1052 0 : ccv.cf = cf;
1053 0 : ccv.value = &value[1];
1054 0 : ccv.complex_value = &llcf->body_filter_src;
1055 :
1056 0 : if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
1057 0 : return NGX_CONF_ERROR;
1058 : }
1059 :
1060 0 : if (llcf->body_filter_src.lengths == NULL) {
1061 : /* no variable found */
1062 0 : p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1);
1063 0 : if (p == NULL) {
1064 0 : return NGX_CONF_ERROR;
1065 : }
1066 :
1067 0 : llcf->body_filter_src_key = p;
1068 :
1069 0 : p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN);
1070 0 : p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len);
1071 0 : *p = '\0';
1072 : }
1073 : }
1074 :
1075 0 : llcf->body_filter_handler = (ngx_http_output_body_filter_pt) cmd->post;
1076 :
1077 0 : lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module);
1078 :
1079 0 : lmcf->requires_body_filter = 1;
1080 0 : lmcf->requires_header_filter = 1;
1081 :
1082 0 : return NGX_CONF_OK;
1083 : }
1084 :
1085 :
1086 : char *
1087 0 : ngx_http_lua_init_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
1088 : void *conf)
1089 : {
1090 : char *rv;
1091 : ngx_conf_t save;
1092 :
1093 0 : save = *cf;
1094 0 : cf->handler = ngx_http_lua_init_by_lua;
1095 0 : cf->handler_conf = conf;
1096 :
1097 0 : rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
1098 :
1099 0 : *cf = save;
1100 :
1101 0 : return rv;
1102 : }
1103 :
1104 :
1105 : char *
1106 0 : ngx_http_lua_init_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
1107 : void *conf)
1108 : {
1109 : u_char *name;
1110 : ngx_str_t *value;
1111 0 : ngx_http_lua_main_conf_t *lmcf = conf;
1112 :
1113 : dd("enter");
1114 :
1115 : /* must specify a content handler */
1116 0 : if (cmd->post == NULL) {
1117 0 : return NGX_CONF_ERROR;
1118 : }
1119 :
1120 0 : if (lmcf->init_handler) {
1121 0 : return "is duplicate";
1122 : }
1123 :
1124 0 : value = cf->args->elts;
1125 :
1126 0 : if (value[1].len == 0) {
1127 : /* Oops...Invalid location conf */
1128 0 : ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
1129 : "invalid location config: no runnable Lua code");
1130 0 : return NGX_CONF_ERROR;
1131 : }
1132 :
1133 0 : lmcf->init_handler = (ngx_http_lua_main_conf_handler_pt) cmd->post;
1134 :
1135 0 : if (cmd->post == ngx_http_lua_init_by_file) {
1136 0 : name = ngx_http_lua_rebase_path(cf->pool, value[1].data,
1137 0 : value[1].len);
1138 0 : if (name == NULL) {
1139 0 : return NGX_CONF_ERROR;
1140 : }
1141 :
1142 0 : lmcf->init_src.data = name;
1143 0 : lmcf->init_src.len = ngx_strlen(name);
1144 :
1145 : } else {
1146 0 : lmcf->init_src = value[1];
1147 : }
1148 :
1149 0 : return NGX_CONF_OK;
1150 : }
1151 :
1152 :
1153 : char *
1154 0 : ngx_http_lua_init_worker_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
1155 : void *conf)
1156 : {
1157 : char *rv;
1158 : ngx_conf_t save;
1159 :
1160 0 : save = *cf;
1161 0 : cf->handler = ngx_http_lua_init_worker_by_lua;
1162 0 : cf->handler_conf = conf;
1163 :
1164 0 : rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
1165 :
1166 0 : *cf = save;
1167 :
1168 0 : return rv;
1169 : }
1170 :
1171 :
1172 : char *
1173 0 : ngx_http_lua_init_worker_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
1174 : void *conf)
1175 : {
1176 : u_char *name;
1177 : ngx_str_t *value;
1178 0 : ngx_http_lua_main_conf_t *lmcf = conf;
1179 :
1180 : dd("enter");
1181 :
1182 : /* must specify a content handler */
1183 0 : if (cmd->post == NULL) {
1184 0 : return NGX_CONF_ERROR;
1185 : }
1186 :
1187 0 : if (lmcf->init_worker_handler) {
1188 0 : return "is duplicate";
1189 : }
1190 :
1191 0 : value = cf->args->elts;
1192 :
1193 0 : lmcf->init_worker_handler = (ngx_http_lua_main_conf_handler_pt) cmd->post;
1194 :
1195 0 : if (cmd->post == ngx_http_lua_init_worker_by_file) {
1196 0 : name = ngx_http_lua_rebase_path(cf->pool, value[1].data,
1197 0 : value[1].len);
1198 0 : if (name == NULL) {
1199 0 : return NGX_CONF_ERROR;
1200 : }
1201 :
1202 0 : lmcf->init_worker_src.data = name;
1203 0 : lmcf->init_worker_src.len = ngx_strlen(name);
1204 :
1205 : } else {
1206 0 : lmcf->init_worker_src = value[1];
1207 : }
1208 :
1209 0 : return NGX_CONF_OK;
1210 : }
1211 :
1212 :
1213 : #if defined(NDK) && NDK
1214 : static ngx_int_t
1215 0 : ngx_http_lua_set_by_lua_init(ngx_http_request_t *r)
1216 : {
1217 : lua_State *L;
1218 : ngx_http_lua_ctx_t *ctx;
1219 : ngx_http_cleanup_t *cln;
1220 :
1221 0 : ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
1222 0 : if (ctx == NULL) {
1223 0 : ctx = ngx_http_lua_create_ctx(r);
1224 0 : if (ctx == NULL) {
1225 0 : return NGX_ERROR;
1226 : }
1227 :
1228 : } else {
1229 0 : L = ngx_http_lua_get_lua_vm(r, ctx);
1230 0 : ngx_http_lua_reset_ctx(r, L, ctx);
1231 : }
1232 :
1233 0 : if (ctx->cleanup == NULL) {
1234 0 : cln = ngx_http_cleanup_add(r, 0);
1235 0 : if (cln == NULL) {
1236 0 : return NGX_ERROR;
1237 : }
1238 :
1239 0 : cln->handler = ngx_http_lua_request_cleanup_handler;
1240 0 : cln->data = ctx;
1241 0 : ctx->cleanup = &cln->handler;
1242 : }
1243 :
1244 0 : ctx->context = NGX_HTTP_LUA_CONTEXT_SET;
1245 0 : return NGX_OK;
1246 : }
1247 : #endif
1248 :
1249 :
1250 : static u_char *
1251 1 : ngx_http_lua_gen_chunk_name(ngx_conf_t *cf, const char *tag, size_t tag_len)
1252 : {
1253 : u_char *p, *out;
1254 : size_t len;
1255 :
1256 1 : len = sizeof("=(:)") - 1 + tag_len + cf->conf_file->file.name.len
1257 : + NGX_INT64_LEN + 1;
1258 :
1259 1 : out = ngx_palloc(cf->pool, len);
1260 1 : if (out == NULL) {
1261 0 : return NULL;
1262 : }
1263 :
1264 1 : if (cf->conf_file->file.name.len) {
1265 1 : p = cf->conf_file->file.name.data + cf->conf_file->file.name.len;
1266 12 : while (--p >= cf->conf_file->file.name.data) {
1267 11 : if (*p == '/' || *p == '\\') {
1268 1 : p++;
1269 1 : goto found;
1270 : }
1271 : }
1272 :
1273 0 : p++;
1274 :
1275 : } else {
1276 0 : p = cf->conf_file->file.name.data;
1277 : }
1278 :
1279 1 : found:
1280 :
1281 2 : ngx_snprintf(out, len, "=%*s(%*s:%d)%Z",
1282 1 : tag_len, tag, cf->conf_file->file.name.data
1283 1 : + cf->conf_file->file.name.len - p,
1284 1 : p, cf->conf_file->line);
1285 :
1286 1 : return out;
1287 : }
1288 :
1289 :
1290 : /* a specialized version of the standard ngx_conf_parse() function */
1291 : char *
1292 1 : ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf, ngx_command_t *cmd)
1293 : {
1294 : ngx_http_lua_block_parser_ctx_t ctx;
1295 :
1296 1 : int level = 1;
1297 : char *rv;
1298 : u_char *p;
1299 : size_t len;
1300 : ngx_str_t *src, *dst;
1301 : ngx_int_t rc;
1302 : ngx_uint_t i, start_line;
1303 : ngx_array_t *saved;
1304 : enum {
1305 : parse_block = 0,
1306 : parse_param
1307 : } type;
1308 :
1309 1 : if (cf->conf_file->file.fd != NGX_INVALID_FILE) {
1310 :
1311 1 : type = parse_block;
1312 :
1313 : } else {
1314 0 : type = parse_param;
1315 : }
1316 :
1317 1 : saved = cf->args;
1318 :
1319 1 : cf->args = ngx_array_create(cf->temp_pool, 4, sizeof(ngx_str_t));
1320 1 : if (cf->args == NULL) {
1321 0 : return NGX_CONF_ERROR;
1322 : }
1323 :
1324 1 : ctx.token_len = 0;
1325 1 : start_line = cf->conf_file->line;
1326 :
1327 : dd("init start line: %d", (int) start_line);
1328 :
1329 1 : ctx.start_line = start_line;
1330 :
1331 : for ( ;; ) {
1332 9 : rc = ngx_http_lua_conf_read_lua_token(cf, &ctx);
1333 :
1334 : dd("parser start line: %d", (int) start_line);
1335 :
1336 5 : switch (rc) {
1337 :
1338 0 : case NGX_ERROR:
1339 0 : goto done;
1340 :
1341 0 : case FOUND_LEFT_CURLY:
1342 :
1343 0 : ctx.start_line = cf->conf_file->line;
1344 :
1345 0 : if (type == parse_param) {
1346 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1347 : "block directives are not supported "
1348 : "in -g option");
1349 0 : goto failed;
1350 : }
1351 :
1352 0 : level++;
1353 : dd("seen block start: level=%d", (int) level);
1354 0 : break;
1355 :
1356 1 : case FOUND_RIGHT_CURLY:
1357 :
1358 1 : level--;
1359 : dd("seen block done: level=%d", (int) level);
1360 :
1361 1 : if (type != parse_block || level < 0) {
1362 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1363 : "unexpected \"}\": level %d, "
1364 : "starting at line %ui", level,
1365 : start_line);
1366 0 : goto failed;
1367 : }
1368 :
1369 1 : if (level == 0) {
1370 1 : ngx_http_lua_assert(cf->handler);
1371 :
1372 1 : src = cf->args->elts;
1373 :
1374 6 : for (len = 0, i = 0; i < cf->args->nelts; i++) {
1375 5 : len += src[i].len;
1376 : }
1377 :
1378 : dd("saved nelts: %d", (int) saved->nelts);
1379 : dd("temp nelts: %d", (int) cf->args->nelts);
1380 : #if 0
1381 : ngx_http_lua_assert(saved->nelts == 1);
1382 : #endif
1383 :
1384 1 : dst = ngx_array_push(saved);
1385 1 : if (dst == NULL) {
1386 0 : return NGX_CONF_ERROR;
1387 : }
1388 1 : dst->len = len;
1389 1 : dst->len--; /* skip the trailing '}' block terminator */
1390 :
1391 1 : p = ngx_palloc(cf->pool, len);
1392 1 : if (p == NULL) {
1393 0 : return NGX_CONF_ERROR;
1394 : }
1395 1 : dst->data = p;
1396 :
1397 6 : for (i = 0; i < cf->args->nelts; i++) {
1398 5 : p = ngx_copy(p, src[i].data, src[i].len);
1399 : }
1400 :
1401 1 : p[-1] = '\0'; /* override the last '}' char to null */
1402 :
1403 1 : cf->args = saved;
1404 :
1405 1 : rv = (*cf->handler)(cf, cmd, cf->handler_conf);
1406 1 : if (rv == NGX_CONF_OK) {
1407 1 : goto done;
1408 : }
1409 :
1410 0 : if (rv == NGX_CONF_ERROR) {
1411 0 : goto failed;
1412 : }
1413 :
1414 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);
1415 :
1416 0 : goto failed;
1417 : }
1418 :
1419 0 : break;
1420 :
1421 4 : case FOUND_LBRACKET_STR:
1422 : case FOUND_LBRACKET_CMT:
1423 : case FOUND_RIGHT_LBRACKET:
1424 : case FOUND_COMMENT_LINE:
1425 : case FOUND_DOUBLE_QUOTED:
1426 : case FOUND_SINGLE_QUOTED:
1427 4 : break;
1428 :
1429 0 : default:
1430 :
1431 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1432 : "unknown return value from the lexer: %i", rc);
1433 0 : goto failed;
1434 : }
1435 : }
1436 :
1437 0 : failed:
1438 :
1439 0 : rc = NGX_ERROR;
1440 :
1441 1 : done:
1442 :
1443 1 : if (rc == NGX_ERROR) {
1444 0 : return NGX_CONF_ERROR;
1445 : }
1446 :
1447 1 : return NGX_CONF_OK;
1448 : }
1449 :
1450 :
1451 : static ngx_int_t
1452 5 : ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf,
1453 : ngx_http_lua_block_parser_ctx_t *ctx)
1454 : {
1455 : enum {
1456 : OVEC_SIZE = 2
1457 : };
1458 : int i, rc;
1459 : int ovec[OVEC_SIZE];
1460 : u_char *start, *p, *q, ch;
1461 : off_t file_size;
1462 : size_t len, buf_size;
1463 : ssize_t n, size;
1464 : ngx_uint_t start_line;
1465 : ngx_str_t *word;
1466 : ngx_buf_t *b;
1467 : #if nginx_version >= 1009002
1468 : ngx_buf_t *dump;
1469 : #endif
1470 :
1471 5 : b = cf->conf_file->buffer;
1472 : #if nginx_version >= 1009002
1473 5 : dump = cf->conf_file->dump;
1474 : #endif
1475 5 : start = b->pos;
1476 5 : start_line = cf->conf_file->line;
1477 5 : buf_size = b->end - b->start;
1478 :
1479 : dd("lexer start line: %d", (int) start_line);
1480 :
1481 5 : file_size = ngx_file_size(&cf->conf_file->file.info);
1482 :
1483 : for ( ;; ) {
1484 :
1485 5 : if (b->pos >= b->last
1486 5 : || (b->last - b->pos < (b->end - b->start) / 3
1487 5 : && cf->conf_file->file.offset < file_size))
1488 : {
1489 :
1490 0 : if (cf->conf_file->file.offset >= file_size) {
1491 :
1492 0 : cf->conf_file->line = ctx->start_line;
1493 :
1494 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1495 : "unexpected end of file, expecting "
1496 : "terminating characters for lua code "
1497 : "block");
1498 0 : return NGX_ERROR;
1499 : }
1500 :
1501 0 : len = b->last - start;
1502 :
1503 0 : if (len == buf_size) {
1504 :
1505 0 : cf->conf_file->line = start_line;
1506 :
1507 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1508 : "too long lua code block, probably "
1509 : "missing terminating characters");
1510 :
1511 0 : return NGX_ERROR;
1512 : }
1513 :
1514 0 : if (len) {
1515 0 : ngx_memmove(b->start, start, len);
1516 : }
1517 :
1518 0 : size = (ssize_t) (file_size - cf->conf_file->file.offset);
1519 :
1520 0 : if (size > b->end - (b->start + len)) {
1521 0 : size = b->end - (b->start + len);
1522 : }
1523 :
1524 0 : n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
1525 0 : cf->conf_file->file.offset);
1526 :
1527 0 : if (n == NGX_ERROR) {
1528 0 : return NGX_ERROR;
1529 : }
1530 :
1531 0 : if (n != size) {
1532 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1533 : ngx_read_file_n " returned "
1534 : "only %z bytes instead of %z",
1535 : n, size);
1536 0 : return NGX_ERROR;
1537 : }
1538 :
1539 0 : b->pos = b->start + (b->pos - start);
1540 0 : b->last = b->start + len + n;
1541 0 : start = b->start;
1542 :
1543 : #if nginx_version >= 1009002
1544 0 : if (dump) {
1545 0 : dump->last = ngx_cpymem(dump->last, b->start + len, size);
1546 : }
1547 : #endif
1548 : }
1549 :
1550 5 : rc = ngx_http_lua_lex(b->pos, b->last - b->pos, ovec);
1551 :
1552 5 : if (rc < 0) { /* no match */
1553 : /* alas. the lexer does not yet support streaming processing. need
1554 : * more work below */
1555 :
1556 0 : if (cf->conf_file->file.offset >= file_size) {
1557 :
1558 0 : cf->conf_file->line = ctx->start_line;
1559 :
1560 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1561 : "unexpected end of file, expecting "
1562 : "terminating characters for lua code "
1563 : "block");
1564 0 : return NGX_ERROR;
1565 : }
1566 :
1567 0 : len = b->last - b->pos;
1568 :
1569 0 : if (len == buf_size) {
1570 :
1571 0 : cf->conf_file->line = start_line;
1572 :
1573 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1574 : "too long lua code block, probably "
1575 : "missing terminating characters");
1576 :
1577 0 : return NGX_ERROR;
1578 : }
1579 :
1580 0 : if (len) {
1581 0 : ngx_memcpy(b->start, b->pos, len);
1582 : }
1583 :
1584 0 : size = (ssize_t) (file_size - cf->conf_file->file.offset);
1585 :
1586 0 : if (size > b->end - (b->start + len)) {
1587 0 : size = b->end - (b->start + len);
1588 : }
1589 :
1590 0 : n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
1591 0 : cf->conf_file->file.offset);
1592 :
1593 0 : if (n == NGX_ERROR) {
1594 0 : return NGX_ERROR;
1595 : }
1596 :
1597 0 : if (n != size) {
1598 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1599 : ngx_read_file_n " returned "
1600 : "only %z bytes instead of %z",
1601 : n, size);
1602 0 : return NGX_ERROR;
1603 : }
1604 :
1605 0 : b->pos = b->start + len;
1606 0 : b->last = b->pos + n;
1607 0 : start = b->start;
1608 :
1609 0 : continue;
1610 : }
1611 :
1612 5 : if (rc == FOUND_LEFT_LBRACKET_STR || rc == FOUND_LEFT_LBRACKET_CMT) {
1613 :
1614 : /* we update the line numbers for best error messages when the
1615 : * closing long bracket is missing */
1616 :
1617 0 : for (i = 0; i < ovec[0]; i++) {
1618 0 : ch = b->pos[i];
1619 0 : if (ch == LF) {
1620 0 : cf->conf_file->line++;
1621 : }
1622 : }
1623 :
1624 0 : b->pos += ovec[0];
1625 0 : ovec[1] -= ovec[0];
1626 0 : ovec[0] = 0;
1627 :
1628 0 : if (rc == FOUND_LEFT_LBRACKET_CMT) {
1629 0 : p = &b->pos[2]; /* we skip the leading "--" prefix */
1630 0 : rc = FOUND_LBRACKET_CMT;
1631 :
1632 : } else {
1633 0 : p = b->pos;
1634 0 : rc = FOUND_LBRACKET_STR;
1635 : }
1636 :
1637 : /* we temporarily rewrite [=*[ in the input buffer to ]=*] to
1638 : * construct the pattern for the corresponding closing long
1639 : * bracket without additional buffers. */
1640 :
1641 0 : ngx_http_lua_assert(p[0] == '[');
1642 0 : p[0] = ']';
1643 :
1644 0 : ngx_http_lua_assert(b->pos[ovec[1] - 1] == '[');
1645 0 : b->pos[ovec[1] - 1] = ']';
1646 :
1647 : /* search for the corresponding closing bracket */
1648 :
1649 : dd("search pattern for the closing long bracket: \"%.*s\" (len=%d)",
1650 : (int) (b->pos + ovec[1] - p), p, (int) (b->pos + ovec[1] - p));
1651 :
1652 0 : q = ngx_http_lua_strlstrn(b->pos + ovec[1], b->last, p,
1653 0 : b->pos + ovec[1] - p - 1);
1654 :
1655 0 : if (q == NULL) {
1656 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1657 : "Lua code block missing the closing "
1658 : "long bracket \"%*s\"",
1659 0 : b->pos + ovec[1] - p, p);
1660 0 : return NGX_ERROR;
1661 : }
1662 :
1663 : /* restore the original opening long bracket */
1664 :
1665 0 : p[0] = '[';
1666 0 : b->pos[ovec[1] - 1] = '[';
1667 :
1668 0 : ovec[1] = q - b->pos + b->pos + ovec[1] - p;
1669 :
1670 : dd("found long bracket token: \"%.*s\"",
1671 : (int) (ovec[1] - ovec[0]), b->pos + ovec[0]);
1672 : }
1673 :
1674 358 : for (i = 0; i < ovec[1]; i++) {
1675 353 : ch = b->pos[i];
1676 353 : if (ch == LF) {
1677 10 : cf->conf_file->line++;
1678 : }
1679 : }
1680 :
1681 5 : b->pos += ovec[1];
1682 5 : ctx->token_len = ovec[1] - ovec[0];
1683 :
1684 5 : break;
1685 : }
1686 :
1687 5 : word = ngx_array_push(cf->args);
1688 5 : if (word == NULL) {
1689 0 : return NGX_ERROR;
1690 : }
1691 :
1692 5 : word->data = ngx_pnalloc(cf->temp_pool, b->pos - start);
1693 5 : if (word->data == NULL) {
1694 0 : return NGX_ERROR;
1695 : }
1696 :
1697 5 : len = b->pos - start;
1698 5 : ngx_memcpy(word->data, start, len);
1699 5 : word->len = len;
1700 :
1701 5 : return rc;
1702 : }
1703 :
1704 :
1705 : char *
1706 0 : ngx_http_lua_capture_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
1707 : void *conf)
1708 : {
1709 : #ifndef HAVE_INTERCEPT_ERROR_LOG_PATCH
1710 : return "not found: missing the capture error log patch for nginx";
1711 : #else
1712 : ngx_str_t *value;
1713 : ssize_t size;
1714 : u_char *data;
1715 : ngx_cycle_t *cycle;
1716 0 : ngx_http_lua_main_conf_t *lmcf = conf;
1717 : ngx_http_lua_log_ringbuf_t *ringbuf;
1718 :
1719 0 : value = cf->args->elts;
1720 0 : cycle = cf->cycle;
1721 :
1722 0 : if (lmcf->requires_capture_log) {
1723 0 : return "is duplicate";
1724 : }
1725 :
1726 0 : if (value[1].len == 0) {
1727 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1728 : "invalid capture error log size \"%V\"",
1729 : &value[1]);
1730 0 : return NGX_CONF_ERROR;
1731 : }
1732 :
1733 0 : size = ngx_parse_size(&value[1]);
1734 :
1735 0 : if (size < NGX_MAX_ERROR_STR) {
1736 0 : ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1737 : "invalid capture error log size \"%V\", "
1738 : "minimum size is %d", &value[1],
1739 : NGX_MAX_ERROR_STR);
1740 0 : return NGX_CONF_ERROR;
1741 : }
1742 :
1743 0 : if (cycle->intercept_error_log_handler) {
1744 0 : return "capture error log handler has been hooked";
1745 : }
1746 :
1747 0 : ringbuf = (ngx_http_lua_log_ringbuf_t *)
1748 0 : ngx_palloc(cf->pool, sizeof(ngx_http_lua_log_ringbuf_t));
1749 0 : if (ringbuf == NULL) {
1750 0 : return NGX_CONF_ERROR;
1751 : }
1752 :
1753 0 : data = ngx_palloc(cf->pool, size);
1754 0 : if (data == NULL) {
1755 0 : return NGX_CONF_ERROR;
1756 : }
1757 :
1758 0 : ngx_http_lua_log_ringbuf_init(ringbuf, data, size);
1759 :
1760 0 : lmcf->requires_capture_log = 1;
1761 0 : cycle->intercept_error_log_handler = (ngx_log_intercept_pt)
1762 : ngx_http_lua_capture_log_handler;
1763 0 : cycle->intercept_error_log_data = ringbuf;
1764 :
1765 0 : return NGX_CONF_OK;
1766 : #endif
1767 : }
1768 :
1769 :
1770 : /*
1771 : * ngx_http_lua_strlstrn() is intended to search for static substring
1772 : * with known length in string until the argument last. The argument n
1773 : * must be length of the second substring - 1.
1774 : */
1775 :
1776 : static u_char *
1777 0 : ngx_http_lua_strlstrn(u_char *s1, u_char *last, u_char *s2, size_t n)
1778 : {
1779 : ngx_uint_t c1, c2;
1780 :
1781 0 : c2 = (ngx_uint_t) *s2++;
1782 0 : last -= n;
1783 :
1784 : do {
1785 : do {
1786 0 : if (s1 >= last) {
1787 0 : return NULL;
1788 : }
1789 :
1790 0 : c1 = (ngx_uint_t) *s1++;
1791 :
1792 : dd("testing char '%c' vs '%c'", (int) c1, (int) c2);
1793 :
1794 0 : } while (c1 != c2);
1795 :
1796 : dd("testing against pattern \"%.*s\"", (int) n, s2);
1797 :
1798 0 : } while (ngx_strncmp(s1, s2, n) != 0);
1799 :
1800 0 : return --s1;
1801 : }
1802 :
1803 :
1804 : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */
|