📄 ngx_http_ssi_filter_module.c
字号:
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_http.h>#define NGX_HTTP_SSI_ERROR 1#define NGX_HTTP_SSI_DATE_LEN 2048#define NGX_HTTP_SSI_ADD_PREFIX 1#define NGX_HTTP_SSI_ADD_ZERO 2#define NGX_HTTP_SSI_EXPR_TEST 4typedef struct { ngx_flag_t enable; ngx_flag_t silent_errors; ngx_flag_t ignore_recycled_buffers; ngx_array_t *types; /* array of ngx_str_t */ size_t min_file_chunk; size_t value_len;} ngx_http_ssi_loc_conf_t;typedef struct { ngx_str_t name; ngx_uint_t key; ngx_str_t value;} ngx_http_ssi_var_t;typedef struct { ngx_str_t name; ngx_chain_t *bufs; ngx_uint_t count;} ngx_http_ssi_block_t;typedef enum { ssi_start_state = 0, ssi_tag_state, ssi_comment0_state, ssi_comment1_state, ssi_sharp_state, ssi_precommand_state, ssi_command_state, ssi_preparam_state, ssi_param_state, ssi_preequal_state, ssi_prevalue_state, ssi_double_quoted_value_state, ssi_quoted_value_state, ssi_quoted_symbol_state, ssi_postparam_state, ssi_comment_end0_state, ssi_comment_end1_state, ssi_error_state, ssi_error_end0_state, ssi_error_end1_state} ngx_http_ssi_state_e;static ngx_int_t ngx_http_ssi_output(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx);static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx);static ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key);static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags);static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);static ngx_int_t ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data, ngx_int_t rc);static ngx_int_t ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data, ngx_int_t rc);static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);static ngx_int_t ngx_http_ssi_config(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);static ngx_int_t ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);static ngx_int_t ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);static ngx_int_t ngx_http_ssi_else(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);static ngx_int_t ngx_http_ssi_endif(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);static ngx_int_t ngx_http_ssi_block(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);static ngx_int_t ngx_http_ssi_endblock(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);static ngx_int_t ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t gmt);static char *ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static ngx_int_t ngx_http_ssi_preconfiguration(ngx_conf_t *cf);static void *ngx_http_ssi_create_main_conf(ngx_conf_t *cf);static char *ngx_http_ssi_init_main_conf(ngx_conf_t *cf, void *conf);static void *ngx_http_ssi_create_loc_conf(ngx_conf_t *cf);static char *ngx_http_ssi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);static ngx_int_t ngx_http_ssi_filter_init(ngx_conf_t *cf);static ngx_command_t ngx_http_ssi_filter_commands[] = { { ngx_string("ssi"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_FLAG, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_ssi_loc_conf_t, enable), NULL }, { ngx_string("ssi_silent_errors"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_ssi_loc_conf_t, silent_errors), NULL }, { ngx_string("ssi_ignore_recycled_buffers"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_ssi_loc_conf_t, ignore_recycled_buffers), NULL }, { ngx_string("ssi_min_file_chunk"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_size_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_ssi_loc_conf_t, min_file_chunk), NULL }, { ngx_string("ssi_value_length"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_size_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_ssi_loc_conf_t, value_len), NULL }, { ngx_string("ssi_types"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_http_ssi_types, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL }, ngx_null_command};static ngx_http_module_t ngx_http_ssi_filter_module_ctx = { ngx_http_ssi_preconfiguration, /* preconfiguration */ ngx_http_ssi_filter_init, /* postconfiguration */ ngx_http_ssi_create_main_conf, /* create main configuration */ ngx_http_ssi_init_main_conf, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ ngx_http_ssi_create_loc_conf, /* create location configuration */ ngx_http_ssi_merge_loc_conf /* merge location configuration */};ngx_module_t ngx_http_ssi_filter_module = { NGX_MODULE_V1, &ngx_http_ssi_filter_module_ctx, /* module context */ ngx_http_ssi_filter_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING};static ngx_http_output_header_filter_pt ngx_http_next_header_filter;static ngx_http_output_body_filter_pt ngx_http_next_body_filter;static u_char ngx_http_ssi_string[] = "<!--";static ngx_str_t ngx_http_ssi_none = ngx_string("(none)");static ngx_str_t ngx_http_ssi_null_string = ngx_null_string;#define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0#define NGX_HTTP_SSI_INCLUDE_FILE 1#define NGX_HTTP_SSI_INCLUDE_WAIT 2#define NGX_HTTP_SSI_INCLUDE_SET 3#define NGX_HTTP_SSI_INCLUDE_STUB 4#define NGX_HTTP_SSI_ECHO_VAR 0#define NGX_HTTP_SSI_ECHO_DEFAULT 1#define NGX_HTTP_SSI_ECHO_ENCODING 2#define NGX_HTTP_SSI_CONFIG_ERRMSG 0#define NGX_HTTP_SSI_CONFIG_TIMEFMT 1#define NGX_HTTP_SSI_SET_VAR 0#define NGX_HTTP_SSI_SET_VALUE 1#define NGX_HTTP_SSI_IF_EXPR 0#define NGX_HTTP_SSI_BLOCK_NAME 0static ngx_http_ssi_param_t ngx_http_ssi_include_params[] = { { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0, 0 }, { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0, 0 }, { ngx_string("wait"), NGX_HTTP_SSI_INCLUDE_WAIT, 0, 0 }, { ngx_string("set"), NGX_HTTP_SSI_INCLUDE_SET, 0, 0 }, { ngx_string("stub"), NGX_HTTP_SSI_INCLUDE_STUB, 0, 0 }, { ngx_null_string, 0, 0, 0 }};static ngx_http_ssi_param_t ngx_http_ssi_echo_params[] = { { ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1, 0 }, { ngx_string("default"), NGX_HTTP_SSI_ECHO_DEFAULT, 0, 0 }, { ngx_string("encoding"), NGX_HTTP_SSI_ECHO_ENCODING, 0, 0 }, { ngx_null_string, 0, 0, 0 }};static ngx_http_ssi_param_t ngx_http_ssi_config_params[] = { { ngx_string("errmsg"), NGX_HTTP_SSI_CONFIG_ERRMSG, 0, 0 }, { ngx_string("timefmt"), NGX_HTTP_SSI_CONFIG_TIMEFMT, 0, 0 }, { ngx_null_string, 0, 0, 0 }};static ngx_http_ssi_param_t ngx_http_ssi_set_params[] = { { ngx_string("var"), NGX_HTTP_SSI_SET_VAR, 1, 0 }, { ngx_string("value"), NGX_HTTP_SSI_SET_VALUE, 1, 0 }, { ngx_null_string, 0, 0, 0 }};static ngx_http_ssi_param_t ngx_http_ssi_if_params[] = { { ngx_string("expr"), NGX_HTTP_SSI_IF_EXPR, 1, 0 }, { ngx_null_string, 0, 0, 0 }};static ngx_http_ssi_param_t ngx_http_ssi_block_params[] = { { ngx_string("name"), NGX_HTTP_SSI_BLOCK_NAME, 1, 0 }, { ngx_null_string, 0, 0, 0 }};static ngx_http_ssi_param_t ngx_http_ssi_no_params[] = { { ngx_null_string, 0, 0, 0 }};static ngx_http_ssi_command_t ngx_http_ssi_commands[] = { { ngx_string("include"), ngx_http_ssi_include, ngx_http_ssi_include_params, 0, 0, 1 }, { ngx_string("echo"), ngx_http_ssi_echo, ngx_http_ssi_echo_params, 0, 0, 0 }, { ngx_string("config"), ngx_http_ssi_config, ngx_http_ssi_config_params, 0, 0, 0 }, { ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0, 0 }, { ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0, 0 }, { ngx_string("elif"), ngx_http_ssi_if, ngx_http_ssi_if_params, NGX_HTTP_SSI_COND_IF, 0, 0 }, { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params, NGX_HTTP_SSI_COND_IF, 0, 0 }, { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params, NGX_HTTP_SSI_COND_ELSE, 0, 0 }, { ngx_string("block"), ngx_http_ssi_block, ngx_http_ssi_block_params, 0, 0, 0 }, { ngx_string("endblock"), ngx_http_ssi_endblock, ngx_http_ssi_no_params, 0, 1, 0 }, { ngx_null_string, NULL, NULL, 0, 0, 0 }};static ngx_http_variable_t ngx_http_ssi_vars[] = { { ngx_string("date_local"), NULL, ngx_http_ssi_date_gmt_local_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("date_gmt"), NULL, ngx_http_ssi_date_gmt_local_variable, 1, NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_null_string, NULL, NULL, 0, 0, 0 }};static ngx_int_tngx_http_ssi_header_filter(ngx_http_request_t *r){ ngx_uint_t i; ngx_str_t *type; ngx_http_ssi_ctx_t *ctx; ngx_http_ssi_loc_conf_t *slcf; slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); if (!slcf->enable || r->headers_out.content_type.len == 0 || r->headers_out.content_length_n == 0) { return ngx_http_next_header_filter(r); } type = slcf->types->elts; for (i = 0; i < slcf->types->nelts; i++) { if (r->headers_out.content_type.len >= type[i].len && ngx_strncasecmp(r->headers_out.content_type.data, type[i].data, type[i].len) == 0) { goto found; } } return ngx_http_next_header_filter(r);found: ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ssi_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_ssi_filter_module); ctx->value_len = slcf->value_len; ctx->last_out = &ctx->out; ctx->encoding = NGX_HTTP_SSI_ENTITY_ENCODING; ctx->output = 1; ctx->params.elts = ctx->params_array; ctx->params.size = sizeof(ngx_table_elt_t); ctx->params.nalloc = NGX_HTTP_SSI_PARAMS_N; ctx->params.pool = r->pool; ctx->timefmt.len = sizeof("%A, %d-%b-%Y %H:%M:%S %Z") - 1; ctx->timefmt.data = (u_char *) "%A, %d-%b-%Y %H:%M:%S %Z"; ctx->errmsg.len = sizeof("[an error occurred while processing the directive]") - 1; ctx->errmsg.data = (u_char *) "[an error occurred while processing the directive]"; r->filter_need_in_memory = 1; if (r == r->main) { ngx_http_clear_content_length(r); ngx_http_clear_last_modified(r); } return ngx_http_next_header_filter(r);}static ngx_int_tngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in){ size_t len; ngx_int_t rc; ngx_buf_t *b; ngx_uint_t i, index; ngx_chain_t *cl, **ll; ngx_table_elt_t *param; ngx_http_request_t *pr; ngx_http_ssi_ctx_t *ctx, *mctx; ngx_http_ssi_block_t *bl; ngx_http_ssi_param_t *prm; ngx_http_ssi_command_t *cmd; ngx_http_ssi_loc_conf_t *slcf; ngx_http_ssi_main_conf_t *smcf; ngx_str_t *params[NGX_HTTP_SSI_MAX_PARAMS + 1]; ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module); if (ctx == NULL || (in == NULL && ctx->buf == NULL && ctx->in == NULL && ctx->busy == NULL)) { return ngx_http_next_body_filter(r, in); } /* add the incoming chain to the chain ctx->in */ if (in) { if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) { return NGX_ERROR; } } if (ctx->wait) { if (r->connection->data != r) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http ssi filter \"%V\" wait", &r->uri); return NGX_AGAIN; } for (pr = ctx->wait->parent; pr; pr = pr->parent) { if (pr == r) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http ssi filter \"%V\" flush", &r->uri); rc = ngx_http_next_body_filter(r, NULL); if (ctx->wait->done) { ctx->wait = NULL; } if (rc == NGX_ERROR || rc == NGX_AGAIN) { return rc; } break; } } if (ctx->wait == r) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http ssi filter \"%V\" continue", &r->uri); ctx->wait = NULL; } } slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http ssi filter \"%V\"", &r->uri); while (ctx->in || ctx->buf) { if (ctx->buf == NULL ){ ctx->buf = ctx->in->buf; ctx->in = ctx->in->next; ctx->pos = ctx->buf->pos; } if (ctx->state == ssi_start_state) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -