📄 mod_include.c
字号:
/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * http_include.c: Handles the server-parsed HTML documents * * Original by Rob McCool; substantial fixups by David Robinson; * incorporated into the Apache module framework by rst. * */#include "apr.h"#include "apr_strings.h"#include "apr_thread_proc.h"#include "apr_hash.h"#include "apr_user.h"#include "apr_lib.h"#include "apr_optional.h"#define APR_WANT_STRFUNC#define APR_WANT_MEMFUNC#include "apr_want.h"#define CORE_PRIVATE#include "ap_config.h"#include "util_filter.h"#include "httpd.h"#include "http_config.h"#include "http_core.h"#include "http_request.h"#include "http_core.h"#include "http_protocol.h"#include "http_log.h"#include "http_main.h"#include "util_script.h"#include "http_core.h"#define MOD_INCLUDE_REDESIGN#include "mod_include.h"#include "util_ebcdic.h"module AP_MODULE_DECLARE_DATA include_module;static apr_hash_t *include_hash;static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *ssi_pfn_register;/***************************************************************** * * XBITHACK. Sigh... NB it's configurable per-directory; the compile-time * option only changes the default. */enum xbithack { xbithack_off, xbithack_on, xbithack_full};struct bndm_t { unsigned int T[256]; unsigned int x;} ;typedef struct { char *default_error_msg; char *default_time_fmt; enum xbithack *xbithack;} include_dir_config;typedef struct { char *default_start_tag; char *default_end_tag; int start_tag_len; bndm_t start_seq_pat; char *undefinedEcho; int undefinedEchoLen;} include_server_config;/* main parser states */typedef enum { PARSE_PRE_HEAD, PARSE_HEAD, PARSE_DIRECTIVE, PARSE_DIRECTIVE_POSTNAME, PARSE_DIRECTIVE_TAIL, PARSE_DIRECTIVE_POSTTAIL, PARSE_PRE_ARG, PARSE_ARG, PARSE_ARG_NAME, PARSE_ARG_POSTNAME, PARSE_ARG_EQ, PARSE_ARG_PREVAL, PARSE_ARG_VAL, PARSE_ARG_VAL_ESC, PARSE_ARG_POSTVAL, PARSE_TAIL, PARSE_TAIL_SEQ, PARSE_EXECUTE} parse_state_t;typedef struct ssi_arg_item { struct ssi_arg_item *next; char *name; apr_size_t name_len; char *value; apr_size_t value_len;} ssi_arg_item_t;typedef struct { parse_state_t state; int seen_eos; int error; char quote; /* quote character value (or \0) */ apr_bucket_brigade *tmp_bb; apr_size_t end_seq_len; char *directive; /* name of the current directive */ unsigned argc; /* argument counter (of the current * directive) */ ssi_arg_item_t *argv; /* all arguments */ ssi_arg_item_t *current_arg; /* currently parsed argument */ request_rec *r; include_ctx_t *ctx; /* public part of the context structure */ apr_pool_t *dpool;} ssi_ctx_t;#ifdef XBITHACK#define DEFAULT_XBITHACK xbithack_full#else#define DEFAULT_XBITHACK xbithack_off#endif#define BYTE_COUNT_THRESHOLD AP_MIN_BYTES_TO_WRITE#define SSI_CREATE_ERROR_BUCKET(ctx, f, bb) APR_BRIGADE_INSERT_TAIL((bb), \ apr_bucket_pool_create(apr_pstrdup((ctx)->pool, (ctx)->error_str), \ strlen((ctx)->error_str), (ctx)->pool, \ (f)->c->bucket_alloc))/* ------------------------ Environment function -------------------------- *//* Sentinel value to store in subprocess_env for items that * shouldn't be evaluated until/unless they're actually used */static const char lazy_eval_sentinel;#define LAZY_VALUE (&lazy_eval_sentinel)static void add_include_vars(request_rec *r, char *timefmt){ apr_table_t *e = r->subprocess_env; char *t; apr_table_setn(e, "DATE_LOCAL", LAZY_VALUE); apr_table_setn(e, "DATE_GMT", LAZY_VALUE); apr_table_setn(e, "LAST_MODIFIED", LAZY_VALUE); apr_table_setn(e, "DOCUMENT_URI", r->uri); if (r->path_info && *r->path_info) { apr_table_setn(e, "DOCUMENT_PATH_INFO", r->path_info); } apr_table_setn(e, "USER_NAME", LAZY_VALUE); if (r->filename && (t = strrchr(r->filename, '/'))) { apr_table_setn(e, "DOCUMENT_NAME", ++t); } else { apr_table_setn(e, "DOCUMENT_NAME", r->uri); } if (r->args) { char *arg_copy = apr_pstrdup(r->pool, r->args); ap_unescape_url(arg_copy); apr_table_setn(e, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy)); }}static const char *add_include_vars_lazy(request_rec *r, const char *var){ char *val; if (!strcasecmp(var, "DATE_LOCAL")) { include_dir_config *conf = (include_dir_config *)ap_get_module_config(r->per_dir_config, &include_module); val = ap_ht_time(r->pool, r->request_time, conf->default_time_fmt, 0); } else if (!strcasecmp(var, "DATE_GMT")) { include_dir_config *conf = (include_dir_config *)ap_get_module_config(r->per_dir_config, &include_module); val = ap_ht_time(r->pool, r->request_time, conf->default_time_fmt, 1); } else if (!strcasecmp(var, "LAST_MODIFIED")) { include_dir_config *conf = (include_dir_config *)ap_get_module_config(r->per_dir_config, &include_module); val = ap_ht_time(r->pool, r->finfo.mtime, conf->default_time_fmt, 0); } else if (!strcasecmp(var, "USER_NAME")) { if (apr_get_username(&val, r->finfo.user, r->pool) != APR_SUCCESS) { val = "<unknown>"; } } else { val = NULL; } if (val) { apr_table_setn(r->subprocess_env, var, val); } return val;}static const char *get_include_var(request_rec *r, include_ctx_t *ctx, const char *var){ const char *val; if (apr_isdigit(*var) && !var[1]) { /* Handle $0 .. $9 from the last regex evaluated. * The choice of returning NULL strings on not-found, * v.s. empty strings on an empty match is deliberate. */ if (!ctx->re_result || !ctx->re_string) { return NULL; } else { int idx = atoi(var); apr_size_t len = (*ctx->re_result)[idx].rm_eo - (*ctx->re_result)[idx].rm_so; if ( (*ctx->re_result)[idx].rm_so < 0 || (*ctx->re_result)[idx].rm_eo < 0) { return NULL; } val = apr_pstrmemdup(r->pool, ctx->re_string + (*ctx->re_result)[idx].rm_so, len); } } else { val = apr_table_get(r->subprocess_env, var); if (val == LAZY_VALUE) val = add_include_vars_lazy(r, var); } return val;}/* --------------------------- Parser functions --------------------------- *//* This is an implementation of the BNDM search algorithm. * * Fast and Flexible String Matching by Combining Bit-parallelism and * Suffix Automata (2001) * Gonzalo Navarro, Mathieu Raffinot * * http://www-igm.univ-mlv.fr/~raffinot/ftp/jea2001.ps.gz * * Initial code submitted by Sascha Schumann. */ /* Precompile the bndm_t data structure. */static void bndm_compile(bndm_t *t, const char *n, apr_size_t nl){ unsigned int x; const char *ne = n + nl; memset(t->T, 0, sizeof(unsigned int) * 256); for (x = 1; n < ne; x <<= 1) t->T[(unsigned char) *n++] |= x; t->x = x - 1;}/* Implements the BNDM search algorithm (as described above). * * n - the pattern to search for * nl - length of the pattern to search for * h - the string to look in * hl - length of the string to look for * t - precompiled bndm structure against the pattern * * Returns the count of character that is the first match or hl if no * match is found. */static apr_size_t bndm(const char *n, apr_size_t nl, const char *h, apr_size_t hl, bndm_t *t){ const char *skip; const char *he, *p, *pi; unsigned int *T, x, d; he = h + hl; T = t->T; x = t->x; pi = h - 1; /* pi: p initial */ p = pi + nl; /* compare window right to left. point to the first char */ while (p < he) { skip = p; d = x; do { d &= T[(unsigned char) *p--]; if (!d) { break; } if ((d & 1)) { if (p != pi) skip = p; else return p - h + 1; } d >>= 1; } while (d); pi = skip; p = pi + nl; } return hl;}/* * decodes a string containing html entities or numeric character references. * 's' is overwritten with the decoded string. * If 's' is syntatically incorrect, then the followed fixups will be made: * unknown entities will be left undecoded; * references to unused numeric characters will be deleted. * In particular, � will not be decoded, but will be deleted. * * drtr *//* maximum length of any ISO-LATIN-1 HTML entity name. */#define MAXENTLEN (6)/* The following is a shrinking transformation, therefore safe. */static void decodehtml(char *s){ int val, i, j; char *p; const char *ents; static const char * const entlist[MAXENTLEN + 1] = { NULL, /* 0 */ NULL, /* 1 */ "lt\074gt\076", /* 2 */ "amp\046ETH\320eth\360", /* 3 */ "quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml\353\iuml\357ouml\366uuml\374yuml\377", /* 4 */ "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc\333\THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352icirc\356ocirc\364\ucirc\373thorn\376", /* 5 */ "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311\Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde\325Oslash\330\Ugrave\331Uacute\332Yacute\335agrave\340aacute\341atilde\343ccedil\347\egrave\350eacute\351igrave\354iacute\355ntilde\361ograve\362oacute\363\otilde\365oslash\370ugrave\371uacute\372yacute\375" /* 6 */ }; /* Do a fast scan through the string until we find anything * that needs more complicated handling */ for (; *s != '&'; s++) { if (*s == '\0') { return; } } for (p = s; *s != '\0'; s++, p++) { if (*s != '&') {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -