Mercurial > hg > nginx-vendor-0-7
comparison src/http/modules/ngx_http_ssi_filter.c @ 48:6cfc63e68377 NGINX_0_1_24
nginx 0.1.24
*) Feature: the ngx_http_ssi_filter_module supports the QUERY_STRING
and DOCUMENT_URI variables.
*) Bugfix: the ngx_http_autoindex_module may some times return the 404
response for existent directory, if this directory was used in
"alias" directive.
*) Bugfix: the ngx_http_ssi_filter_module ran incorrectly for large
responses.
*) Bugfix: the lack of the "Referer" header line was always accounted
as valid referrer.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Fri, 04 Mar 2005 00:00:00 +0300 |
parents | 9f3205d496a0 |
children |
comparison
equal
deleted
inserted
replaced
47:4ae32548452c | 48:6cfc63e68377 |
---|---|
39 ngx_table_elt_t params_array[NGX_HTTP_SSI_PARAMS_N]; | 39 ngx_table_elt_t params_array[NGX_HTTP_SSI_PARAMS_N]; |
40 | 40 |
41 ngx_chain_t *in; | 41 ngx_chain_t *in; |
42 ngx_chain_t *out; | 42 ngx_chain_t *out; |
43 ngx_chain_t **last_out; | 43 ngx_chain_t **last_out; |
44 ngx_chain_t *busy; | |
45 ngx_chain_t *free; | |
44 | 46 |
45 ngx_uint_t state; | 47 ngx_uint_t state; |
46 ngx_uint_t saved_state; | 48 ngx_uint_t saved_state; |
47 size_t saved; | 49 size_t saved; |
48 size_t looked; | 50 size_t looked; |
156 NGX_MODULE, | 158 NGX_MODULE, |
157 &ngx_http_ssi_filter_module_ctx, /* module context */ | 159 &ngx_http_ssi_filter_module_ctx, /* module context */ |
158 ngx_http_ssi_filter_commands, /* module directives */ | 160 ngx_http_ssi_filter_commands, /* module directives */ |
159 NGX_HTTP_MODULE, /* module type */ | 161 NGX_HTTP_MODULE, /* module type */ |
160 ngx_http_ssi_filter_init, /* init module */ | 162 ngx_http_ssi_filter_init, /* init module */ |
161 NULL /* init child */ | 163 NULL /* init process */ |
162 }; | 164 }; |
163 | 165 |
164 | 166 |
165 static ngx_int_t (*ngx_http_next_header_filter) (ngx_http_request_t *r); | 167 static ngx_int_t (*ngx_http_next_header_filter) (ngx_http_request_t *r); |
166 static ngx_int_t (*ngx_http_next_body_filter) (ngx_http_request_t *r, | 168 static ngx_int_t (*ngx_http_next_body_filter) (ngx_http_request_t *r, |
210 { | 212 { |
211 return ngx_http_next_header_filter(r); | 213 return ngx_http_next_header_filter(r); |
212 } | 214 } |
213 | 215 |
214 | 216 |
215 if (!(ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ssi_ctx_t)))) { | 217 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ssi_ctx_t)); |
218 if (ctx == NULL) { | |
216 return NGX_ERROR; | 219 return NGX_ERROR; |
217 } | 220 } |
218 | 221 |
219 ngx_http_set_ctx(r, ctx, ngx_http_ssi_filter_module); | 222 ngx_http_set_ctx(r, ctx, ngx_http_ssi_filter_module); |
220 | 223 |
260 ngx_http_ssi_command_t *cmd; | 263 ngx_http_ssi_command_t *cmd; |
261 ngx_str_t *params[NGX_HTTP_SSI_MAX_PARAMS]; | 264 ngx_str_t *params[NGX_HTTP_SSI_MAX_PARAMS]; |
262 | 265 |
263 ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module); | 266 ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module); |
264 | 267 |
265 if (ctx == NULL || (in == NULL && ctx->in == NULL)) { | 268 if (ctx == NULL || (in == NULL && ctx->in == NULL && ctx->busy == NULL)) { |
266 return ngx_http_next_body_filter(r, in); | 269 return ngx_http_next_body_filter(r, in); |
267 } | 270 } |
268 | 271 |
269 /* add the incoming chain to the chain ctx->in */ | 272 /* add the incoming chain to the chain ctx->in */ |
270 | 273 |
277 conf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); | 280 conf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); |
278 | 281 |
279 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 282 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
280 "http ssi filter"); | 283 "http ssi filter"); |
281 | 284 |
282 b = NULL; | 285 while (ctx->in || ctx->buf) { |
283 | 286 |
284 while (ctx->in) { | 287 if (ctx->buf == NULL ){ |
285 | 288 ctx->buf = ctx->in->buf; |
286 ctx->buf = ctx->in->buf; | 289 ctx->in = ctx->in->next; |
287 ctx->in = ctx->in->next; | 290 ctx->pos = ctx->buf->pos; |
288 ctx->pos = ctx->buf->pos; | 291 } |
289 | 292 |
290 if (ctx->state == ssi_start_state) { | 293 if (ctx->state == ssi_start_state) { |
291 ctx->copy_start = ctx->pos; | 294 ctx->copy_start = ctx->pos; |
292 ctx->copy_end = ctx->pos; | 295 ctx->copy_end = ctx->pos; |
293 } | 296 } |
294 | 297 |
298 b = NULL; | |
299 | |
295 while (ctx->pos < ctx->buf->last) { | 300 while (ctx->pos < ctx->buf->last) { |
296 | 301 |
297 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 302 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
298 "saved: %d state: %d", ctx->saved, ctx->state); | 303 "saved: %d state: %d", ctx->saved, ctx->state); |
299 | 304 |
311 | 316 |
312 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 317 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
313 "saved: %d", ctx->saved); | 318 "saved: %d", ctx->saved); |
314 | 319 |
315 if (ctx->saved) { | 320 if (ctx->saved) { |
316 if (!(b = ngx_calloc_buf(r->pool))) { | 321 |
317 return NGX_ERROR; | 322 if (ctx->free) { |
323 cl = ctx->free; | |
324 ctx->free = ctx->free->next; | |
325 b = cl->buf; | |
326 ngx_memzero(b, sizeof(ngx_buf_t)); | |
327 | |
328 } else { | |
329 b = ngx_calloc_buf(r->pool); | |
330 if (b == NULL) { | |
331 return NGX_ERROR; | |
332 } | |
333 | |
334 cl = ngx_alloc_chain_link(r->pool); | |
335 if (cl == NULL) { | |
336 return NGX_ERROR; | |
337 } | |
338 | |
339 cl->buf = b; | |
318 } | 340 } |
319 | 341 |
320 b->memory = 1; | 342 b->memory = 1; |
321 b->pos = ngx_http_ssi_string; | 343 b->pos = ngx_http_ssi_string; |
322 b->last = ngx_http_ssi_string + ctx->saved; | 344 b->last = ngx_http_ssi_string + ctx->saved; |
323 | 345 |
324 if (!(cl = ngx_alloc_chain_link(r->pool))) { | 346 *ctx->last_out = cl; |
347 ctx->last_out = &cl->next; | |
348 | |
349 ctx->saved = 0; | |
350 } | |
351 | |
352 if (ctx->free) { | |
353 cl = ctx->free; | |
354 ctx->free = ctx->free->next; | |
355 b = cl->buf; | |
356 | |
357 } else { | |
358 b = ngx_alloc_buf(r->pool); | |
359 if (b == NULL) { | |
325 return NGX_ERROR; | 360 return NGX_ERROR; |
326 } | 361 } |
327 | 362 |
363 cl = ngx_alloc_chain_link(r->pool); | |
364 if (cl == NULL) { | |
365 return NGX_ERROR; | |
366 } | |
367 | |
328 cl->buf = b; | 368 cl->buf = b; |
329 *ctx->last_out = cl; | |
330 ctx->last_out = &cl->next; | |
331 | |
332 ctx->saved = 0; | |
333 } | |
334 | |
335 if (!(b = ngx_calloc_buf(r->pool))) { | |
336 return NGX_ERROR; | |
337 } | 369 } |
338 | 370 |
339 ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t)); | 371 ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t)); |
340 | 372 |
341 b->last_buf = 0; | 373 b->last_buf = 0; |
374 b->recycled = 0; | |
342 b->pos = ctx->copy_start; | 375 b->pos = ctx->copy_start; |
343 b->last = ctx->copy_end; | 376 b->last = ctx->copy_end; |
344 | 377 |
345 if (b->in_file) { | 378 if (b->in_file) { |
346 | 379 |
351 } else { | 384 } else { |
352 b->in_file = 0; | 385 b->in_file = 0; |
353 } | 386 } |
354 } | 387 } |
355 | 388 |
356 if (!(cl = ngx_alloc_chain_link(r->pool))) { | |
357 return NGX_ERROR; | |
358 } | |
359 | |
360 cl->buf = b; | |
361 cl->next = NULL; | 389 cl->next = NULL; |
362 *ctx->last_out = cl; | 390 *ctx->last_out = cl; |
363 ctx->last_out = &cl->next; | 391 ctx->last_out = &cl->next; |
364 } | 392 } |
365 | 393 |
459 } | 487 } |
460 | 488 |
461 | 489 |
462 /* rc == NGX_HTTP_SSI_ERROR */ | 490 /* rc == NGX_HTTP_SSI_ERROR */ |
463 | 491 |
464 ssi_error: | 492 ssi_error: |
465 | 493 |
466 if (conf->silent_errors) { | 494 if (conf->silent_errors) { |
467 continue; | 495 continue; |
468 } | 496 } |
469 | 497 |
470 if (!(b = ngx_calloc_buf(r->pool))) { | 498 if (ctx->free) { |
471 return NGX_ERROR; | 499 cl = ctx->free; |
500 ctx->free = ctx->free->next; | |
501 b = cl->buf; | |
502 ngx_memzero(b, sizeof(ngx_buf_t)); | |
503 | |
504 } else { | |
505 b = ngx_calloc_buf(r->pool); | |
506 if (b == NULL) { | |
507 return NGX_ERROR; | |
508 } | |
509 | |
510 cl = ngx_alloc_chain_link(r->pool); | |
511 if (cl == NULL) { | |
512 return NGX_ERROR; | |
513 } | |
514 | |
515 cl->buf = b; | |
472 } | 516 } |
473 | 517 |
474 b->memory = 1; | 518 b->memory = 1; |
475 b->pos = ngx_http_ssi_error_string; | 519 b->pos = ngx_http_ssi_error_string; |
476 b->last = ngx_http_ssi_error_string | 520 b->last = ngx_http_ssi_error_string |
477 + sizeof(ngx_http_ssi_error_string) - 1; | 521 + sizeof(ngx_http_ssi_error_string) - 1; |
478 | 522 |
479 if (!(cl = ngx_alloc_chain_link(r->pool))) { | |
480 return NGX_ERROR; | |
481 } | |
482 | |
483 cl->buf = b; | |
484 cl->next = NULL; | 523 cl->next = NULL; |
485 *ctx->last_out = cl; | 524 *ctx->last_out = cl; |
486 ctx->last_out = &cl->next; | 525 ctx->last_out = &cl->next; |
487 | 526 |
488 continue; | 527 continue; |
489 } | 528 } |
490 | 529 |
491 ctx->buf->pos = ctx->buf->last; | 530 if (ctx->buf->recycled || ctx->buf->last_buf) { |
492 | 531 if (b == NULL) { |
493 if (b && ctx->buf->last_buf) { | 532 |
494 b->last_buf = 1; | 533 if (ctx->free) { |
534 cl = ctx->free; | |
535 ctx->free = ctx->free->next; | |
536 b = cl->buf; | |
537 ngx_memzero(b, sizeof(ngx_buf_t)); | |
538 | |
539 } else { | |
540 b = ngx_calloc_buf(r->pool); | |
541 if (b == NULL) { | |
542 return NGX_ERROR; | |
543 } | |
544 | |
545 cl = ngx_alloc_chain_link(r->pool); | |
546 if (cl == NULL) { | |
547 return NGX_ERROR; | |
548 } | |
549 | |
550 cl->buf = b; | |
551 } | |
552 | |
553 cl->next = NULL; | |
554 *ctx->last_out = cl; | |
555 ctx->last_out = &cl->next; | |
556 } | |
557 | |
558 b->last_buf = ctx->buf->last_buf; | |
559 b->flush = ctx->buf->recycled; | |
560 b->shadow = ctx->buf; | |
495 } | 561 } |
496 | 562 |
563 ctx->buf = NULL; | |
564 | |
497 ctx->saved = ctx->looked; | 565 ctx->saved = ctx->looked; |
498 } | 566 } |
499 | 567 |
500 if (ctx->out == NULL) { | 568 if (ctx->out == NULL && ctx->busy == NULL) { |
501 return NGX_OK; | 569 return NGX_OK; |
502 } | 570 } |
503 | 571 |
504 rc = ngx_http_next_body_filter(r, ctx->out); | 572 rc = ngx_http_next_body_filter(r, ctx->out); |
573 | |
574 if (ctx->busy == NULL) { | |
575 ctx->busy = ctx->out; | |
576 | |
577 } else { | |
578 for (cl = ctx->busy; cl->next; cl = cl->next) { /* void */ } | |
579 cl->next = ctx->out; | |
580 } | |
505 | 581 |
506 ctx->out = NULL; | 582 ctx->out = NULL; |
507 ctx->last_out = &ctx->out; | 583 ctx->last_out = &ctx->out; |
584 | |
585 while (ctx->busy) { | |
586 | |
587 b = ctx->busy->buf; | |
588 | |
589 if (ngx_buf_size(b) != 0) { | |
590 break; | |
591 } | |
592 | |
593 #if (NGX_HAVE_WRITE_ZEROCOPY) | |
594 if (b->zerocopy_busy) { | |
595 break; | |
596 } | |
597 #endif | |
598 | |
599 if (b->shadow) { | |
600 b->shadow->pos = b->shadow->last; | |
601 } | |
602 | |
603 cl = ctx->busy; | |
604 ctx->busy = cl->next; | |
605 cl->next = ctx->free; | |
606 ctx->free = cl; | |
607 } | |
508 | 608 |
509 return rc; | 609 return rc; |
510 } | 610 } |
511 | 611 |
512 | 612 |
528 | 628 |
529 if (state == ssi_start_state) { | 629 if (state == ssi_start_state) { |
530 | 630 |
531 /* the tight loop */ | 631 /* the tight loop */ |
532 | 632 |
533 for ( /* void */ ; p < last; ch = *(++p)) { | 633 for ( ;; ) { |
534 if (ch != '<') { | 634 if (ch == '<') { |
535 continue; | 635 copy_end = p; |
536 } | 636 looked = 1; |
537 | 637 state = ssi_tag_state; |
538 copy_end = p; | 638 |
539 looked = 1; | 639 goto tag_started; |
540 state = ssi_tag_state; | 640 } |
541 | 641 |
542 goto tag_started; | 642 if (++p == last) { |
643 break; | |
644 } | |
645 | |
646 ch = *p; | |
543 } | 647 } |
544 | 648 |
545 ctx->pos = p; | 649 ctx->pos = p; |
546 ctx->looked = looked; | 650 ctx->looked = looked; |
547 ctx->copy_end = p; | 651 ctx->copy_end = p; |
550 ctx->copy_start = ctx->buf->pos; | 654 ctx->copy_start = ctx->buf->pos; |
551 } | 655 } |
552 | 656 |
553 return NGX_AGAIN; | 657 return NGX_AGAIN; |
554 | 658 |
555 tag_started: | 659 tag_started: |
660 | |
556 continue; | 661 continue; |
557 } | 662 } |
558 | 663 |
559 switch (state) { | 664 switch (state) { |
560 | 665 |
713 case '-': | 818 case '-': |
714 state = ssi_comment_end0_state; | 819 state = ssi_comment_end0_state; |
715 break; | 820 break; |
716 | 821 |
717 default: | 822 default: |
718 if (!(ctx->param = ngx_array_push(&ctx->params))) { | 823 ctx->param = ngx_array_push(&ctx->params); |
824 if (ctx->param == NULL) { | |
719 return NGX_ERROR; | 825 return NGX_ERROR; |
720 } | 826 } |
721 | 827 |
722 ctx->param->key.len = 1; | 828 ctx->param->key.len = 1; |
723 ctx->param->key.data = ngx_palloc(r->pool, | 829 ctx->param->key.data = ngx_palloc(r->pool, |
1039 | 1145 |
1040 static ngx_int_t | 1146 static ngx_int_t |
1041 ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, | 1147 ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, |
1042 ngx_str_t **params) | 1148 ngx_str_t **params) |
1043 { | 1149 { |
1044 u_char ch; | 1150 ngx_buf_t *b; |
1045 ngx_uint_t i, n; | 1151 ngx_str_t *var, *value; |
1046 ngx_buf_t *b; | 1152 ngx_chain_t *cl; |
1047 ngx_str_t *var, *value; | 1153 ngx_http_variable_value_t *v; |
1048 ngx_chain_t *cl; | |
1049 ngx_list_part_t *part; | |
1050 ngx_table_elt_t *header; | |
1051 | 1154 |
1052 var = params[NGX_HTTP_SSI_ECHO_VAR]; | 1155 var = params[NGX_HTTP_SSI_ECHO_VAR]; |
1053 value = NULL; | 1156 value = NULL; |
1054 | 1157 |
1055 if (var->len > 5 && ngx_strncmp(var->data, "HTTP_", 5) == 0) { | 1158 v = ngx_http_get_variable(r, var); |
1056 | 1159 |
1057 part = &r->headers_in.headers.part; | 1160 if (v == NULL) { |
1058 header = part->elts; | 1161 return NGX_HTTP_SSI_ERROR; |
1059 | 1162 } |
1060 for (i = 0; /* void */ ; i++) { | 1163 |
1061 | 1164 if (v == NGX_HTTP_VARIABLE_NOT_FOUND) { |
1062 if (i >= part->nelts) { | 1165 value = params[NGX_HTTP_SSI_ECHO_DEFAULT]; |
1063 if (part->next == NULL) { | 1166 |
1064 break; | 1167 if (value == NULL) { |
1065 } | 1168 value = &ngx_http_ssi_none; |
1066 | 1169 |
1067 part = part->next; | 1170 } else if (value->len == 0) { |
1068 header = part->elts; | 1171 return NGX_OK; |
1069 i = 0; | |
1070 } | |
1071 | |
1072 for (n = 0; n + 5 < var->len && n < header[i].key.len; n++) | |
1073 { | |
1074 ch = header[i].key.data[n]; | |
1075 | |
1076 if (ch >= 'a' && ch <= 'z') { | |
1077 ch &= ~0x20; | |
1078 | |
1079 } else if (ch == '-') { | |
1080 ch = '_'; | |
1081 } | |
1082 | |
1083 if (var->data[n + 5] != ch) { | |
1084 break; | |
1085 } | |
1086 } | |
1087 | |
1088 if (n + 5 == var->len) { | |
1089 value = &header[i].value; | |
1090 break; | |
1091 } | |
1092 } | 1172 } |
1093 | 1173 |
1094 } else if (var->len == sizeof("REMOTE_ADDR") - 1 | 1174 } else { |
1095 && ngx_strncmp(var->data, "REMOTE_ADDR", | 1175 value = &v->text; |
1096 sizeof("REMOTE_ADDR") - 1) == 0) | 1176 |
1097 { | 1177 if (value->len == 0) { |
1098 value = &r->connection->addr_text; | 1178 return NGX_OK; |
1099 } | 1179 } |
1100 | 1180 } |
1101 | 1181 |
1102 if (value == NULL) { | 1182 b = ngx_calloc_buf(r->pool); |
1103 value = params[NGX_HTTP_SSI_ECHO_DEFAULT]; | 1183 if (b == NULL) { |
1104 } | |
1105 | |
1106 if (value == NULL) { | |
1107 value = &ngx_http_ssi_none; | |
1108 | |
1109 } else if (value->len == 0) { | |
1110 return NGX_OK; | |
1111 } | |
1112 | |
1113 if (!(b = ngx_calloc_buf(r->pool))) { | |
1114 return NGX_HTTP_SSI_ERROR; | 1184 return NGX_HTTP_SSI_ERROR; |
1115 } | 1185 } |
1116 | 1186 |
1117 if (!(cl = ngx_alloc_chain_link(r->pool))) { | 1187 cl = ngx_alloc_chain_link(r->pool); |
1188 if (cl == NULL) { | |
1118 return NGX_HTTP_SSI_ERROR; | 1189 return NGX_HTTP_SSI_ERROR; |
1119 } | 1190 } |
1120 | 1191 |
1121 b->memory = 1; | 1192 b->memory = 1; |
1122 b->pos = value->data; | 1193 b->pos = value->data; |
1134 static void * | 1205 static void * |
1135 ngx_http_ssi_create_conf(ngx_conf_t *cf) | 1206 ngx_http_ssi_create_conf(ngx_conf_t *cf) |
1136 { | 1207 { |
1137 ngx_http_ssi_conf_t *conf; | 1208 ngx_http_ssi_conf_t *conf; |
1138 | 1209 |
1139 if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_conf_t)))) { | 1210 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_conf_t)); |
1211 if (conf == NULL) { | |
1140 return NGX_CONF_ERROR; | 1212 return NGX_CONF_ERROR; |
1141 } | 1213 } |
1142 | 1214 |
1143 conf->enable = NGX_CONF_UNSET; | 1215 conf->enable = NGX_CONF_UNSET; |
1144 conf->silent_errors = NGX_CONF_UNSET; | 1216 conf->silent_errors = NGX_CONF_UNSET; |