comparison src/http/modules/ngx_http_ssi_filter.c @ 242:5d4f49dc8de5

nginx-0.0.1-2004-01-28-18:22:37 import
author Igor Sysoev <igor@sysoev.ru>
date Wed, 28 Jan 2004 15:22:37 +0000
parents 3bfa496bc22e
children bf2faf694c19
comparison
equal deleted inserted replaced
241:3bfa496bc22e 242:5d4f49dc8de5
19 ssize_t value_len; 19 ssize_t value_len;
20 } ngx_http_ssi_conf_t; 20 } ngx_http_ssi_conf_t;
21 21
22 22
23 typedef struct { 23 typedef struct {
24 } ngx_http_ssi_command_t;
25
26
27 typedef struct {
24 ngx_hunk_t *buf; 28 ngx_hunk_t *buf;
25 29
26 char *start; 30 char *start;
27 char *last; 31 char *last;
28 char *pos; 32 char *pos;
36 ngx_chain_t **last_out; 40 ngx_chain_t **last_out;
37 ngx_chain_t *busy; 41 ngx_chain_t *busy;
38 42
39 int state; 43 int state;
40 size_t saved; 44 size_t saved;
41 ngx_int_t err;
42 } ngx_http_ssi_ctx_t; 45 } ngx_http_ssi_ctx_t;
46
47
48 typedef ngx_int_t (*ngx_http_ssi_opcode_pt) (ngx_http_request_t *r,
49 ngx_http_ssi_ctx_t *ctx);
50
51 typedef struct {
52 ngx_str_t name;
53 ngx_http_ssi_opcode_pt op;
54 } ngx_http_ssi_op_t;
43 55
44 56
45 typedef enum { 57 typedef enum {
46 ssi_start_state = 0, 58 ssi_start_state = 0,
47 ssi_tag_state, 59 ssi_tag_state,
56 ssi_prevalue_state, 68 ssi_prevalue_state,
57 ssi_double_quoted_value_state, 69 ssi_double_quoted_value_state,
58 ssi_double_quoted_value_quote_state, 70 ssi_double_quoted_value_quote_state,
59 ssi_quoted_value_state, 71 ssi_quoted_value_state,
60 ssi_quoted_value_quote_state, 72 ssi_quoted_value_quote_state,
73 ssi_comment_end0_state,
74 ssi_comment_end1_state,
61 ssi_error_state, 75 ssi_error_state,
62 ssi_comment_end0_state, 76 ssi_error_end0_state,
63 ssi_comment_end1_state 77 ssi_error_end1_state
64 } ngx_http_ssi_state_e; 78 } ngx_http_ssi_state_e;
65 79
66 80
81 static ngx_int_t ngx_http_ssi_error(ngx_http_request_t *r,
82 ngx_http_ssi_ctx_t *ctx);
67 static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r, 83 static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
68 ngx_http_ssi_ctx_t *ctx); 84 ngx_http_ssi_ctx_t *ctx);
85
86 static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r,
87 ngx_http_ssi_ctx_t *ctx);
88
69 static void *ngx_http_ssi_create_conf(ngx_conf_t *cf); 89 static void *ngx_http_ssi_create_conf(ngx_conf_t *cf);
70 static char *ngx_http_ssi_merge_conf(ngx_conf_t *cf, 90 static char *ngx_http_ssi_merge_conf(ngx_conf_t *cf,
71 void *parent, void *child); 91 void *parent, void *child);
72 static int ngx_http_ssi_filter_init(ngx_cycle_t *cycle); 92 static int ngx_http_ssi_filter_init(ngx_cycle_t *cycle);
93
94
95 static ngx_http_ssi_op_t ngx_http_ssi_commands[] = {
96 { ngx_string("echo"), ngx_http_ssi_echo },
97 { ngx_null_string, NULL }
98 };
73 99
74 100
75 static ngx_command_t ngx_http_ssi_filter_commands[] = { 101 static ngx_command_t ngx_http_ssi_filter_commands[] = {
76 102
77 { ngx_string("ssi"), 103 { ngx_string("ssi"),
109 NULL /* init child */ 135 NULL /* init child */
110 }; 136 };
111 137
112 138
113 static int (*ngx_http_next_header_filter) (ngx_http_request_t *r); 139 static int (*ngx_http_next_header_filter) (ngx_http_request_t *r);
114 static int (*ngx_http_next_body_filter) (ngx_http_request_t *r, ngx_chain_t *in); 140 static int (*ngx_http_next_body_filter) (ngx_http_request_t *r,
115 141 ngx_chain_t *in);
116 142
117 143
118 static char ssi_string[] = "<!--#"; 144 static char ssi_string[] = "<!--#";
119 static char error_string[] = "[an error occurred while processing " 145 static char error_string[] = "[an error occurred while processing "
120 "the directive]"; 146 "the directive]";
147 static char stub_string[] = "[a stub ssi string]";
121 148
122 149
123 static int ngx_http_ssi_header_filter(ngx_http_request_t *r) 150 static int ngx_http_ssi_header_filter(ngx_http_request_t *r)
124 { 151 {
125 ngx_http_ssi_ctx_t *ctx; 152 ngx_http_ssi_ctx_t *ctx;
155 182
156 183
157 static int ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in) 184 static int ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
158 { 185 {
159 size_t len; 186 size_t len;
160 ngx_int_t rc; 187 ngx_int_t rc, found;
161 ngx_hunk_t *hunk; 188 ngx_hunk_t *hunk;
162 ngx_chain_t *cl, *tl; 189 ngx_chain_t *cl, *tl;
190 ngx_http_ssi_op_t *cmd;
163 ngx_http_ssi_ctx_t *ctx; 191 ngx_http_ssi_ctx_t *ctx;
164 192
165 ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module); 193 ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
166 194
167 if (ctx == NULL || (in == NULL && ctx->in == NULL)) { 195 if (ctx == NULL || (in == NULL && ctx->in == NULL)) {
207 } 235 }
208 } 236 }
209 237
210 while (ctx->pos < ctx->buf->last) { 238 while (ctx->pos < ctx->buf->last) {
211 239
240 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
241 "saved: %d state: %d", ctx->saved, ctx->state);
242
243 rc = ngx_http_ssi_parse(r, ctx);
244
212 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 245 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
213 "saved: %d", ctx->saved); 246 "parse: %d", rc);
214 247
215 rc = ngx_http_ssi_parse(r, ctx); 248 if (rc == NGX_AGAIN) {
216 249 continue;
217 if (rc == NGX_ERROR) { 250
251 } else if (rc == NGX_ERROR) {
218 return rc; 252 return rc;
219 253
220 } else if (rc == NGX_HTTP_SSI_COPY) { 254 } else if (rc == NGX_HTTP_SSI_COPY) {
221 255
222 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 256 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
258 if (ctx->pos == ctx->buf->last) { 292 if (ctx->pos == ctx->buf->last) {
259 ctx->saved = ctx->pos - ctx->last; 293 ctx->saved = ctx->pos - ctx->last;
260 } 294 }
261 295
262 continue; 296 continue;
297
298 } else if (rc >= NGX_HTTP_SSI_INVALID_COMMAND) {
299
300 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
301 "saved: %d error: %d",
302 ctx->saved, rc);
303
304 if (ngx_http_ssi_error(r, ctx) == NGX_ERROR) {
305 return NGX_ERROR;
306 }
307
308 if (rc == NGX_HTTP_SSI_INVALID_COMMAND) {
309 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
310 "invalid SSI command \"%s\" found",
311 ctx->command.data);
312
313 } else if (rc == NGX_HTTP_SSI_INVALID_PARAM) {
314 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
315 "invalid parameter \"%s\" found "
316 "in SSI command \"%s\"",
317 ctx->param->key.data, ctx->command.data);
318 }
263 319
264 #if 0 320 #if 0
265 } else if (rc == NGX_HTTP_SSI_INVALID_COMMAND) { 321 } else if (rc == NGX_HTTP_SSI_INVALID_COMMAND) {
266 } else if (rc == NGX_HTTP_SSI_INVALID_PARAM) { 322 } else if (rc == NGX_HTTP_SSI_INVALID_PARAM) {
267 } else if (rc == NGX_HTTP_SSI_INVALID_VALUE) { 323 } else if (rc == NGX_HTTP_SSI_INVALID_VALUE) {
268 } else if (rc == NGX_HTTP_SSI_LONG_VALUE) { 324 } else if (rc == NGX_HTTP_SSI_LONG_VALUE) {
269 #endif 325 #endif
270 326
271 } else { 327 } else {
328
329 found = 0;
330
331 for (cmd = ngx_http_ssi_commands; cmd->name.len; cmd++) {
332 if (ctx->command.len != cmd->name.len) {
333 continue;
334 }
335
336 if (ngx_strncmp(ctx->command.data, cmd->name.data,
337 cmd->name.len) != 0)
338 {
339 continue;
340 }
341
342 found = 1;
343
344 if (cmd->op(r, ctx) == NGX_ERROR) {
345 return NGX_ERROR;
346 }
347 }
348
349 if (!found) {
350 if (ngx_http_ssi_error(r, ctx) == NGX_ERROR) {
351 return NGX_ERROR;
352 }
353 }
354
355 #if 0
272 if (!(hunk = ngx_calloc_hunk(r->pool))) { 356 if (!(hunk = ngx_calloc_hunk(r->pool))) {
273 return NGX_ERROR; 357 return NGX_ERROR;
274 } 358 }
275 359
276 hunk->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP; 360 hunk->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
277 hunk->pos = error_string; 361 hunk->pos = stub_string;
278 hunk->last = error_string + sizeof(error_string) - 1; 362 hunk->last = stub_string + sizeof(stub_string) - 1;
279 363
280 ngx_alloc_link_and_set_hunk(cl, hunk, r->pool, NGX_ERROR); 364 ngx_alloc_link_and_set_hunk(cl, hunk, r->pool, NGX_ERROR);
281 365
282 *ctx->last_out = cl; 366 *ctx->last_out = cl;
283 ctx->last_out = &cl->next; 367 ctx->last_out = &cl->next;
368 #endif
284 } 369 }
285 } 370 }
286 371
287 ctx->buf = NULL; 372 ctx->buf = NULL;
288 } 373 }
310 while (ctx->busy) { 395 while (ctx->busy) {
311 if (ngx_hunk_size(ctx->busy->hunk) != 0) { 396 if (ngx_hunk_size(ctx->busy->hunk) != 0) {
312 break; 397 break;
313 } 398 }
314 399
315 if (ctx->busy->hunk->shadow) { 400 /* TODO: NGX_HUNK_ZEROCOPY_BUSY */
316 ctx->busy->hunk->shadow->pos = ctx->busy->hunk->pos; 401
402 hunk = ctx->busy->hunk->shadow;
403 if (hunk) {
404 hunk->pos = ctx->busy->hunk->pos;
405
406 len = hunk->last - hunk->pos;
407 if (len < 5 && ngx_strncmp(hunk->pos, ssi_string, len) == 0) {
408 hunk->pos = hunk->last;
409 }
317 } 410 }
318 411
319 ctx->busy = ctx->busy->next; 412 ctx->busy = ctx->busy->next;
320 } 413 }
321 } 414 }
415
416 return NGX_OK;
417 }
418
419
420 static ngx_int_t ngx_http_ssi_error(ngx_http_request_t *r,
421 ngx_http_ssi_ctx_t *ctx)
422 {
423 ngx_hunk_t *hunk;
424 ngx_chain_t *cl;
425
426 if (!(hunk = ngx_calloc_hunk(r->pool))) {
427 return NGX_ERROR;
428 }
429
430 hunk->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
431 hunk->pos = error_string;
432 hunk->last = error_string + sizeof(error_string) - 1;
433
434 ngx_alloc_link_and_set_hunk(cl, hunk, r->pool, NGX_ERROR);
435
436 *ctx->last_out = cl;
437 ctx->last_out = &cl->next;
322 438
323 return NGX_OK; 439 return NGX_OK;
324 } 440 }
325 441
326 442
520 return NGX_ERROR; 636 return NGX_ERROR;
521 } 637 }
522 638
523 ctx->command.data[0] = ch; 639 ctx->command.data[0] = ch;
524 ctx->command.len = 1; 640 ctx->command.len = 1;
525 ctx->err = NGX_OK;
526 state = ssi_command_state; 641 state = ssi_command_state;
527 break; 642 break;
528 } 643 }
529 644
530 break; 645 break;
544 state = ssi_comment_end0_state; 659 state = ssi_comment_end0_state;
545 break; 660 break;
546 661
547 default: 662 default:
548 if (ctx->command.len >= NGX_HTTP_SSI_COMMAND_LEN) { 663 if (ctx->command.len >= NGX_HTTP_SSI_COMMAND_LEN) {
549 ctx->err = NGX_HTTP_SSI_INVALID_COMMAND; 664 ctx->command.data[NGX_HTTP_SSI_COMMAND_LEN] = 0;
550 state = ssi_error_state; 665
551 break; 666 ctx->last = last;
667 ctx->pos = p;
668 ctx->state = ssi_error_state;
669
670 return NGX_HTTP_SSI_INVALID_COMMAND;
552 } 671 }
553 672
554 ctx->command.data[ctx->command.len++] = ch; 673 ctx->command.data[ctx->command.len++] = ch;
555 } 674 }
556 675
567 case '-': 686 case '-':
568 state = ssi_comment_end0_state; 687 state = ssi_comment_end0_state;
569 break; 688 break;
570 689
571 default: 690 default:
691 if (ctx->params.elts == NULL) {
692 ngx_init_array(ctx->params, r->pool,
693 5, sizeof(ngx_table_elt_t), NGX_ERROR);
694 }
695
572 if (!(ctx->param = ngx_push_array(&ctx->params))) { 696 if (!(ctx->param = ngx_push_array(&ctx->params))) {
573 return NGX_ERROR; 697 return NGX_ERROR;
574 } 698 }
575 699
576 ctx->param->key.data = 700 ctx->param->key.data =
607 case '=': 731 case '=':
608 ctx->param->key.data[ctx->param->key.len] = 0; 732 ctx->param->key.data[ctx->param->key.len] = 0;
609 state = ssi_prevalue_state; 733 state = ssi_prevalue_state;
610 break; 734 break;
611 735
736 case '-':
737 ctx->last = last;
738 ctx->pos = p;
739 ctx->state = ssi_error_end0_state;
740
741 return NGX_HTTP_SSI_INVALID_PARAM;
742
612 default: 743 default:
613 if (ctx->param->key.len >= NGX_HTTP_SSI_PARAM_LEN) { 744 if (ctx->param->key.len >= NGX_HTTP_SSI_PARAM_LEN) {
614 ctx->err = NGX_HTTP_SSI_INVALID_PARAM; 745 ctx->param->key.data[NGX_HTTP_SSI_PARAM_LEN] = 0;
615 state = ssi_error_state; 746
616 break; 747 ctx->last = last;
748 ctx->pos = p;
749 ctx->state = ssi_error_state;
750
751 return NGX_HTTP_SSI_INVALID_PARAM;
617 } 752 }
618 753
619 ctx->param->key.data[ctx->param->key.len++] = ch; 754 ctx->param->key.data[ctx->param->key.len++] = ch;
620 } 755 }
621 756
631 766
632 case '=': 767 case '=':
633 state = ssi_prevalue_state; 768 state = ssi_prevalue_state;
634 break; 769 break;
635 770
636 default: 771 case '-':
637 ctx->err = NGX_HTTP_SSI_INVALID_PARAM; 772 ctx->last = last;
638 state = ssi_error_state; 773 ctx->pos = p;
639 break; 774 ctx->state = ssi_error_end0_state;
775
776 return NGX_HTTP_SSI_INVALID_PARAM;
777
778 default:
779 ctx->last = last;
780 ctx->pos = p;
781 ctx->state = ssi_error_state;
782
783 return NGX_HTTP_SSI_INVALID_PARAM;
640 } 784 }
641 785
642 break; 786 break;
643 787
644 case ssi_prevalue_state: 788 case ssi_prevalue_state:
655 799
656 case '\'': 800 case '\'':
657 state = ssi_quoted_value_state; 801 state = ssi_quoted_value_state;
658 break; 802 break;
659 803
660 default: 804 case '-':
661 ctx->err = NGX_HTTP_SSI_INVALID_VALUE; 805 ctx->last = last;
662 state = ssi_error_state; 806 ctx->pos = p;
663 break; 807 ctx->state = ssi_error_end0_state;
808
809 return NGX_HTTP_SSI_INVALID_VALUE;
810
811 default:
812 ctx->last = last;
813 ctx->pos = p;
814 ctx->state = ssi_error_state;
815
816 return NGX_HTTP_SSI_INVALID_VALUE;
664 } 817 }
665 818
666 break; 819 break;
667 820
668 case ssi_double_quoted_value_state: 821 case ssi_double_quoted_value_state:
675 state = ssi_preparam_state; 828 state = ssi_preparam_state;
676 break; 829 break;
677 830
678 default: 831 default:
679 if ((ssize_t) ctx->param->value.len >= conf->value_len) { 832 if ((ssize_t) ctx->param->value.len >= conf->value_len) {
680 ctx->err = NGX_HTTP_SSI_LONG_VALUE; 833 ctx->last = last;
681 state = ssi_error_state; 834 ctx->pos = p;
682 break; 835 ctx->state = ssi_error_state;
836
837 return NGX_HTTP_SSI_LONG_VALUE;
683 } 838 }
684 839
685 ctx->param->value.data[ctx->param->value.len++] = ch; 840 ctx->param->value.data[ctx->param->value.len++] = ch;
686 } 841 }
687 842
688 break; 843 break;
689 844
690 case ssi_double_quoted_value_quote_state: 845 case ssi_double_quoted_value_quote_state:
691 if ((ssize_t) ctx->param->value.len >= conf->value_len) { 846 if ((ssize_t) ctx->param->value.len >= conf->value_len) {
692 ctx->err = NGX_HTTP_SSI_LONG_VALUE; 847 ctx->last = last;
693 state = ssi_error_state; 848 ctx->pos = p;
694 break; 849 ctx->state = ssi_error_state;
850
851 return NGX_HTTP_SSI_LONG_VALUE;
695 } 852 }
696 853
697 ctx->param->value.data[ctx->param->value.len++] = ch; 854 ctx->param->value.data[ctx->param->value.len++] = ch;
698 855
699 state = ssi_double_quoted_value_state; 856 state = ssi_double_quoted_value_state;
709 state = ssi_preparam_state; 866 state = ssi_preparam_state;
710 break; 867 break;
711 868
712 default: 869 default:
713 if ((ssize_t) ctx->param->value.len >= conf->value_len) { 870 if ((ssize_t) ctx->param->value.len >= conf->value_len) {
714 ctx->err = NGX_HTTP_SSI_LONG_VALUE; 871 ctx->last = last;
715 state = ssi_error_state; 872 ctx->pos = p;
716 break; 873 ctx->state = ssi_error_state;
874
875 return NGX_HTTP_SSI_LONG_VALUE;
717 } 876 }
718 877
719 ctx->param->value.data[ctx->param->value.len++] = ch; 878 ctx->param->value.data[ctx->param->value.len++] = ch;
720 } 879 }
721 880
722 break; 881 break;
723 882
724 case ssi_quoted_value_quote_state: 883 case ssi_quoted_value_quote_state:
725 if ((ssize_t) ctx->param->value.len >= conf->value_len) { 884 if ((ssize_t) ctx->param->value.len >= conf->value_len) {
726 ctx->err = NGX_HTTP_SSI_LONG_VALUE; 885 ctx->last = last;
727 state = ssi_error_state; 886 ctx->pos = p;
728 break; 887 ctx->state = ssi_error_state;
888
889 return NGX_HTTP_SSI_LONG_VALUE;
729 } 890 }
730 891
731 ctx->param->value.data[ctx->param->value.len++] = ch; 892 ctx->param->value.data[ctx->param->value.len++] = ch;
732 893
733 state = ssi_quoted_value_state; 894 state = ssi_quoted_value_state;
734 break; 895 break;
735 896
736 case ssi_error_state: 897 case ssi_comment_end0_state:
737 switch (ch) { 898 switch (ch) {
738 case '-': 899 case '-':
739 state = ssi_comment_end1_state; 900 state = ssi_comment_end1_state;
740 break; 901 break;
741 902
742 default: 903 default:
743 break; 904 ctx->last = last;
744 } 905 ctx->pos = p;
745 906 ctx->state = ssi_error_state;
746 break; 907
747 908 return NGX_HTTP_SSI_INVALID_COMMAND;
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;
758 } 909 }
759 910
760 break; 911 break;
761 912
762 case ssi_comment_end1_state: 913 case ssi_comment_end1_state:
763 switch (ch) { 914 switch (ch) {
764 case '>': 915 case '>':
765 ctx->state = ssi_start_state; 916 ctx->state = ssi_start_state;
766 ctx->start = p; 917 ctx->start = p;
767 ctx->pos = p; 918 ctx->pos = p;
768 return ctx->err; 919
769 920 return NGX_OK;
770 default: 921
771 ctx->err = NGX_HTTP_SSI_INVALID_COMMAND; 922 default:
923 ctx->last = last;
924 ctx->pos = p;
925 ctx->state = ssi_error_state;
926
927 return NGX_HTTP_SSI_INVALID_COMMAND;
928 }
929
930 break;
931
932 case ssi_error_state:
933 switch (ch) {
934 case '-':
935 state = ssi_error_end0_state;
936 break;
937
938 default:
939 break;
940 }
941
942 break;
943
944 case ssi_error_end0_state:
945 switch (ch) {
946 case '-':
947 state = ssi_error_end1_state;
948 break;
949
950 default:
951 state = ssi_error_state;
952 break;
953 }
954
955 break;
956
957 case ssi_error_end1_state:
958 switch (ch) {
959 case '>':
960 ctx->state = ssi_start_state;
961 ctx->start = p;
962 ctx->pos = p;
963
964 return NGX_AGAIN;
965
966 default:
772 state = ssi_error_state; 967 state = ssi_error_state;
773 break; 968 break;
774 } 969 }
775 970
776 break; 971 break;
780 ctx->state = state; 975 ctx->state = state;
781 ctx->last = last; 976 ctx->last = last;
782 ctx->pos = p; 977 ctx->pos = p;
783 978
784 return NGX_HTTP_SSI_COPY; 979 return NGX_HTTP_SSI_COPY;
980 }
981
982
983 static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r,
984 ngx_http_ssi_ctx_t *ctx)
985 {
986 return NGX_OK;
785 } 987 }
786 988
787 989
788 static void *ngx_http_ssi_create_conf(ngx_conf_t *cf) 990 static void *ngx_http_ssi_create_conf(ngx_conf_t *cf)
789 { 991 {