1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_http.h>
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev#define NGX_HTTP_SSI_ERROR          1
13e18a033bSKonstantin Ananyev
14e18a033bSKonstantin Ananyev#define NGX_HTTP_SSI_DATE_LEN       2048
15e18a033bSKonstantin Ananyev
16e18a033bSKonstantin Ananyev#define NGX_HTTP_SSI_ADD_PREFIX     1
17e18a033bSKonstantin Ananyev#define NGX_HTTP_SSI_ADD_ZERO       2
18e18a033bSKonstantin Ananyev
19e18a033bSKonstantin Ananyev
20e18a033bSKonstantin Ananyevtypedef struct {
21e18a033bSKonstantin Ananyev    ngx_flag_t    enable;
22e18a033bSKonstantin Ananyev    ngx_flag_t    silent_errors;
23e18a033bSKonstantin Ananyev    ngx_flag_t    ignore_recycled_buffers;
24e18a033bSKonstantin Ananyev    ngx_flag_t    last_modified;
25e18a033bSKonstantin Ananyev
26e18a033bSKonstantin Ananyev    ngx_hash_t    types;
27e18a033bSKonstantin Ananyev
28e18a033bSKonstantin Ananyev    size_t        min_file_chunk;
29e18a033bSKonstantin Ananyev    size_t        value_len;
30e18a033bSKonstantin Ananyev
31e18a033bSKonstantin Ananyev    ngx_array_t  *types_keys;
32e18a033bSKonstantin Ananyev} ngx_http_ssi_loc_conf_t;
33e18a033bSKonstantin Ananyev
34e18a033bSKonstantin Ananyev
35e18a033bSKonstantin Ananyevtypedef struct {
36e18a033bSKonstantin Ananyev    ngx_str_t     name;
37e18a033bSKonstantin Ananyev    ngx_uint_t    key;
38e18a033bSKonstantin Ananyev    ngx_str_t     value;
39e18a033bSKonstantin Ananyev} ngx_http_ssi_var_t;
40e18a033bSKonstantin Ananyev
41e18a033bSKonstantin Ananyev
42e18a033bSKonstantin Ananyevtypedef struct {
43e18a033bSKonstantin Ananyev    ngx_str_t     name;
44e18a033bSKonstantin Ananyev    ngx_chain_t  *bufs;
45e18a033bSKonstantin Ananyev    ngx_uint_t    count;
46e18a033bSKonstantin Ananyev} ngx_http_ssi_block_t;
47e18a033bSKonstantin Ananyev
48e18a033bSKonstantin Ananyev
49e18a033bSKonstantin Ananyevtypedef enum {
50e18a033bSKonstantin Ananyev    ssi_start_state = 0,
51e18a033bSKonstantin Ananyev    ssi_tag_state,
52e18a033bSKonstantin Ananyev    ssi_comment0_state,
53e18a033bSKonstantin Ananyev    ssi_comment1_state,
54e18a033bSKonstantin Ananyev    ssi_sharp_state,
55e18a033bSKonstantin Ananyev    ssi_precommand_state,
56e18a033bSKonstantin Ananyev    ssi_command_state,
57e18a033bSKonstantin Ananyev    ssi_preparam_state,
58e18a033bSKonstantin Ananyev    ssi_param_state,
59e18a033bSKonstantin Ananyev    ssi_preequal_state,
60e18a033bSKonstantin Ananyev    ssi_prevalue_state,
61e18a033bSKonstantin Ananyev    ssi_double_quoted_value_state,
62e18a033bSKonstantin Ananyev    ssi_quoted_value_state,
63e18a033bSKonstantin Ananyev    ssi_quoted_symbol_state,
64e18a033bSKonstantin Ananyev    ssi_postparam_state,
65e18a033bSKonstantin Ananyev    ssi_comment_end0_state,
66e18a033bSKonstantin Ananyev    ssi_comment_end1_state,
67e18a033bSKonstantin Ananyev    ssi_error_state,
68e18a033bSKonstantin Ananyev    ssi_error_end0_state,
69e18a033bSKonstantin Ananyev    ssi_error_end1_state
70e18a033bSKonstantin Ananyev} ngx_http_ssi_state_e;
71e18a033bSKonstantin Ananyev
72e18a033bSKonstantin Ananyev
73e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_output(ngx_http_request_t *r,
74e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx);
75e18a033bSKonstantin Ananyevstatic void ngx_http_ssi_buffered(ngx_http_request_t *r,
76e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx);
77e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
78e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx);
79e18a033bSKonstantin Ananyevstatic ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r,
80e18a033bSKonstantin Ananyev    ngx_str_t *name, ngx_uint_t key);
81e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r,
82e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags);
83e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_regex_match(ngx_http_request_t *r,
84e18a033bSKonstantin Ananyev    ngx_str_t *pattern, ngx_str_t *str);
85e18a033bSKonstantin Ananyev
86e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
87e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
88e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data,
89e18a033bSKonstantin Ananyev    ngx_int_t rc);
90e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data,
91e18a033bSKonstantin Ananyev    ngx_int_t rc);
92e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r,
93e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
94e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_config(ngx_http_request_t *r,
95e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
96e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_set(ngx_http_request_t *r,
97e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
98e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_if(ngx_http_request_t *r,
99e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
100e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_else(ngx_http_request_t *r,
101e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
102e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_endif(ngx_http_request_t *r,
103e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
104e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_block(ngx_http_request_t *r,
105e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
106e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_endblock(ngx_http_request_t *r,
107e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
108e18a033bSKonstantin Ananyev
109e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r,
110e18a033bSKonstantin Ananyev    ngx_http_variable_value_t *v, uintptr_t gmt);
111e18a033bSKonstantin Ananyev
112e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_preconfiguration(ngx_conf_t *cf);
113e18a033bSKonstantin Ananyevstatic void *ngx_http_ssi_create_main_conf(ngx_conf_t *cf);
114e18a033bSKonstantin Ananyevstatic char *ngx_http_ssi_init_main_conf(ngx_conf_t *cf, void *conf);
115e18a033bSKonstantin Ananyevstatic void *ngx_http_ssi_create_loc_conf(ngx_conf_t *cf);
116e18a033bSKonstantin Ananyevstatic char *ngx_http_ssi_merge_loc_conf(ngx_conf_t *cf,
117e18a033bSKonstantin Ananyev    void *parent, void *child);
118e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_ssi_filter_init(ngx_conf_t *cf);
119e18a033bSKonstantin Ananyev
120e18a033bSKonstantin Ananyev
121e18a033bSKonstantin Ananyevstatic ngx_command_t  ngx_http_ssi_filter_commands[] = {
122e18a033bSKonstantin Ananyev
123e18a033bSKonstantin Ananyev    { ngx_string("ssi"),
124e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
125e18a033bSKonstantin Ananyev                        |NGX_CONF_FLAG,
126e18a033bSKonstantin Ananyev      ngx_conf_set_flag_slot,
127e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
128e18a033bSKonstantin Ananyev      offsetof(ngx_http_ssi_loc_conf_t, enable),
129e18a033bSKonstantin Ananyev      NULL },
130e18a033bSKonstantin Ananyev
131e18a033bSKonstantin Ananyev    { ngx_string("ssi_silent_errors"),
132e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
133e18a033bSKonstantin Ananyev      ngx_conf_set_flag_slot,
134e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
135e18a033bSKonstantin Ananyev      offsetof(ngx_http_ssi_loc_conf_t, silent_errors),
136e18a033bSKonstantin Ananyev      NULL },
137e18a033bSKonstantin Ananyev
138e18a033bSKonstantin Ananyev    { ngx_string("ssi_ignore_recycled_buffers"),
139e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
140e18a033bSKonstantin Ananyev      ngx_conf_set_flag_slot,
141e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
142e18a033bSKonstantin Ananyev      offsetof(ngx_http_ssi_loc_conf_t, ignore_recycled_buffers),
143e18a033bSKonstantin Ananyev      NULL },
144e18a033bSKonstantin Ananyev
145e18a033bSKonstantin Ananyev    { ngx_string("ssi_min_file_chunk"),
146e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
147e18a033bSKonstantin Ananyev      ngx_conf_set_size_slot,
148e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
149e18a033bSKonstantin Ananyev      offsetof(ngx_http_ssi_loc_conf_t, min_file_chunk),
150e18a033bSKonstantin Ananyev      NULL },
151e18a033bSKonstantin Ananyev
152e18a033bSKonstantin Ananyev    { ngx_string("ssi_value_length"),
153e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
154e18a033bSKonstantin Ananyev      ngx_conf_set_size_slot,
155e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
156e18a033bSKonstantin Ananyev      offsetof(ngx_http_ssi_loc_conf_t, value_len),
157e18a033bSKonstantin Ananyev      NULL },
158e18a033bSKonstantin Ananyev
159e18a033bSKonstantin Ananyev    { ngx_string("ssi_types"),
160e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
161e18a033bSKonstantin Ananyev      ngx_http_types_slot,
162e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
163e18a033bSKonstantin Ananyev      offsetof(ngx_http_ssi_loc_conf_t, types_keys),
164e18a033bSKonstantin Ananyev      &ngx_http_html_default_types[0] },
165e18a033bSKonstantin Ananyev
166e18a033bSKonstantin Ananyev    { ngx_string("ssi_last_modified"),
167e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
168e18a033bSKonstantin Ananyev      ngx_conf_set_flag_slot,
169e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
170e18a033bSKonstantin Ananyev      offsetof(ngx_http_ssi_loc_conf_t, last_modified),
171e18a033bSKonstantin Ananyev      NULL },
172e18a033bSKonstantin Ananyev
173e18a033bSKonstantin Ananyev      ngx_null_command
174e18a033bSKonstantin Ananyev};
175e18a033bSKonstantin Ananyev
176e18a033bSKonstantin Ananyev
177e18a033bSKonstantin Ananyev
178e18a033bSKonstantin Ananyevstatic ngx_http_module_t  ngx_http_ssi_filter_module_ctx = {
179e18a033bSKonstantin Ananyev    ngx_http_ssi_preconfiguration,         /* preconfiguration */
180e18a033bSKonstantin Ananyev    ngx_http_ssi_filter_init,              /* postconfiguration */
181e18a033bSKonstantin Ananyev
182e18a033bSKonstantin Ananyev    ngx_http_ssi_create_main_conf,         /* create main configuration */
183e18a033bSKonstantin Ananyev    ngx_http_ssi_init_main_conf,           /* init main configuration */
184e18a033bSKonstantin Ananyev
185e18a033bSKonstantin Ananyev    NULL,                                  /* create server configuration */
186e18a033bSKonstantin Ananyev    NULL,                                  /* merge server configuration */
187e18a033bSKonstantin Ananyev
188e18a033bSKonstantin Ananyev    ngx_http_ssi_create_loc_conf,          /* create location configuration */
189e18a033bSKonstantin Ananyev    ngx_http_ssi_merge_loc_conf            /* merge location configuration */
190e18a033bSKonstantin Ananyev};
191e18a033bSKonstantin Ananyev
192e18a033bSKonstantin Ananyev
193e18a033bSKonstantin Ananyevngx_module_t  ngx_http_ssi_filter_module = {
194e18a033bSKonstantin Ananyev    NGX_MODULE_V1,
195e18a033bSKonstantin Ananyev    &ngx_http_ssi_filter_module_ctx,       /* module context */
196e18a033bSKonstantin Ananyev    ngx_http_ssi_filter_commands,          /* module directives */
197e18a033bSKonstantin Ananyev    NGX_HTTP_MODULE,                       /* module type */
198e18a033bSKonstantin Ananyev    NULL,                                  /* init master */
199e18a033bSKonstantin Ananyev    NULL,                                  /* init module */
200e18a033bSKonstantin Ananyev    NULL,                                  /* init process */
201e18a033bSKonstantin Ananyev    NULL,                                  /* init thread */
202e18a033bSKonstantin Ananyev    NULL,                                  /* exit thread */
203e18a033bSKonstantin Ananyev    NULL,                                  /* exit process */
204e18a033bSKonstantin Ananyev    NULL,                                  /* exit master */
205e18a033bSKonstantin Ananyev    NGX_MODULE_V1_PADDING
206e18a033bSKonstantin Ananyev};
207e18a033bSKonstantin Ananyev
208e18a033bSKonstantin Ananyev
209e18a033bSKonstantin Ananyevstatic ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
210e18a033bSKonstantin Ananyevstatic ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
211e18a033bSKonstantin Ananyev
212e18a033bSKonstantin Ananyev
213e18a033bSKonstantin Ananyevstatic u_char ngx_http_ssi_string[] = "<!--";
214e18a033bSKonstantin Ananyev
215e18a033bSKonstantin Ananyevstatic ngx_str_t ngx_http_ssi_none = ngx_string("(none)");
216e18a033bSKonstantin Ananyevstatic ngx_str_t ngx_http_ssi_timefmt = ngx_string("%A, %d-%b-%Y %H:%M:%S %Z");
217e18a033bSKonstantin Ananyevstatic ngx_str_t ngx_http_ssi_null_string = ngx_null_string;
218e18a033bSKonstantin Ananyev
219e18a033bSKonstantin Ananyev
220e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_INCLUDE_VIRTUAL  0
221e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_INCLUDE_FILE     1
222e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_INCLUDE_WAIT     2
223e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_INCLUDE_SET      3
224e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_INCLUDE_STUB     4
225e18a033bSKonstantin Ananyev
226e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_ECHO_VAR         0
227e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_ECHO_DEFAULT     1
228e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_ECHO_ENCODING    2
229e18a033bSKonstantin Ananyev
230e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_CONFIG_ERRMSG    0
231e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_CONFIG_TIMEFMT   1
232e18a033bSKonstantin Ananyev
233e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_SET_VAR          0
234e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_SET_VALUE        1
235e18a033bSKonstantin Ananyev
236e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_IF_EXPR          0
237e18a033bSKonstantin Ananyev
238e18a033bSKonstantin Ananyev#define  NGX_HTTP_SSI_BLOCK_NAME       0
239e18a033bSKonstantin Ananyev
240e18a033bSKonstantin Ananyev
241e18a033bSKonstantin Ananyevstatic ngx_http_ssi_param_t  ngx_http_ssi_include_params[] = {
242e18a033bSKonstantin Ananyev    { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0, 0 },
243e18a033bSKonstantin Ananyev    { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0, 0 },
244e18a033bSKonstantin Ananyev    { ngx_string("wait"), NGX_HTTP_SSI_INCLUDE_WAIT, 0, 0 },
245e18a033bSKonstantin Ananyev    { ngx_string("set"), NGX_HTTP_SSI_INCLUDE_SET, 0, 0 },
246e18a033bSKonstantin Ananyev    { ngx_string("stub"), NGX_HTTP_SSI_INCLUDE_STUB, 0, 0 },
247e18a033bSKonstantin Ananyev    { ngx_null_string, 0, 0, 0 }
248e18a033bSKonstantin Ananyev};
249e18a033bSKonstantin Ananyev
250e18a033bSKonstantin Ananyev
251e18a033bSKonstantin Ananyevstatic ngx_http_ssi_param_t  ngx_http_ssi_echo_params[] = {
252e18a033bSKonstantin Ananyev    { ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1, 0 },
253e18a033bSKonstantin Ananyev    { ngx_string("default"), NGX_HTTP_SSI_ECHO_DEFAULT, 0, 0 },
254e18a033bSKonstantin Ananyev    { ngx_string("encoding"), NGX_HTTP_SSI_ECHO_ENCODING, 0, 0 },
255e18a033bSKonstantin Ananyev    { ngx_null_string, 0, 0, 0 }
256e18a033bSKonstantin Ananyev};
257e18a033bSKonstantin Ananyev
258e18a033bSKonstantin Ananyev
259e18a033bSKonstantin Ananyevstatic ngx_http_ssi_param_t  ngx_http_ssi_config_params[] = {
260e18a033bSKonstantin Ananyev    { ngx_string("errmsg"), NGX_HTTP_SSI_CONFIG_ERRMSG, 0, 0 },
261e18a033bSKonstantin Ananyev    { ngx_string("timefmt"), NGX_HTTP_SSI_CONFIG_TIMEFMT, 0, 0 },
262e18a033bSKonstantin Ananyev    { ngx_null_string, 0, 0, 0 }
263e18a033bSKonstantin Ananyev};
264e18a033bSKonstantin Ananyev
265e18a033bSKonstantin Ananyev
266e18a033bSKonstantin Ananyevstatic ngx_http_ssi_param_t  ngx_http_ssi_set_params[] = {
267e18a033bSKonstantin Ananyev    { ngx_string("var"), NGX_HTTP_SSI_SET_VAR, 1, 0 },
268e18a033bSKonstantin Ananyev    { ngx_string("value"), NGX_HTTP_SSI_SET_VALUE, 1, 0 },
269e18a033bSKonstantin Ananyev    { ngx_null_string, 0, 0, 0 }
270e18a033bSKonstantin Ananyev};
271e18a033bSKonstantin Ananyev
272e18a033bSKonstantin Ananyev
273e18a033bSKonstantin Ananyevstatic ngx_http_ssi_param_t  ngx_http_ssi_if_params[] = {
274e18a033bSKonstantin Ananyev    { ngx_string("expr"), NGX_HTTP_SSI_IF_EXPR, 1, 0 },
275e18a033bSKonstantin Ananyev    { ngx_null_string, 0, 0, 0 }
276e18a033bSKonstantin Ananyev};
277e18a033bSKonstantin Ananyev
278e18a033bSKonstantin Ananyev
279e18a033bSKonstantin Ananyevstatic ngx_http_ssi_param_t  ngx_http_ssi_block_params[] = {
280e18a033bSKonstantin Ananyev    { ngx_string("name"), NGX_HTTP_SSI_BLOCK_NAME, 1, 0 },
281e18a033bSKonstantin Ananyev    { ngx_null_string, 0, 0, 0 }
282e18a033bSKonstantin Ananyev};
283e18a033bSKonstantin Ananyev
284e18a033bSKonstantin Ananyev
285e18a033bSKonstantin Ananyevstatic ngx_http_ssi_param_t  ngx_http_ssi_no_params[] = {
286e18a033bSKonstantin Ananyev    { ngx_null_string, 0, 0, 0 }
287e18a033bSKonstantin Ananyev};
288e18a033bSKonstantin Ananyev
289e18a033bSKonstantin Ananyev
290e18a033bSKonstantin Ananyevstatic ngx_http_ssi_command_t  ngx_http_ssi_commands[] = {
291e18a033bSKonstantin Ananyev    { ngx_string("include"), ngx_http_ssi_include,
292e18a033bSKonstantin Ananyev                       ngx_http_ssi_include_params, 0, 0, 1 },
293e18a033bSKonstantin Ananyev    { ngx_string("echo"), ngx_http_ssi_echo,
294e18a033bSKonstantin Ananyev                       ngx_http_ssi_echo_params, 0, 0, 0 },
295e18a033bSKonstantin Ananyev    { ngx_string("config"), ngx_http_ssi_config,
296e18a033bSKonstantin Ananyev                       ngx_http_ssi_config_params, 0, 0, 0 },
297e18a033bSKonstantin Ananyev    { ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0, 0 },
298e18a033bSKonstantin Ananyev
299e18a033bSKonstantin Ananyev    { ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0, 0 },
300e18a033bSKonstantin Ananyev    { ngx_string("elif"), ngx_http_ssi_if, ngx_http_ssi_if_params,
301e18a033bSKonstantin Ananyev                       NGX_HTTP_SSI_COND_IF, 0, 0 },
302e18a033bSKonstantin Ananyev    { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params,
303e18a033bSKonstantin Ananyev                       NGX_HTTP_SSI_COND_IF, 0, 0 },
304e18a033bSKonstantin Ananyev    { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params,
305e18a033bSKonstantin Ananyev                       NGX_HTTP_SSI_COND_ELSE, 0, 0 },
306e18a033bSKonstantin Ananyev
307e18a033bSKonstantin Ananyev    { ngx_string("block"), ngx_http_ssi_block,
308e18a033bSKonstantin Ananyev                       ngx_http_ssi_block_params, 0, 0, 0 },
309e18a033bSKonstantin Ananyev    { ngx_string("endblock"), ngx_http_ssi_endblock,
310e18a033bSKonstantin Ananyev                       ngx_http_ssi_no_params, 0, 1, 0 },
311e18a033bSKonstantin Ananyev
312e18a033bSKonstantin Ananyev    { ngx_null_string, NULL, NULL, 0, 0, 0 }
313e18a033bSKonstantin Ananyev};
314e18a033bSKonstantin Ananyev
315e18a033bSKonstantin Ananyev
316e18a033bSKonstantin Ananyevstatic ngx_http_variable_t  ngx_http_ssi_vars[] = {
317e18a033bSKonstantin Ananyev
318e18a033bSKonstantin Ananyev    { ngx_string("date_local"), NULL, ngx_http_ssi_date_gmt_local_variable, 0,
319e18a033bSKonstantin Ananyev      NGX_HTTP_VAR_NOCACHEABLE, 0 },
320e18a033bSKonstantin Ananyev
321e18a033bSKonstantin Ananyev    { ngx_string("date_gmt"), NULL, ngx_http_ssi_date_gmt_local_variable, 1,
322e18a033bSKonstantin Ananyev      NGX_HTTP_VAR_NOCACHEABLE, 0 },
323e18a033bSKonstantin Ananyev
324e18a033bSKonstantin Ananyev    { ngx_null_string, NULL, NULL, 0, 0, 0 }
325e18a033bSKonstantin Ananyev};
326e18a033bSKonstantin Ananyev
327e18a033bSKonstantin Ananyev
328e18a033bSKonstantin Ananyev
329e18a033bSKonstantin Ananyevstatic ngx_int_t
330e18a033bSKonstantin Ananyevngx_http_ssi_header_filter(ngx_http_request_t *r)
331e18a033bSKonstantin Ananyev{
332e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t       *ctx;
333e18a033bSKonstantin Ananyev    ngx_http_ssi_loc_conf_t  *slcf;
334e18a033bSKonstantin Ananyev
335e18a033bSKonstantin Ananyev    slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module);
336e18a033bSKonstantin Ananyev
337e18a033bSKonstantin Ananyev    if (!slcf->enable
338e18a033bSKonstantin Ananyev        || r->headers_out.content_length_n == 0
339e18a033bSKonstantin Ananyev        || ngx_http_test_content_type(r, &slcf->types) == NULL)
340e18a033bSKonstantin Ananyev    {
341e18a033bSKonstantin Ananyev        return ngx_http_next_header_filter(r);
342e18a033bSKonstantin Ananyev    }
343e18a033bSKonstantin Ananyev
344e18a033bSKonstantin Ananyev    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ssi_ctx_t));
345e18a033bSKonstantin Ananyev    if (ctx == NULL) {
346e18a033bSKonstantin Ananyev        return NGX_ERROR;
347e18a033bSKonstantin Ananyev    }
348e18a033bSKonstantin Ananyev
349e18a033bSKonstantin Ananyev    ngx_http_set_ctx(r, ctx, ngx_http_ssi_filter_module);
350e18a033bSKonstantin Ananyev
351e18a033bSKonstantin Ananyev
352e18a033bSKonstantin Ananyev    ctx->value_len = slcf->value_len;
353e18a033bSKonstantin Ananyev    ctx->last_out = &ctx->out;
354e18a033bSKonstantin Ananyev
355e18a033bSKonstantin Ananyev    ctx->encoding = NGX_HTTP_SSI_ENTITY_ENCODING;
356e18a033bSKonstantin Ananyev    ctx->output = 1;
357e18a033bSKonstantin Ananyev
358e18a033bSKonstantin Ananyev    ctx->params.elts = ctx->params_array;
359e18a033bSKonstantin Ananyev    ctx->params.size = sizeof(ngx_table_elt_t);
360e18a033bSKonstantin Ananyev    ctx->params.nalloc = NGX_HTTP_SSI_PARAMS_N;
361e18a033bSKonstantin Ananyev    ctx->params.pool = r->pool;
362e18a033bSKonstantin Ananyev
363e18a033bSKonstantin Ananyev    ctx->timefmt = ngx_http_ssi_timefmt;
364e18a033bSKonstantin Ananyev    ngx_str_set(&ctx->errmsg,
365e18a033bSKonstantin Ananyev                "[an error occurred while processing the directive]");
366e18a033bSKonstantin Ananyev
367e18a033bSKonstantin Ananyev    r->filter_need_in_memory = 1;
368e18a033bSKonstantin Ananyev
369e18a033bSKonstantin Ananyev    if (r == r->main) {
370e18a033bSKonstantin Ananyev        ngx_http_clear_content_length(r);
371e18a033bSKonstantin Ananyev        ngx_http_clear_accept_ranges(r);
372e18a033bSKonstantin Ananyev
373e18a033bSKonstantin Ananyev        if (!slcf->last_modified) {
374e18a033bSKonstantin Ananyev            ngx_http_clear_last_modified(r);
375e18a033bSKonstantin Ananyev            ngx_http_clear_etag(r);
376e18a033bSKonstantin Ananyev
377e18a033bSKonstantin Ananyev        } else {
378e18a033bSKonstantin Ananyev            ngx_http_weak_etag(r);
379e18a033bSKonstantin Ananyev        }
380e18a033bSKonstantin Ananyev    }
381e18a033bSKonstantin Ananyev
382e18a033bSKonstantin Ananyev    return ngx_http_next_header_filter(r);
383e18a033bSKonstantin Ananyev}
384e18a033bSKonstantin Ananyev
385e18a033bSKonstantin Ananyev
386e18a033bSKonstantin Ananyevstatic ngx_int_t
387e18a033bSKonstantin Ananyevngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
388e18a033bSKonstantin Ananyev{
389e18a033bSKonstantin Ananyev    size_t                     len;
390e18a033bSKonstantin Ananyev    ngx_int_t                  rc;
391e18a033bSKonstantin Ananyev    ngx_buf_t                 *b;
392e18a033bSKonstantin Ananyev    ngx_uint_t                 i, index;
393e18a033bSKonstantin Ananyev    ngx_chain_t               *cl, **ll;
394e18a033bSKonstantin Ananyev    ngx_table_elt_t           *param;
395e18a033bSKonstantin Ananyev    ngx_http_ssi_ctx_t        *ctx, *mctx;
396e18a033bSKonstantin Ananyev    ngx_http_ssi_block_t      *bl;
397e18a033bSKonstantin Ananyev    ngx_http_ssi_param_t      *prm;
398e18a033bSKonstantin Ananyev    ngx_http_ssi_command_t    *cmd;
399e18a033bSKonstantin Ananyev    ngx_http_ssi_loc_conf_t   *slcf;
400e18a033bSKonstantin Ananyev    ngx_http_ssi_main_conf_t  *smcf;
401e18a033bSKonstantin Ananyev    ngx_str_t                 *params[NGX_HTTP_SSI_MAX_PARAMS + 1];
402e18a033bSKonstantin Ananyev
403e18a033bSKonstantin Ananyev    ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
404e18a033bSKonstantin Ananyev
405e18a033bSKonstantin Ananyev    if (ctx == NULL
406e18a033bSKonstantin Ananyev        || (in == NULL
407e18a033bSKonstantin Ananyev            && ctx->buf == NULL
408e18a033bSKonstantin Ananyev            && ctx->in == NULL
409e18a033bSKonstantin Ananyev            && ctx->busy == NULL))
410e18a033bSKonstantin Ananyev    {
411e18a033bSKonstantin Ananyev        return ngx_http_next_body_filter(r, in);
412e18a033bSKonstantin Ananyev    }