Mercurial > hg > nginx
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 |