Mercurial > hg > nginx-vendor-current
comparison src/http/modules/ngx_http_ssi_filter_module.c @ 146:36af50a5582d NGINX_0_3_20
nginx 0.3.20
*) Bugfix: in SSI handling.
*) Bugfix: the ngx_http_memcached_module did not support the keys in
the "/usr?args" form.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Wed, 11 Jan 2006 00:00:00 +0300 |
parents | 8e6d4d96ec4c |
children | ea622d8acb38 |
comparison
equal
deleted
inserted
replaced
145:85a84f8da62b | 146:36af50a5582d |
---|---|
6 | 6 |
7 #include <ngx_config.h> | 7 #include <ngx_config.h> |
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_http.h> | 9 #include <ngx_http.h> |
10 | 10 |
11 #define NGX_HTTP_SSI_MAX_PARAMS 16 | |
12 | |
13 #define NGX_HTTP_SSI_COMMAND_LEN 31 | |
14 #define NGX_HTTP_SSI_PARAM_LEN 31 | |
15 #define NGX_HTTP_SSI_PARAMS_N 4 | |
16 | |
17 #define NGX_HTTP_SSI_ERROR 1 | 11 #define NGX_HTTP_SSI_ERROR 1 |
18 | 12 |
19 #define NGX_HTTP_SSI_DATE_LEN 2048 | 13 #define NGX_HTTP_SSI_DATE_LEN 2048 |
20 | 14 |
21 | |
22 #define NGX_HTTP_SSI_ADD_PREFIX 1 | 15 #define NGX_HTTP_SSI_ADD_PREFIX 1 |
23 | 16 |
24 | 17 |
25 typedef struct { | 18 typedef struct { |
26 ngx_flag_t enable; | 19 ngx_flag_t enable; |
27 ngx_flag_t silent_errors; | 20 ngx_flag_t silent_errors; |
28 ngx_flag_t ignore_recycled_buffers; | 21 ngx_flag_t ignore_recycled_buffers; |
29 | 22 |
30 ngx_array_t *types; /* array of ngx_str_t */ | 23 ngx_array_t *types; /* array of ngx_str_t */ |
31 | 24 |
32 size_t min_file_chunk; | 25 size_t min_file_chunk; |
33 size_t value_len; | 26 size_t value_len; |
34 } ngx_http_ssi_conf_t; | 27 } ngx_http_ssi_loc_conf_t; |
35 | 28 |
36 | 29 |
37 typedef struct { | 30 typedef struct { |
38 ngx_str_t name; | 31 ngx_str_t name; |
39 ngx_str_t value; | 32 ngx_str_t value; |
40 } ngx_http_ssi_var_t; | 33 } ngx_http_ssi_var_t; |
41 | |
42 | |
43 typedef struct { | |
44 ngx_buf_t *buf; | |
45 | |
46 u_char *pos; | |
47 u_char *copy_start; | |
48 u_char *copy_end; | |
49 | |
50 ngx_str_t command; | |
51 ngx_array_t params; | |
52 ngx_table_elt_t *param; | |
53 ngx_table_elt_t params_array[NGX_HTTP_SSI_PARAMS_N]; | |
54 | |
55 ngx_chain_t *in; | |
56 ngx_chain_t *out; | |
57 ngx_chain_t **last_out; | |
58 ngx_chain_t *busy; | |
59 ngx_chain_t *free; | |
60 | |
61 ngx_uint_t state; | |
62 ngx_uint_t saved_state; | |
63 size_t saved; | |
64 size_t looked; | |
65 | |
66 size_t value_len; | |
67 | |
68 ngx_array_t variables; | |
69 | |
70 ngx_uint_t output; /* unsigned output:1; */ | |
71 | |
72 ngx_str_t timefmt; | |
73 ngx_str_t errmsg; | |
74 } ngx_http_ssi_ctx_t; | |
75 | |
76 | |
77 typedef ngx_int_t (*ngx_http_ssi_command_pt) (ngx_http_request_t *r, | |
78 ngx_http_ssi_ctx_t *ctx, ngx_str_t **); | |
79 | |
80 | |
81 typedef struct { | |
82 ngx_str_t name; | |
83 ngx_uint_t index; | |
84 | |
85 ngx_uint_t mandatory; | |
86 } ngx_http_ssi_param_t; | |
87 | |
88 | |
89 typedef struct { | |
90 ngx_str_t name; | |
91 ngx_http_ssi_command_pt handler; | |
92 ngx_http_ssi_param_t *params; | |
93 | |
94 unsigned conditional:1; | |
95 unsigned flush:1; | |
96 } ngx_http_ssi_command_t; | |
97 | 34 |
98 | 35 |
99 typedef enum { | 36 typedef enum { |
100 ssi_start_state = 0, | 37 ssi_start_state = 0, |
101 ssi_tag_state, | 38 ssi_tag_state, |
147 static ngx_int_t ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, | 84 static ngx_int_t ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, |
148 ngx_http_variable_value_t *v, uintptr_t gmt); | 85 ngx_http_variable_value_t *v, uintptr_t gmt); |
149 | 86 |
150 static char *ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 87 static char *ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
151 | 88 |
152 static ngx_int_t ngx_http_ssi_add_variables(ngx_conf_t *cf); | 89 static ngx_int_t ngx_http_ssi_preconfiguration(ngx_conf_t *cf); |
90 static void *ngx_http_ssi_create_main_conf(ngx_conf_t *cf); | |
91 static char *ngx_http_ssi_init_main_conf(ngx_conf_t *cf, void *conf); | |
153 static void *ngx_http_ssi_create_conf(ngx_conf_t *cf); | 92 static void *ngx_http_ssi_create_conf(ngx_conf_t *cf); |
154 static char *ngx_http_ssi_merge_conf(ngx_conf_t *cf, | 93 static char *ngx_http_ssi_merge_conf(ngx_conf_t *cf, |
155 void *parent, void *child); | 94 void *parent, void *child); |
156 static ngx_int_t ngx_http_ssi_filter_init(ngx_cycle_t *cycle); | 95 static ngx_int_t ngx_http_ssi_filter_init(ngx_cycle_t *cycle); |
157 | 96 |
160 | 99 |
161 { ngx_string("ssi"), | 100 { ngx_string("ssi"), |
162 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | 101 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
163 ngx_conf_set_flag_slot, | 102 ngx_conf_set_flag_slot, |
164 NGX_HTTP_LOC_CONF_OFFSET, | 103 NGX_HTTP_LOC_CONF_OFFSET, |
165 offsetof(ngx_http_ssi_conf_t, enable), | 104 offsetof(ngx_http_ssi_loc_conf_t, enable), |
166 NULL }, | 105 NULL }, |
167 | 106 |
168 { ngx_string("ssi_silent_errors"), | 107 { ngx_string("ssi_silent_errors"), |
169 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | 108 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
170 ngx_conf_set_flag_slot, | 109 ngx_conf_set_flag_slot, |
171 NGX_HTTP_LOC_CONF_OFFSET, | 110 NGX_HTTP_LOC_CONF_OFFSET, |
172 offsetof(ngx_http_ssi_conf_t, silent_errors), | 111 offsetof(ngx_http_ssi_loc_conf_t, silent_errors), |
173 NULL }, | 112 NULL }, |
174 | 113 |
175 { ngx_string("ssi_ignore_recycled_buffers"), | 114 { ngx_string("ssi_ignore_recycled_buffers"), |
176 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | 115 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
177 ngx_conf_set_flag_slot, | 116 ngx_conf_set_flag_slot, |
178 NGX_HTTP_LOC_CONF_OFFSET, | 117 NGX_HTTP_LOC_CONF_OFFSET, |
179 offsetof(ngx_http_ssi_conf_t, ignore_recycled_buffers), | 118 offsetof(ngx_http_ssi_loc_conf_t, ignore_recycled_buffers), |
180 NULL }, | 119 NULL }, |
181 | 120 |
182 { ngx_string("ssi_min_file_chunk"), | 121 { ngx_string("ssi_min_file_chunk"), |
183 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | 122 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
184 ngx_conf_set_size_slot, | 123 ngx_conf_set_size_slot, |
185 NGX_HTTP_LOC_CONF_OFFSET, | 124 NGX_HTTP_LOC_CONF_OFFSET, |
186 offsetof(ngx_http_ssi_conf_t, min_file_chunk), | 125 offsetof(ngx_http_ssi_loc_conf_t, min_file_chunk), |
187 NULL }, | 126 NULL }, |
188 | 127 |
189 { ngx_string("ssi_value_length"), | 128 { ngx_string("ssi_value_length"), |
190 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | 129 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
191 ngx_conf_set_size_slot, | 130 ngx_conf_set_size_slot, |
192 NGX_HTTP_LOC_CONF_OFFSET, | 131 NGX_HTTP_LOC_CONF_OFFSET, |
193 offsetof(ngx_http_ssi_conf_t, value_len), | 132 offsetof(ngx_http_ssi_loc_conf_t, value_len), |
194 NULL }, | 133 NULL }, |
195 | 134 |
196 { ngx_string("ssi_types"), | 135 { ngx_string("ssi_types"), |
197 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | 136 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
198 ngx_http_ssi_types, | 137 ngx_http_ssi_types, |
204 }; | 143 }; |
205 | 144 |
206 | 145 |
207 | 146 |
208 static ngx_http_module_t ngx_http_ssi_filter_module_ctx = { | 147 static ngx_http_module_t ngx_http_ssi_filter_module_ctx = { |
209 ngx_http_ssi_add_variables, /* preconfiguration */ | 148 ngx_http_ssi_preconfiguration, /* preconfiguration */ |
210 NULL, /* postconfiguration */ | 149 NULL, /* postconfiguration */ |
211 | 150 |
212 NULL, /* create main configuration */ | 151 ngx_http_ssi_create_main_conf, /* create main configuration */ |
213 NULL, /* init main configuration */ | 152 ngx_http_ssi_init_main_conf, /* init main configuration */ |
214 | 153 |
215 NULL, /* create server configuration */ | 154 NULL, /* create server configuration */ |
216 NULL, /* merge server configuration */ | 155 NULL, /* merge server configuration */ |
217 | 156 |
218 ngx_http_ssi_create_conf, /* create location configuration */ | 157 ngx_http_ssi_create_conf, /* create location configuration */ |
258 | 197 |
259 #define NGX_HTTP_SSI_IF_EXPR 0 | 198 #define NGX_HTTP_SSI_IF_EXPR 0 |
260 | 199 |
261 | 200 |
262 static ngx_http_ssi_param_t ngx_http_ssi_include_params[] = { | 201 static ngx_http_ssi_param_t ngx_http_ssi_include_params[] = { |
263 { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0 }, | 202 { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0, 0 }, |
264 { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0 }, | 203 { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0, 0 }, |
265 { ngx_null_string, 0, 0 } | 204 { ngx_null_string, 0, 0, 0 } |
266 }; | 205 }; |
267 | 206 |
268 | 207 |
269 static ngx_http_ssi_param_t ngx_http_ssi_echo_params[] = { | 208 static ngx_http_ssi_param_t ngx_http_ssi_echo_params[] = { |
270 { ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1 }, | 209 { ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1, 0 }, |
271 { ngx_string("default"), NGX_HTTP_SSI_ECHO_DEFAULT, 0 }, | 210 { ngx_string("default"), NGX_HTTP_SSI_ECHO_DEFAULT, 0, 0 }, |
272 { ngx_null_string, 0, 0 } | 211 { ngx_null_string, 0, 0, 0 } |
273 }; | 212 }; |
274 | 213 |
275 | 214 |
276 static ngx_http_ssi_param_t ngx_http_ssi_config_params[] = { | 215 static ngx_http_ssi_param_t ngx_http_ssi_config_params[] = { |
277 { ngx_string("errmsg"), NGX_HTTP_SSI_CONFIG_ERRMSG, 0 }, | 216 { ngx_string("errmsg"), NGX_HTTP_SSI_CONFIG_ERRMSG, 0, 0 }, |
278 { ngx_string("timefmt"), NGX_HTTP_SSI_CONFIG_TIMEFMT, 0 }, | 217 { ngx_string("timefmt"), NGX_HTTP_SSI_CONFIG_TIMEFMT, 0, 0 }, |
279 { ngx_null_string, 0, 0 } | 218 { ngx_null_string, 0, 0, 0 } |
280 }; | 219 }; |
281 | 220 |
282 | 221 |
283 static ngx_http_ssi_param_t ngx_http_ssi_set_params[] = { | 222 static ngx_http_ssi_param_t ngx_http_ssi_set_params[] = { |
284 { ngx_string("var"), NGX_HTTP_SSI_SET_VAR, 1 }, | 223 { ngx_string("var"), NGX_HTTP_SSI_SET_VAR, 1, 0 }, |
285 { ngx_string("value"), NGX_HTTP_SSI_SET_VALUE, 1 }, | 224 { ngx_string("value"), NGX_HTTP_SSI_SET_VALUE, 1, 0 }, |
286 { ngx_null_string, 0, 0 } | 225 { ngx_null_string, 0, 0, 0 } |
287 }; | 226 }; |
288 | 227 |
289 | 228 |
290 static ngx_http_ssi_param_t ngx_http_ssi_if_params[] = { | 229 static ngx_http_ssi_param_t ngx_http_ssi_if_params[] = { |
291 { ngx_string("expr"), NGX_HTTP_SSI_IF_EXPR, 1 }, | 230 { ngx_string("expr"), NGX_HTTP_SSI_IF_EXPR, 1, 0 }, |
292 { ngx_null_string, 0, 0 } | 231 { ngx_null_string, 0, 0, 0 } |
293 }; | 232 }; |
294 | 233 |
295 | 234 |
296 static ngx_http_ssi_param_t ngx_http_ssi_no_params[] = { | 235 static ngx_http_ssi_param_t ngx_http_ssi_no_params[] = { |
297 { ngx_null_string, 0, 0 } | 236 { ngx_null_string, 0, 0, 0 } |
298 }; | 237 }; |
299 | 238 |
300 | 239 |
301 static ngx_http_ssi_command_t ngx_http_ssi_commands[] = { | 240 static ngx_http_ssi_command_t ngx_http_ssi_commands[] = { |
302 { ngx_string("include"), ngx_http_ssi_include, | 241 { ngx_string("include"), ngx_http_ssi_include, |
328 | 267 |
329 | 268 |
330 static ngx_int_t | 269 static ngx_int_t |
331 ngx_http_ssi_header_filter(ngx_http_request_t *r) | 270 ngx_http_ssi_header_filter(ngx_http_request_t *r) |
332 { | 271 { |
333 ngx_uint_t i; | 272 ngx_uint_t i; |
334 ngx_str_t *type; | 273 ngx_str_t *type; |
335 ngx_http_ssi_ctx_t *ctx; | 274 ngx_http_ssi_ctx_t *ctx; |
336 ngx_http_ssi_conf_t *conf; | 275 ngx_http_ssi_loc_conf_t *slcf; |
337 | 276 |
338 conf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); | 277 slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); |
339 | 278 |
340 if (!conf->enable | 279 if (!slcf->enable |
341 || r->headers_out.content_type.len == 0 | 280 || r->headers_out.content_type.len == 0 |
342 || r->headers_out.content_length_n == 0) | 281 || r->headers_out.content_length_n == 0) |
343 { | 282 { |
344 return ngx_http_next_header_filter(r); | 283 return ngx_http_next_header_filter(r); |
345 } | 284 } |
346 | 285 |
347 | 286 |
348 type = conf->types->elts; | 287 type = slcf->types->elts; |
349 for (i = 0; i < conf->types->nelts; i++) { | 288 for (i = 0; i < slcf->types->nelts; i++) { |
350 if (r->headers_out.content_type.len >= type[i].len | 289 if (r->headers_out.content_type.len >= type[i].len |
351 && ngx_strncasecmp(r->headers_out.content_type.data, | 290 && ngx_strncasecmp(r->headers_out.content_type.data, |
352 type[i].data, type[i].len) == 0) | 291 type[i].data, type[i].len) == 0) |
353 { | 292 { |
354 goto found; | 293 goto found; |
366 } | 305 } |
367 | 306 |
368 ngx_http_set_ctx(r, ctx, ngx_http_ssi_filter_module); | 307 ngx_http_set_ctx(r, ctx, ngx_http_ssi_filter_module); |
369 | 308 |
370 | 309 |
371 ctx->value_len = conf->value_len; | 310 ctx->value_len = slcf->value_len; |
372 ctx->last_out = &ctx->out; | 311 ctx->last_out = &ctx->out; |
373 | 312 |
374 ctx->output = 1; | 313 ctx->output = 1; |
375 | 314 |
376 ctx->params.elts = ctx->params_array; | 315 ctx->params.elts = ctx->params_array; |
386 ctx->errmsg.data = (u_char *) | 325 ctx->errmsg.data = (u_char *) |
387 "[an error occurred while processing the directive]"; | 326 "[an error occurred while processing the directive]"; |
388 | 327 |
389 r->filter_need_in_memory = 1; | 328 r->filter_need_in_memory = 1; |
390 | 329 |
391 if (r->main == r) { | 330 if (r == r->main) { |
392 ngx_http_clear_content_length(r); | 331 ngx_http_clear_content_length(r); |
393 ngx_http_clear_last_modified(r); | 332 ngx_http_clear_last_modified(r); |
394 } | 333 } |
395 | 334 |
396 return ngx_http_next_header_filter(r); | 335 return ngx_http_next_header_filter(r); |
398 | 337 |
399 | 338 |
400 static ngx_int_t | 339 static ngx_int_t |
401 ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | 340 ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in) |
402 { | 341 { |
403 ngx_int_t rc; | 342 ngx_int_t rc; |
404 ngx_uint_t i; | 343 ngx_buf_t *b; |
405 ngx_buf_t *b; | 344 ngx_uint_t i, index; |
406 ngx_chain_t *cl; | 345 ngx_chain_t *cl; |
407 ngx_table_elt_t *param; | 346 ngx_table_elt_t *param; |
408 ngx_connection_t *c; | 347 ngx_connection_t *c; |
409 ngx_http_ssi_ctx_t *ctx; | 348 ngx_http_ssi_ctx_t *ctx; |
410 ngx_http_ssi_conf_t *conf; | 349 ngx_http_ssi_param_t *prm; |
411 ngx_http_ssi_param_t *prm; | 350 ngx_http_ssi_command_t *cmd; |
412 ngx_http_ssi_command_t *cmd; | 351 ngx_http_ssi_loc_conf_t *slcf; |
413 ngx_str_t *params[NGX_HTTP_SSI_MAX_PARAMS]; | 352 ngx_http_ssi_main_conf_t *smcf; |
353 ngx_str_t *params[NGX_HTTP_SSI_MAX_PARAMS]; | |
414 | 354 |
415 ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module); | 355 ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module); |
416 | 356 |
417 if (ctx == NULL || (in == NULL && ctx->in == NULL && ctx->busy == NULL)) { | 357 if (ctx == NULL || (in == NULL && ctx->in == NULL && ctx->busy == NULL)) { |
418 return ngx_http_next_body_filter(r, in); | 358 return ngx_http_next_body_filter(r, in); |
424 if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) { | 364 if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) { |
425 return NGX_ERROR; | 365 return NGX_ERROR; |
426 } | 366 } |
427 } | 367 } |
428 | 368 |
429 conf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); | 369 slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); |
430 | 370 |
431 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 371 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
432 "http ssi filter \"%V\"", &r->uri); | 372 "http ssi filter \"%V\"", &r->uri); |
433 | 373 |
434 while (ctx->in || ctx->buf) { | 374 while (ctx->in || ctx->buf) { |
526 b->shadow = NULL; | 466 b->shadow = NULL; |
527 b->last_buf = 0; | 467 b->last_buf = 0; |
528 b->recycled = 0; | 468 b->recycled = 0; |
529 | 469 |
530 if (b->in_file) { | 470 if (b->in_file) { |
531 if (conf->min_file_chunk < (size_t) (b->last - b->pos)) | 471 if (slcf->min_file_chunk < (size_t) (b->last - b->pos)) |
532 { | 472 { |
533 b->file_last = b->file_pos + (b->last - b->start); | 473 b->file_last = b->file_pos + (b->last - b->start); |
534 b->file_pos += b->pos - b->start; | 474 b->file_pos += b->pos - b->start; |
535 | 475 |
536 } else { | 476 } else { |
563 | 503 |
564 b = NULL; | 504 b = NULL; |
565 | 505 |
566 if (rc == NGX_OK) { | 506 if (rc == NGX_OK) { |
567 | 507 |
568 for (cmd = ngx_http_ssi_commands; cmd->handler; cmd++) { | 508 smcf = ngx_http_get_module_main_conf(r, |
569 if (cmd->name.len == 0) { | 509 ngx_http_ssi_filter_module); |
570 cmd = (ngx_http_ssi_command_t *) cmd->handler; | 510 |
511 cmd = ngx_hash_find(&smcf->hash, ctx->key, ctx->command.data, | |
512 ctx->command.len); | |
513 | |
514 if (cmd == NULL) { | |
515 if (ctx->output) { | |
516 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
517 "invalid SSI command: \"%V\"", | |
518 &ctx->command); | |
519 goto ssi_error; | |
571 } | 520 } |
572 | 521 |
573 if (cmd->name.len != ctx->command.len | 522 continue; |
574 || ngx_strncmp(cmd->name.data, ctx->command.data, | |
575 ctx->command.len) != 0) | |
576 { | |
577 continue; | |
578 } | |
579 | |
580 break; | |
581 } | |
582 | |
583 if (cmd->name.len == 0 && ctx->output) { | |
584 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
585 "invalid SSI command: \"%V\"", &ctx->command); | |
586 goto ssi_error; | |
587 } | 523 } |
588 | 524 |
589 if (!ctx->output && !cmd->conditional) { | 525 if (!ctx->output && !cmd->conditional) { |
590 continue; | 526 continue; |
591 } | 527 } |
592 | 528 |
529 if (ctx->params.nelts > NGX_HTTP_SSI_MAX_PARAMS) { | |
530 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
531 "too many SSI command paramters: \"%V\"", | |
532 &ctx->command); | |
533 goto ssi_error; | |
534 } | |
535 | |
593 ngx_memzero(params, | 536 ngx_memzero(params, |
594 NGX_HTTP_SSI_MAX_PARAMS * sizeof(ngx_str_t *)); | 537 NGX_HTTP_SSI_MAX_PARAMS * sizeof(ngx_str_t *)); |
595 | 538 |
596 param = ctx->params.elts; | 539 param = ctx->params.elts; |
597 | |
598 | 540 |
599 for (i = 0; i < ctx->params.nelts; i++) { | 541 for (i = 0; i < ctx->params.nelts; i++) { |
600 | 542 |
601 for (prm = cmd->params; prm->name.len; prm++) { | 543 for (prm = cmd->params; prm->name.len; prm++) { |
602 | 544 |
605 prm->name.len) != 0) | 547 prm->name.len) != 0) |
606 { | 548 { |
607 continue; | 549 continue; |
608 } | 550 } |
609 | 551 |
610 if (params[prm->index]) { | 552 if (!prm->multiple) { |
611 ngx_log_error(NGX_LOG_ERR, | 553 if (params[prm->index]) { |
612 r->connection->log, 0, | 554 ngx_log_error(NGX_LOG_ERR, |
613 "duplicate \"%V\" parameter " | 555 r->connection->log, 0, |
614 "in \"%V\" SSI command", | 556 "duplicate \"%V\" parameter " |
615 ¶m[i].key, &ctx->command); | 557 "in \"%V\" SSI command", |
616 | 558 ¶m[i].key, &ctx->command); |
617 goto ssi_error; | 559 |
560 goto ssi_error; | |
561 } | |
562 | |
563 params[prm->index] = ¶m[i].value; | |
564 | |
565 break; | |
618 } | 566 } |
619 | 567 |
620 params[prm->index] = ¶m[i].value; | 568 for (index = prm->index; params[index]; index++) { |
569 /* void */ | |
570 } | |
571 | |
572 params[index] = ¶m[i].value; | |
621 | 573 |
622 break; | 574 break; |
623 } | 575 } |
624 | 576 |
625 if (prm->name.len == 0) { | 577 if (prm->name.len == 0) { |
671 | 623 |
672 /* rc == NGX_HTTP_SSI_ERROR */ | 624 /* rc == NGX_HTTP_SSI_ERROR */ |
673 | 625 |
674 ssi_error: | 626 ssi_error: |
675 | 627 |
676 if (conf->silent_errors) { | 628 if (slcf->silent_errors) { |
677 continue; | 629 continue; |
678 } | 630 } |
679 | 631 |
680 if (ctx->free) { | 632 if (ctx->free) { |
681 cl = ctx->free; | 633 cl = ctx->free; |
707 | 659 |
708 continue; | 660 continue; |
709 } | 661 } |
710 | 662 |
711 if (ctx->buf->last_buf || ctx->buf->recycled) { | 663 if (ctx->buf->last_buf || ctx->buf->recycled) { |
712 | |
713 if (b == NULL) { | 664 if (b == NULL) { |
714 if (ctx->free) { | 665 if (ctx->free) { |
715 cl = ctx->free; | 666 cl = ctx->free; |
716 ctx->free = ctx->free->next; | 667 ctx->free = ctx->free->next; |
717 b = cl->buf; | 668 b = cl->buf; |
739 } | 690 } |
740 | 691 |
741 b->last_buf = ctx->buf->last_buf; | 692 b->last_buf = ctx->buf->last_buf; |
742 b->shadow = ctx->buf; | 693 b->shadow = ctx->buf; |
743 | 694 |
744 if (conf->ignore_recycled_buffers == 0) { | 695 if (slcf->ignore_recycled_buffers == 0) { |
745 b->recycled = ctx->buf->recycled; | 696 b->recycled = ctx->buf->recycled; |
746 } | 697 } |
747 } | 698 } |
748 | 699 |
749 ctx->buf = NULL; | 700 ctx->buf = NULL; |
967 if (ctx->command.data == NULL) { | 918 if (ctx->command.data == NULL) { |
968 return NGX_ERROR; | 919 return NGX_ERROR; |
969 } | 920 } |
970 | 921 |
971 ctx->command.data[0] = ch; | 922 ctx->command.data[0] = ch; |
923 ctx->key = 0; | |
924 ctx->key = ngx_hash(ctx->key, ch); | |
925 | |
972 ctx->params.nelts = 0; | 926 ctx->params.nelts = 0; |
973 state = ssi_command_state; | 927 state = ssi_command_state; |
974 break; | 928 break; |
975 } | 929 } |
976 | 930 |
989 state = ssi_comment_end0_state; | 943 state = ssi_comment_end0_state; |
990 break; | 944 break; |
991 | 945 |
992 default: | 946 default: |
993 ctx->command.data[ctx->command.len++] = ch; | 947 ctx->command.data[ctx->command.len++] = ch; |
948 ctx->key = ngx_hash(ctx->key, ch); | |
994 | 949 |
995 if (ctx->command.len == NGX_HTTP_SSI_COMMAND_LEN) { | 950 if (ctx->command.len == NGX_HTTP_SSI_COMMAND_LEN) { |
996 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 951 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
997 "the \"%V\" SSI command is too long", | 952 "the \"%V\" SSI command is too long", |
998 &ctx->command); | 953 &ctx->command); |
2037 | 1992 |
2038 | 1993 |
2039 static char * | 1994 static char * |
2040 ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 1995 ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
2041 { | 1996 { |
2042 ngx_http_ssi_conf_t *scf = conf; | 1997 ngx_http_ssi_loc_conf_t *slcf = conf; |
2043 | 1998 |
2044 ngx_str_t *value, *type; | 1999 ngx_str_t *value, *type; |
2045 ngx_uint_t i; | 2000 ngx_uint_t i; |
2046 | 2001 |
2047 if (scf->types == NULL) { | 2002 if (slcf->types == NULL) { |
2048 scf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); | 2003 slcf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); |
2049 if (scf->types == NULL) { | 2004 if (slcf->types == NULL) { |
2050 return NGX_CONF_ERROR; | 2005 return NGX_CONF_ERROR; |
2051 } | 2006 } |
2052 | 2007 |
2053 type = ngx_array_push(scf->types); | 2008 type = ngx_array_push(slcf->types); |
2054 if (type == NULL) { | 2009 if (type == NULL) { |
2055 return NGX_CONF_ERROR; | 2010 return NGX_CONF_ERROR; |
2056 } | 2011 } |
2057 | 2012 |
2058 type->len = sizeof("text/html") - 1; | 2013 type->len = sizeof("text/html") - 1; |
2065 | 2020 |
2066 if (ngx_strcmp(value[i].data, "text/html") == 0) { | 2021 if (ngx_strcmp(value[i].data, "text/html") == 0) { |
2067 continue; | 2022 continue; |
2068 } | 2023 } |
2069 | 2024 |
2070 type = ngx_array_push(scf->types); | 2025 type = ngx_array_push(slcf->types); |
2071 if (type == NULL) { | 2026 if (type == NULL) { |
2072 return NGX_CONF_ERROR; | 2027 return NGX_CONF_ERROR; |
2073 } | 2028 } |
2074 | 2029 |
2075 type->len = value[i].len; | 2030 type->len = value[i].len; |
2085 return NGX_CONF_OK; | 2040 return NGX_CONF_OK; |
2086 } | 2041 } |
2087 | 2042 |
2088 | 2043 |
2089 static ngx_int_t | 2044 static ngx_int_t |
2090 ngx_http_ssi_add_variables(ngx_conf_t *cf) | 2045 ngx_http_ssi_preconfiguration(ngx_conf_t *cf) |
2091 { | 2046 { |
2092 ngx_http_variable_t *var, *v; | 2047 ngx_int_t rc; |
2048 ngx_http_variable_t *var, *v; | |
2049 ngx_http_ssi_command_t *cmd; | |
2050 ngx_http_ssi_main_conf_t *smcf; | |
2093 | 2051 |
2094 for (v = ngx_http_ssi_vars; v->name.len; v++) { | 2052 for (v = ngx_http_ssi_vars; v->name.len; v++) { |
2095 var = ngx_http_add_variable(cf, &v->name, v->flags); | 2053 var = ngx_http_add_variable(cf, &v->name, v->flags); |
2096 if (var == NULL) { | 2054 if (var == NULL) { |
2097 return NGX_ERROR; | 2055 return NGX_ERROR; |
2099 | 2057 |
2100 var->handler = v->handler; | 2058 var->handler = v->handler; |
2101 var->data = v->data; | 2059 var->data = v->data; |
2102 } | 2060 } |
2103 | 2061 |
2062 smcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_ssi_filter_module); | |
2063 | |
2064 for (cmd = ngx_http_ssi_commands; cmd->name.len; cmd++) { | |
2065 rc = ngx_hash_add_key(&smcf->commands, &cmd->name, cmd, | |
2066 NGX_HASH_READONLY_KEY); | |
2067 | |
2068 if (rc == NGX_OK) { | |
2069 continue; | |
2070 } | |
2071 | |
2072 if (rc == NGX_BUSY) { | |
2073 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
2074 "conflicting SSI command \"%V\"", &cmd->name); | |
2075 } | |
2076 | |
2077 return NGX_ERROR; | |
2078 } | |
2079 | |
2104 return NGX_OK; | 2080 return NGX_OK; |
2081 } | |
2082 | |
2083 | |
2084 static void * | |
2085 ngx_http_ssi_create_main_conf(ngx_conf_t *cf) | |
2086 { | |
2087 ngx_http_ssi_main_conf_t *smcf; | |
2088 | |
2089 smcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_main_conf_t)); | |
2090 if (smcf == NULL) { | |
2091 return NGX_CONF_ERROR; | |
2092 } | |
2093 | |
2094 smcf->commands.pool = cf->pool; | |
2095 smcf->commands.temp_pool = cf->temp_pool; | |
2096 | |
2097 if (ngx_hash_keys_array_init(&smcf->commands, NGX_HASH_SMALL) != NGX_OK) { | |
2098 return NGX_CONF_ERROR; | |
2099 } | |
2100 | |
2101 return smcf; | |
2102 } | |
2103 | |
2104 | |
2105 static char * | |
2106 ngx_http_ssi_init_main_conf(ngx_conf_t *cf, void *conf) | |
2107 { | |
2108 ngx_http_ssi_main_conf_t *smcf = conf; | |
2109 | |
2110 ngx_hash_init_t hash; | |
2111 | |
2112 hash.hash = &smcf->hash; | |
2113 hash.key = ngx_hash_key; | |
2114 hash.max_size = 1024; | |
2115 hash.bucket_size = ngx_cacheline_size; | |
2116 hash.name = "ssi_command_hash"; | |
2117 hash.pool = cf->pool; | |
2118 hash.temp_pool = NULL; | |
2119 | |
2120 if (ngx_hash_init(&hash, smcf->commands.keys.elts, | |
2121 smcf->commands.keys.nelts) | |
2122 != NGX_OK) | |
2123 { | |
2124 return NGX_CONF_ERROR; | |
2125 } | |
2126 | |
2127 return NGX_CONF_OK; | |
2105 } | 2128 } |
2106 | 2129 |
2107 | 2130 |
2108 static void * | 2131 static void * |
2109 ngx_http_ssi_create_conf(ngx_conf_t *cf) | 2132 ngx_http_ssi_create_conf(ngx_conf_t *cf) |
2110 { | 2133 { |
2111 ngx_http_ssi_conf_t *conf; | 2134 ngx_http_ssi_loc_conf_t *slcf; |
2112 | 2135 |
2113 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_conf_t)); | 2136 slcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_loc_conf_t)); |
2114 if (conf == NULL) { | 2137 if (slcf == NULL) { |
2115 return NGX_CONF_ERROR; | 2138 return NGX_CONF_ERROR; |
2116 } | 2139 } |
2117 | 2140 |
2118 /* | 2141 /* |
2119 * set by ngx_pcalloc(): | 2142 * set by ngx_pcalloc(): |
2120 * | 2143 * |
2121 * conf->types = NULL; | 2144 * conf->types = NULL; |
2122 */ | 2145 */ |
2123 | 2146 |
2124 conf->enable = NGX_CONF_UNSET; | 2147 slcf->enable = NGX_CONF_UNSET; |
2125 conf->silent_errors = NGX_CONF_UNSET; | 2148 slcf->silent_errors = NGX_CONF_UNSET; |
2126 conf->ignore_recycled_buffers = NGX_CONF_UNSET; | 2149 slcf->ignore_recycled_buffers = NGX_CONF_UNSET; |
2127 | 2150 |
2128 conf->min_file_chunk = NGX_CONF_UNSET_SIZE; | 2151 slcf->min_file_chunk = NGX_CONF_UNSET_SIZE; |
2129 conf->value_len = NGX_CONF_UNSET_SIZE; | 2152 slcf->value_len = NGX_CONF_UNSET_SIZE; |
2130 | 2153 |
2131 return conf; | 2154 return slcf; |
2132 } | 2155 } |
2133 | 2156 |
2134 | 2157 |
2135 static char * | 2158 static char * |
2136 ngx_http_ssi_merge_conf(ngx_conf_t *cf, void *parent, void *child) | 2159 ngx_http_ssi_merge_conf(ngx_conf_t *cf, void *parent, void *child) |
2137 { | 2160 { |
2138 ngx_http_ssi_conf_t *prev = parent; | 2161 ngx_http_ssi_loc_conf_t *prev = parent; |
2139 ngx_http_ssi_conf_t *conf = child; | 2162 ngx_http_ssi_loc_conf_t *conf = child; |
2140 | 2163 |
2141 ngx_str_t *type; | 2164 ngx_str_t *type; |
2142 | 2165 |
2143 ngx_conf_merge_value(conf->enable, prev->enable, 0); | 2166 ngx_conf_merge_value(conf->enable, prev->enable, 0); |
2144 ngx_conf_merge_value(conf->silent_errors, prev->silent_errors, 0); | 2167 ngx_conf_merge_value(conf->silent_errors, prev->silent_errors, 0); |