📄 mod_include.c
字号:
#define CREATE_NODE(ctx, name) do { \ (name) = apr_palloc((ctx)->dpool, sizeof(*(name))); \ (name)->parent = (name)->left = (name)->right = NULL; \ (name)->done = 0; \} while(0)#define DEBUG_INIT(ctx, f, bb)#define DEBUG_PRINTF(arg)#define DEBUG_DUMP_TOKEN(ctx, token)#define DEBUG_DUMP_EVAL(ctx, node)#define DEBUG_DUMP_UNMATCHED(ctx, unmatched)#define DEBUG_DUMP_COND(ctx, text)#define DEBUG_DUMP_TREE(ctx, root)#endif /* !DEBUG_INCLUDE *//* * +-------------------------------------------------------+ * | | * | Static Module Data * | | * +-------------------------------------------------------+ *//* global module structure */module AP_MODULE_DECLARE_DATA include_module;/* function handlers for include directives */static apr_hash_t *include_handlers;/* forward declaration of handler registry */static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *ssi_pfn_register;/* 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)/* default values */#define DEFAULT_START_SEQUENCE "<!--#"#define DEFAULT_END_SEQUENCE "-->"#define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"#define DEFAULT_UNDEFINED_ECHO "(none)"#ifdef XBITHACK#define DEFAULT_XBITHACK XBITHACK_FULL#else#define DEFAULT_XBITHACK XBITHACK_OFF#endif/* * +-------------------------------------------------------+ * | | * | Environment/Expansion Functions * | | * +-------------------------------------------------------+ *//* * 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. *//* 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" "\353iuml\357ouml\366uuml\374yuml\377", /* 4 */ "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc" "\333THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352" "icirc\356ocirc\364ucirc\373thorn\376", /* 5 */ "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311" "Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde" "\325Oslash\330Ugrave\331Uacute\332Yacute\335agrave\340" "aacute\341atilde\343ccedil\347egrave\350eacute\351igrave" "\354iacute\355ntilde\361ograve\362oacute\363otilde\365" "oslash\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 != '&') { *p = *s; continue; } /* find end of entity */ for (i = 1; s[i] != ';' && s[i] != '\0'; i++) { continue; } if (s[i] == '\0') { /* treat as normal data */ *p = *s; continue; } /* is it numeric ? */ if (s[1] == '#') { for (j = 2, val = 0; j < i && apr_isdigit(s[j]); j++) { val = val * 10 + s[j] - '0'; } s += i; if (j < i || val <= 8 || (val >= 11 && val <= 31) || (val >= 127 && val <= 160) || val >= 256) { p--; /* no data to output */ } else { *p = RAW_ASCII_CHAR(val); } } else { j = i - 1; if (j > MAXENTLEN || entlist[j] == NULL) { /* wrong length */ *p = '&'; continue; /* skip it */ } for (ents = entlist[j]; *ents != '\0'; ents += i) { if (strncmp(s + 1, ents, j) == 0) { break; } } if (*ents == '\0') { *p = '&'; /* unknown */ } else { *p = RAW_ASCII_CHAR(((const unsigned char *) ents)[j]); s += i; } } } *p = '\0';}static void add_include_vars(request_rec *r, const 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_uid_name_get(&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(const char *var, include_ctx_t *ctx){ const char *val; request_rec *r = ctx->intern->r; if (apr_isdigit(*var) && !var[1]) { apr_size_t idx = *var - '0'; backref_t *re = ctx->intern->re; /* 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 (!re) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "regex capture $%" APR_SIZE_T_FMT " refers to no regex in %s", idx, r->filename); return NULL; } else { if (re->nsub < idx || idx >= AP_MAX_REG_MATCH) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "regex capture $%" APR_SIZE_T_FMT " is out of range (last regex was: '%s') in %s", idx, re->rexp, r->filename); return NULL; } if (re->match[idx].rm_so < 0 || re->match[idx].rm_eo < 0) { return NULL; } val = apr_pstrmemdup(ctx->dpool, re->source + re->match[idx].rm_so, re->match[idx].rm_eo - re->match[idx].rm_so); } } else { val = apr_table_get(r->subprocess_env, var); if (val == LAZY_VALUE) { val = add_include_vars_lazy(r, var); } } return val;}/* * Do variable substitution on strings * * (Note: If out==NULL, this function allocs a buffer for the resulting * string from ctx->pool. The return value is always the parsed string) */static char *ap_ssi_parse_string(include_ctx_t *ctx, const char *in, char *out, apr_size_t length, int leave_name){ request_rec *r = ctx->intern->r; result_item_t *result = NULL, *current = NULL; apr_size_t outlen = 0, inlen, span; char *ret = NULL, *eout = NULL; const char *p; if (out) { /* sanity check, out && !length is not supported */ ap_assert(out && length); ret = out; eout = out + length - 1; } span = strcspn(in, "\\$"); inlen = strlen(in); /* fast exit */ if (inlen == span) { if (out) { apr_cpystrn(out, in, length); } else { ret = apr_pstrmemdup(ctx->pool, in, (length && length <= inlen) ? length - 1 : inlen); } return ret; } /* well, actually something to do */ p = in + span; if (out) { if (span) { memcpy(out, in, (out+span <= eout) ? span : (eout-out)); out += span; } } else { current = result = apr_palloc(ctx->dpool, sizeof(*result)); current->next = NULL; current->string = in; current->len = span; outlen = span; } /* loop for specials */ do { if ((out && out >= eout) || (length && outlen >= length)) { break; } /* prepare next entry */ if (!out && current->len) { current->next = apr_palloc(ctx->dpool, sizeof(*current->next)); current = current->next; current->next = NULL; current->len = 0; } /* * escaped character */ if (*p == '\\') { if (out) { *out++ = (p[1] == '$') ? *++p : *p; ++p; } else { current->len = 1; current->string = (p[1] == '$') ? ++p : p; ++p; ++outlen; } } /* * variable expansion */ else { /* *p == '$' */ const char *newp = NULL, *ep, *key = NULL; if (*++p == '{') { ep = ap_strchr_c(++p, '}'); if (!ep) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Missing '}' on " "variable \"%s\" in %s", p, r->filename); break; } if (p < ep) { key = apr_pstrmemdup(ctx->dpool, p, ep - p); newp = ep + 1; } p -= 2; } else { ep = p; while (*ep == '_' || apr_isalnum(*ep)) { ++ep; } if (p < ep) { key = apr_pstrmemdup(ctx->dpool, p, ep - p); newp = ep; } --p; } /* empty name results in a copy of '$' in the output string */ if (!key) { if (out) { *out++ = *p++; } else { current->len = 1; current->string = p++; ++outlen; } } else { const char *val = get_include_var(key, ctx); apr_size_t len = 0; if (val) { len = strlen(val); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -