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;