comparison src/http/modules/ngx_http_ssi_filter.c @ 241:3bfa496bc22e

nginx-0.0.1-2004-01-27-10:08:39 import
author Igor Sysoev <igor@sysoev.ru>
date Tue, 27 Jan 2004 07:08:39 +0000
parents 725129fdd524
children 5d4f49dc8de5
comparison
equal deleted inserted replaced
240:725129fdd524 241:3bfa496bc22e
14 #define NGX_HTTP_SSI_LONG_VALUE 5 14 #define NGX_HTTP_SSI_LONG_VALUE 5
15 15
16 16
17 typedef struct { 17 typedef struct {
18 int enable; 18 int enable;
19 ssize_t value_len;
19 } ngx_http_ssi_conf_t; 20 } ngx_http_ssi_conf_t;
20 21
21 22
22 typedef struct { 23 typedef struct {
23 ngx_hunk_t *buf; 24 ngx_hunk_t *buf;
24 25
25 char *start; 26 char *start;
26 char *last; 27 char *last;
27 char *pos; 28 char *pos;
28 29
29 ngx_table_elt_t *param;
30 ngx_str_t command; 30 ngx_str_t command;
31 ngx_array_t params; 31 ngx_array_t params;
32 int state; 32 ngx_table_elt_t *param;
33 33
34 ngx_chain_t *in; 34 ngx_chain_t *in;
35 ngx_chain_t *current;
36 ngx_chain_t *out; 35 ngx_chain_t *out;
37 ngx_chain_t **last_out; 36 ngx_chain_t **last_out;
38 ngx_chain_t *busy; 37 ngx_chain_t *busy;
39 38
40 size_t prev; 39 int state;
41 40 size_t saved;
42 u_int value_len; 41 ngx_int_t err;
43 } ngx_http_ssi_ctx_t; 42 } ngx_http_ssi_ctx_t;
43
44
45 typedef enum {
46 ssi_start_state = 0,
47 ssi_tag_state,
48 ssi_comment0_state,
49 ssi_comment1_state,
50 ssi_sharp_state,
51 ssi_precommand_state,
52 ssi_command_state,
53 ssi_preparam_state,
54 ssi_param_state,
55 ssi_preequal_state,
56 ssi_prevalue_state,
57 ssi_double_quoted_value_state,
58 ssi_double_quoted_value_quote_state,
59 ssi_quoted_value_state,
60 ssi_quoted_value_quote_state,
61 ssi_error_state,
62 ssi_comment_end0_state,
63 ssi_comment_end1_state
64 } ngx_http_ssi_state_e;
44 65
45 66
46 static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r, 67 static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
47 ngx_http_ssi_ctx_t *ctx); 68 ngx_http_ssi_ctx_t *ctx);
48 static void *ngx_http_ssi_create_conf(ngx_conf_t *cf); 69 static void *ngx_http_ssi_create_conf(ngx_conf_t *cf);
92 static int (*ngx_http_next_header_filter) (ngx_http_request_t *r); 113 static int (*ngx_http_next_header_filter) (ngx_http_request_t *r);
93 static int (*ngx_http_next_body_filter) (ngx_http_request_t *r, ngx_chain_t *in); 114 static int (*ngx_http_next_body_filter) (ngx_http_request_t *r, ngx_chain_t *in);
94 115
95 116
96 117
97 static char comment_string[] = "<!--"; 118 static char ssi_string[] = "<!--#";
98 static char error_string[] = "[an error occurred while processing " 119 static char error_string[] = "[an error occurred while processing "
99 "the directive]"; 120 "the directive]";
100 121
101 122
102 static int ngx_http_ssi_header_filter(ngx_http_request_t *r) 123 static int ngx_http_ssi_header_filter(ngx_http_request_t *r)
112 133
113 ngx_http_create_ctx(r, ctx, ngx_http_ssi_filter_module, 134 ngx_http_create_ctx(r, ctx, ngx_http_ssi_filter_module,
114 sizeof(ngx_http_ssi_ctx_t), NGX_ERROR); 135 sizeof(ngx_http_ssi_ctx_t), NGX_ERROR);
115 136
116 ctx->last_out = &ctx->out; 137 ctx->last_out = &ctx->out;
117 /* STUB: conf */ ctx->value_len = 200;
118 138
119 r->headers_out.content_length_n = -1; 139 r->headers_out.content_length_n = -1;
120 if (r->headers_out.content_length) { 140 if (r->headers_out.content_length) {
121 r->headers_out.content_length->key.len = 0; 141 r->headers_out.content_length->key.len = 0;
122 r->headers_out.content_length = NULL; 142 r->headers_out.content_length = NULL;
134 } 154 }
135 155
136 156
137 static int ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in) 157 static int ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
138 { 158 {
159 size_t len;
139 ngx_int_t rc; 160 ngx_int_t rc;
140 ngx_hunk_t *hunk; 161 ngx_hunk_t *hunk;
141 ngx_chain_t *cl, *tl; 162 ngx_chain_t *cl, *tl;
142 ngx_http_ssi_ctx_t *ctx; 163 ngx_http_ssi_ctx_t *ctx;
143 164
151 172
152 if (in) { 173 if (in) {
153 if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) { 174 if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) {
154 return NGX_ERROR; 175 return NGX_ERROR;
155 } 176 }
156 177 }
157 if (ctx->current == NULL) { 178
158 ctx->current = ctx->in; 179 while (ctx->in) {
159 }
160 }
161
162 while (ctx->current) {
163 if (ctx->buf == NULL) { 180 if (ctx->buf == NULL) {
164 ctx->buf = ctx->current->hunk; 181 ctx->buf = ctx->in->hunk;
165 ctx->current = ctx->current->next; 182 ctx->in = ctx->in->next;
166 183
167 ctx->start = ctx->buf->pos; 184 ctx->start = ctx->buf->pos;
168 ctx->pos = ctx->buf->pos; 185 ctx->pos = ctx->buf->pos;
169 ctx->last = ctx->buf->pos; 186 ctx->last = ctx->buf->pos;
187
188 if (ctx->saved) {
189 len = ctx->buf->last - ctx->buf->pos;
190 if (len > 5 - ctx->saved) {
191 len = 5 - ctx->saved;
192 }
193
194 if (ngx_strncmp(ctx->buf->pos, &ssi_string[ctx->saved], len)
195 == 0)
196 {
197 if (len < 5 - ctx->saved) {
198 ctx->buf = NULL;
199 continue;
200
201 } else {
202 ctx->saved = 0;
203 ctx->pos += len;
204 ctx->state = ssi_precommand_state;
205 }
206 }
207 }
170 } 208 }
171 209
172 while (ctx->pos < ctx->buf->last) { 210 while (ctx->pos < ctx->buf->last) {
211
212 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
213 "saved: %d", ctx->saved);
214
173 rc = ngx_http_ssi_parse(r, ctx); 215 rc = ngx_http_ssi_parse(r, ctx);
174 216
175 if (rc == NGX_ERROR) { 217 if (rc == NGX_ERROR) {
176 return rc; 218 return rc;
177 219
178 } else if (rc == NGX_HTTP_SSI_COPY) { 220 } else if (rc == NGX_HTTP_SSI_COPY) {
179 if (ctx->prev) { 221
222 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
223 "saved: %d copy: %d",
224 ctx->saved, ctx->last - ctx->start);
225
226 if (ctx->saved) {
180 227
181 if (!(hunk = ngx_calloc_hunk(r->pool))) { 228 if (!(hunk = ngx_calloc_hunk(r->pool))) {
182 return NGX_ERROR; 229 return NGX_ERROR;
183 } 230 }
184 231
185 hunk->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP; 232 hunk->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
186 hunk->pos = comment_string; 233 hunk->pos = ssi_string;
187 hunk->last = comment_string + ctx->prev; 234 hunk->last = ssi_string + ctx->saved;
188 235
189 ngx_alloc_link_and_set_hunk(cl, hunk, r->pool, NGX_ERROR); 236 ngx_alloc_link_and_set_hunk(cl, hunk, r->pool, NGX_ERROR);
190 237
191 *ctx->last_out = cl; 238 *ctx->last_out = cl;
192 ctx->last_out = &cl->next; 239 ctx->last_out = &cl->next;
193 240
194 ctx->prev = 0; 241 ctx->saved = 0;
195 } 242 }
196 243
197 if (!(hunk = ngx_calloc_hunk(r->pool))) { 244 if (!(hunk = ngx_calloc_hunk(r->pool))) {
198 return NGX_ERROR; 245 return NGX_ERROR;
199 } 246 }
207 254
208 *ctx->last_out = cl; 255 *ctx->last_out = cl;
209 ctx->last_out = &cl->next; 256 ctx->last_out = &cl->next;
210 257
211 if (ctx->pos == ctx->buf->last) { 258 if (ctx->pos == ctx->buf->last) {
212 ctx->prev = ctx->buf->last - ctx->last; 259 ctx->saved = ctx->pos - ctx->last;
213 } 260 }
214 261
215 continue; 262 continue;
216 263
217 #if 0 264 #if 0
341 388
342 389
343 static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r, 390 static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
344 ngx_http_ssi_ctx_t *ctx) 391 ngx_http_ssi_ctx_t *ctx)
345 { 392 {
346 char *p, *last, *end, ch; 393 char *p, *last, *end, ch;
347 394 ngx_http_ssi_conf_t *conf;
348 enum { 395 ngx_http_ssi_state_e state;
349 ssi_start_state = 0, 396
350 ssi_tag_state, 397 conf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module);
351 ssi_comment0_state,
352 ssi_comment1_state,
353 ssi_sharp_state,
354 ssi_precommand_state,
355 ssi_command_state,
356 ssi_preparam_state,
357 ssi_param_state,
358 ssi_preequal_state,
359 ssi_prevalue_state,
360 ssi_double_quoted_value_state,
361 ssi_double_quoted_value_quote_state,
362 ssi_quoted_value_state,
363 ssi_quoted_value_quote_state,
364 ssi_comment_end0_state,
365 ssi_comment_end1_state
366 } state;
367
368 398
369 state = ctx->state; 399 state = ctx->state;
370 last = ctx->last;
371 p = ctx->pos; 400 p = ctx->pos;
372 end = ctx->buf->last; 401 end = ctx->buf->last;
402 last = NULL;
373 403
374 while (p < end) { 404 while (p < end) {
375 ch = *p++; 405 ch = *p++;
376 406
377 switch (state) { 407 switch (state) {
378 408
379 case ssi_start_state: 409 case ssi_start_state:
380 410
381 last = NULL;
382
383 /* a tight loop */ 411 /* a tight loop */
412
384 for ( ;; ) { 413 for ( ;; ) {
385 414
386 if (ch == '<') { 415 if (ch == '<') {
416 last = p - 1;
387 state = ssi_tag_state; 417 state = ssi_tag_state;
388 last = p - 1;
389 break; 418 break;
390 } 419 }
391 420
392 if (p == end) { 421 if (p == end) {
393 ctx->state = ssi_start_state;
394 ctx->last = p; 422 ctx->last = p;
395 ctx->pos = p; 423 ctx->pos = p;
424 ctx->state = ssi_start_state;
396 425
397 return NGX_HTTP_SSI_COPY; 426 return NGX_HTTP_SSI_COPY;
398 } 427 }
399 428
400 ch = *p++; 429 ch = *p++;
456 break; 485 break;
457 486
458 case ssi_sharp_state: 487 case ssi_sharp_state:
459 switch (ch) { 488 switch (ch) {
460 case '#': 489 case '#':
461 ctx->state = ssi_precommand_state;
462 ctx->last = last; 490 ctx->last = last;
463 ctx->pos = p; 491 ctx->pos = p;
492 ctx->state = ssi_precommand_state;
464 493
465 return NGX_HTTP_SSI_COPY; 494 return NGX_HTTP_SSI_COPY;
466 495
467 case '<': 496 case '<':
468 last = p - 1; 497 last = p - 1;
491 return NGX_ERROR; 520 return NGX_ERROR;
492 } 521 }
493 522
494 ctx->command.data[0] = ch; 523 ctx->command.data[0] = ch;
495 ctx->command.len = 1; 524 ctx->command.len = 1;
525 ctx->err = NGX_OK;
496 state = ssi_command_state; 526 state = ssi_command_state;
497 break; 527 break;
498 } 528 }
499 529
500 break; 530 break;
514 state = ssi_comment_end0_state; 544 state = ssi_comment_end0_state;
515 break; 545 break;
516 546
517 default: 547 default:
518 if (ctx->command.len >= NGX_HTTP_SSI_COMMAND_LEN) { 548 if (ctx->command.len >= NGX_HTTP_SSI_COMMAND_LEN) {
519 return NGX_HTTP_SSI_INVALID_COMMAND; 549 ctx->err = NGX_HTTP_SSI_INVALID_COMMAND;
550 state = ssi_error_state;
551 break;
520 } 552 }
521 553
522 ctx->command.data[ctx->command.len++] = ch; 554 ctx->command.data[ctx->command.len++] = ch;
523 } 555 }
524 556
548 } 580 }
549 ctx->param->key.data[0] = ch; 581 ctx->param->key.data[0] = ch;
550 ctx->param->key.len = 1; 582 ctx->param->key.len = 1;
551 583
552 ctx->param->value.data = 584 ctx->param->value.data =
553 ngx_palloc(r->pool, ctx->value_len + 1); 585 ngx_palloc(r->pool, conf->value_len + 1);
554 if (ctx->param->value.data == NULL) { 586 if (ctx->param->value.data == NULL) {
555 return NGX_ERROR; 587 return NGX_ERROR;
556 } 588 }
557 ctx->param->value.len = 0; 589 ctx->param->value.len = 0;
558 590
577 state = ssi_prevalue_state; 609 state = ssi_prevalue_state;
578 break; 610 break;
579 611
580 default: 612 default:
581 if (ctx->param->key.len >= NGX_HTTP_SSI_PARAM_LEN) { 613 if (ctx->param->key.len >= NGX_HTTP_SSI_PARAM_LEN) {
582 return NGX_HTTP_SSI_INVALID_PARAM; 614 ctx->err = NGX_HTTP_SSI_INVALID_PARAM;
615 state = ssi_error_state;
616 break;
583 } 617 }
584 618
585 ctx->param->key.data[ctx->param->key.len++] = ch; 619 ctx->param->key.data[ctx->param->key.len++] = ch;
586 } 620 }
587 621
598 case '=': 632 case '=':
599 state = ssi_prevalue_state; 633 state = ssi_prevalue_state;
600 break; 634 break;
601 635
602 default: 636 default:
603 return NGX_HTTP_SSI_INVALID_PARAM; 637 ctx->err = NGX_HTTP_SSI_INVALID_PARAM;
638 state = ssi_error_state;
639 break;
604 } 640 }
605 641
606 break; 642 break;
607 643
608 case ssi_prevalue_state: 644 case ssi_prevalue_state:
620 case '\'': 656 case '\'':
621 state = ssi_quoted_value_state; 657 state = ssi_quoted_value_state;
622 break; 658 break;
623 659
624 default: 660 default:
625 return NGX_HTTP_SSI_INVALID_VALUE; 661 ctx->err = NGX_HTTP_SSI_INVALID_VALUE;
662 state = ssi_error_state;
663 break;
626 } 664 }
627 665
628 break; 666 break;
629 667
630 case ssi_double_quoted_value_state: 668 case ssi_double_quoted_value_state:
636 case '"': 674 case '"':
637 state = ssi_preparam_state; 675 state = ssi_preparam_state;
638 break; 676 break;
639 677
640 default: 678 default:
641 if (ctx->param->value.len >= ctx->value_len) { 679 if ((ssize_t) ctx->param->value.len >= conf->value_len) {
642 return NGX_HTTP_SSI_LONG_VALUE; 680 ctx->err = NGX_HTTP_SSI_LONG_VALUE;
681 state = ssi_error_state;
682 break;
643 } 683 }
644 684
645 ctx->param->value.data[ctx->param->value.len++] = ch; 685 ctx->param->value.data[ctx->param->value.len++] = ch;
646 } 686 }
647 687
648 break; 688 break;
649 689
650 case ssi_double_quoted_value_quote_state: 690 case ssi_double_quoted_value_quote_state:
651 if (ctx->param->value.len >= ctx->value_len) { 691 if ((ssize_t) ctx->param->value.len >= conf->value_len) {
652 return NGX_HTTP_SSI_LONG_VALUE; 692 ctx->err = NGX_HTTP_SSI_LONG_VALUE;
693 state = ssi_error_state;
694 break;
653 } 695 }
654 696
655 ctx->param->value.data[ctx->param->value.len++] = ch; 697 ctx->param->value.data[ctx->param->value.len++] = ch;
656 698
657 state = ssi_double_quoted_value_state; 699 state = ssi_double_quoted_value_state;
666 case '\'': 708 case '\'':
667 state = ssi_preparam_state; 709 state = ssi_preparam_state;
668 break; 710 break;
669 711
670 default: 712 default:
671 if (ctx->param->value.len >= ctx->value_len) { 713 if ((ssize_t) ctx->param->value.len >= conf->value_len) {
672 return NGX_HTTP_SSI_LONG_VALUE; 714 ctx->err = NGX_HTTP_SSI_LONG_VALUE;
715 state = ssi_error_state;
716 break;
673 } 717 }
674 718
675 ctx->param->value.data[ctx->param->value.len++] = ch; 719 ctx->param->value.data[ctx->param->value.len++] = ch;
676 } 720 }
677 721
678 break; 722 break;
679 723
680 case ssi_quoted_value_quote_state: 724 case ssi_quoted_value_quote_state:
681 if (ctx->param->value.len >= ctx->value_len) { 725 if ((ssize_t) ctx->param->value.len >= conf->value_len) {
682 return NGX_HTTP_SSI_LONG_VALUE; 726 ctx->err = NGX_HTTP_SSI_LONG_VALUE;
727 state = ssi_error_state;
728 break;
683 } 729 }
684 730
685 ctx->param->value.data[ctx->param->value.len++] = ch; 731 ctx->param->value.data[ctx->param->value.len++] = ch;
686 732
687 state = ssi_quoted_value_state; 733 state = ssi_quoted_value_state;
688 break; 734 break;
689 735
690 case ssi_comment_end0_state: 736 case ssi_error_state:
691 switch (ch) { 737 switch (ch) {
692 case '-': 738 case '-':
693 state = ssi_comment_end1_state; 739 state = ssi_comment_end1_state;
694 break; 740 break;
695 741
696 default: 742 default:
697 return NGX_HTTP_SSI_INVALID_COMMAND; 743 break;
744 }
745
746 break;
747
748 case ssi_comment_end0_state:
749 switch (ch) {
750 case '-':
751 state = ssi_comment_end1_state;
752 break;
753
754 default:
755 ctx->err = NGX_HTTP_SSI_INVALID_COMMAND;
756 state = ssi_error_state;
757 break;
698 } 758 }
699 759
700 break; 760 break;
701 761
702 case ssi_comment_end1_state: 762 case ssi_comment_end1_state:
703 switch (ch) { 763 switch (ch) {
704 case '>': 764 case '>':
705 ctx->state = ssi_start_state; 765 ctx->state = ssi_start_state;
706 ctx->start = p; 766 ctx->start = p;
707 ctx->pos = p; 767 ctx->pos = p;
708 return NGX_OK; 768 return ctx->err;
709 769
710 default: 770 default:
711 return NGX_HTTP_SSI_INVALID_COMMAND; 771 ctx->err = NGX_HTTP_SSI_INVALID_COMMAND;
772 state = ssi_error_state;
773 break;
712 } 774 }
713 775
714 break; 776 break;
715 } 777 }
716 } 778 }
730 if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_conf_t)))) { 792 if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_conf_t)))) {
731 return NGX_CONF_ERROR; 793 return NGX_CONF_ERROR;
732 } 794 }
733 795
734 conf->enable = NGX_CONF_UNSET; 796 conf->enable = NGX_CONF_UNSET;
797 conf->value_len = NGX_CONF_UNSET;
735 798
736 return conf; 799 return conf;
737 } 800 }
738 801
739 802
742 { 805 {
743 ngx_http_ssi_conf_t *prev = parent; 806 ngx_http_ssi_conf_t *prev = parent;
744 ngx_http_ssi_conf_t *conf = child; 807 ngx_http_ssi_conf_t *conf = child;
745 808
746 ngx_conf_merge_value(conf->enable, prev->enable, 0); 809 ngx_conf_merge_value(conf->enable, prev->enable, 0);
810 ngx_conf_merge_size_value(conf->value_len, prev->value_len, 256);
747 811
748 return NGX_CONF_OK; 812 return NGX_CONF_OK;
749 } 813 }
750 814
751 815