mod_include.c revision 6c4c113ce85934b11c9e78399e1bb8ec7a568af9
16c3dab75292d97eca6698f695f5012c16f86011slive/* ====================================================================
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * The Apache Software License, Version 1.1
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * reserved.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * Redistribution and use in source and binary forms, with or without
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * modification, are permitted provided that the following conditions
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * are met:
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * 1. Redistributions of source code must retain the above copyright
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * notice, this list of conditions and the following disclaimer.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * 2. Redistributions in binary form must reproduce the above copyright
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * notice, this list of conditions and the following disclaimer in
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * the documentation and/or other materials provided with the
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * distribution.
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * 3. The end-user documentation included with the redistribution,
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * if any, must include the following acknowledgment:
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd * "This product includes software developed by the
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd * Apache Software Foundation (http://www.apache.org/)."
ecc5150d35c0dc5ee5119c2717e6660fa331abbftakashi * Alternately, this acknowledgment may appear in the software itself,
ecc5150d35c0dc5ee5119c2717e6660fa331abbftakashi * if and wherever such third-party acknowledgments normally appear.
fac8c35bfb158112226ab43ddf84d59daca5dc30nd * 4. The names "Apache" and "Apache Software Foundation" must
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung * not be used to endorse or promote products derived from this
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * software without prior written permission. For written
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem * permission, please contact apache@apache.org.
16c3dab75292d97eca6698f695f5012c16f86011slive * 5. Products derived from this software may not be called "Apache",
16c3dab75292d97eca6698f695f5012c16f86011slive * nor may "Apache" appear in their name, without prior written
16c3dab75292d97eca6698f695f5012c16f86011slive * permission of the Apache Software Foundation.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16c3dab75292d97eca6698f695f5012c16f86011slive * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16c3dab75292d97eca6698f695f5012c16f86011slive * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
16c3dab75292d97eca6698f695f5012c16f86011slive * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
16c3dab75292d97eca6698f695f5012c16f86011slive * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
71fccc298df6a1540d408151a26aa22beed55d0bnd * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
71fccc298df6a1540d408151a26aa22beed55d0bnd * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71fccc298df6a1540d408151a26aa22beed55d0bnd * SUCH DAMAGE.
71fccc298df6a1540d408151a26aa22beed55d0bnd * ====================================================================
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * This software consists of voluntary contributions made by many
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * individuals on behalf of the Apache Software Foundation. For more
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * information on the Apache Software Foundation, please see
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * Portions of this software are based upon public domain software
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * originally written at the National Center for Supercomputing Applications,
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * University of Illinois, Urbana-Champaign.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * http_include.c: Handles the server-parsed HTML documents
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * Original by Rob McCool; substantial fixups by David Robinson;
16c3dab75292d97eca6698f695f5012c16f86011slive * incorporated into the Apache module framework by rst.
16c3dab75292d97eca6698f695f5012c16f86011slivestatic APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *ssi_pfn_register;
16c3dab75292d97eca6698f695f5012c16f86011slive/*****************************************************************
16c3dab75292d97eca6698f695f5012c16f86011slive * XBITHACK. Sigh... NB it's configurable per-directory; the compile-time
16c3dab75292d97eca6698f695f5012c16f86011slive * option only changes the default.
16c3dab75292d97eca6698f695f5012c16f86011slive unsigned int T[256];
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd unsigned int x;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndtypedef struct {
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndtypedef struct {
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* main parser states */
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndtypedef enum {
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndtypedef struct ssi_arg_item {
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndtypedef struct {
71fccc298df6a1540d408151a26aa22beed55d0bnd * directive)
16c3dab75292d97eca6698f695f5012c16f86011slive ssi_arg_item_t *current_arg; /* currently parsed argument */
71fccc298df6a1540d408151a26aa22beed55d0bnd include_ctx_t *ctx; /* public part of the context structure */
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd#define SSI_CREATE_ERROR_BUCKET(ctx, f, bb) APR_BRIGADE_INSERT_TAIL((bb), \
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd apr_bucket_pool_create(apr_pstrdup((ctx)->pool, (ctx)->error_str), \
16c3dab75292d97eca6698f695f5012c16f86011slive#endif /* MOD_INCLUDE_REDESIGN */
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* ------------------------ Environment function -------------------------- */
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* Sentinel value to store in subprocess_env for items that
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * shouldn't be evaluated until/unless they're actually used
71fccc298df6a1540d408151a26aa22beed55d0bndstatic const char lazy_eval_sentinel;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic void add_include_vars(request_rec *r, char *timefmt)
71fccc298df6a1540d408151a26aa22beed55d0bndstatic const char *add_include_vars_lazy(request_rec *r, const char *var)
16c3dab75292d97eca6698f695f5012c16f86011slive (include_dir_config *)ap_get_module_config(r->per_dir_config,
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd val = ap_ht_time(r->pool, r->request_time, conf->default_time_fmt, 0);
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd (include_dir_config *)ap_get_module_config(r->per_dir_config,
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd val = ap_ht_time(r->pool, r->request_time, conf->default_time_fmt, 1);
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd (include_dir_config *)ap_get_module_config(r->per_dir_config,
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd val = ap_ht_time(r->pool, r->finfo.mtime, conf->default_time_fmt, 0);
16c3dab75292d97eca6698f695f5012c16f86011slive if (apr_get_username(&val, r->finfo.user, r->pool) != APR_SUCCESS) {
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic const char *get_include_var(request_rec *r, include_ctx_t *ctx,
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd const char *var)
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd const char *val;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd /* Handle $0 .. $9 from the last regex evaluated.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * The choice of returning NULL strings on not-found,
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * v.s. empty strings on an empty match is deliberate.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* --------------------------- Parser functions --------------------------- */
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* This is an implementation of the BNDM search algorithm.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * Fast and Flexible String Matching by Combining Bit-parallelism and
71fccc298df6a1540d408151a26aa22beed55d0bnd * Suffix Automata (2001)
71fccc298df6a1540d408151a26aa22beed55d0bnd * Gonzalo Navarro, Mathieu Raffinot
71fccc298df6a1540d408151a26aa22beed55d0bnd * Initial code submitted by Sascha Schumann.
71fccc298df6a1540d408151a26aa22beed55d0bnd/* Precompile the bndm_t data structure. */
71fccc298df6a1540d408151a26aa22beed55d0bndstatic void bndm_compile(bndm_t *t, const char *n, apr_size_t nl)
71fccc298df6a1540d408151a26aa22beed55d0bnd unsigned int x;
71fccc298df6a1540d408151a26aa22beed55d0bnd t->T[(unsigned char) *n++] |= x;
71fccc298df6a1540d408151a26aa22beed55d0bnd t->x = x - 1;
71fccc298df6a1540d408151a26aa22beed55d0bnd/* Implements the BNDM search algorithm (as described above).
71fccc298df6a1540d408151a26aa22beed55d0bnd * n - the pattern to search for
71fccc298df6a1540d408151a26aa22beed55d0bnd * nl - length of the pattern to search for
71fccc298df6a1540d408151a26aa22beed55d0bnd * h - the string to look in
71fccc298df6a1540d408151a26aa22beed55d0bnd * hl - length of the string to look for
71fccc298df6a1540d408151a26aa22beed55d0bnd * t - precompiled bndm structure against the pattern
71fccc298df6a1540d408151a26aa22beed55d0bnd * Returns the count of character that is the first match or hl if no
71fccc298df6a1540d408151a26aa22beed55d0bnd * match is found.
71fccc298df6a1540d408151a26aa22beed55d0bndstatic apr_size_t bndm(const char *n, apr_size_t nl, const char *h,
71fccc298df6a1540d408151a26aa22beed55d0bnd const char *skip;
71fccc298df6a1540d408151a26aa22beed55d0bnd unsigned int *T, x, d;
ecc5150d35c0dc5ee5119c2717e6660fa331abbftakashi p = pi + nl; /* compare window right to left. point to the first char */
fac8c35bfb158112226ab43ddf84d59daca5dc30nd while (p < he) {
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd d &= T[(unsigned char) *p--];
if (p != pi)
skip = p;
return hl;
#ifndef MOD_INCLUDE_REDESIGN
const char *buf;
*do_cleanup = 0;
int read_done = 0;
return start_bucket;
if (!read_done) {
return NULL;
c = buf;
if (len)
c = buf;
return NULL;
const char *buf;
const char *start;
int read_done = 0;
return dptr;
if (!read_done) {
return NULL;
c = buf;
start = c;
return (tmp_buck);
if (!apr_isspace(*c)) {
const char *tmp = c;
*c != *str);
if (!apr_isspace(*c)) {
const char *tmp = c;
if (*c == str[0]) {
return NULL;
request_rec *r,
char *tmp_buf,
int done = 0;
const char *tmp_from;
return (APR_ENOMEM);
} while ((!done) &&
return (APR_SUCCESS);
static void decodehtml(char *s)
int val, i, j;
const char *ents;
#ifdef MOD_INCLUDE_REDESIGN
if (!**tag) {
if (!*tag_val) {
++(*tag_val);
if (dodecode) {
#ifndef MOD_INCLUDE_REDESIGN
int shift_val = 0;
while (apr_islower(*c)) {
term = *c++;
*tag_val = c;
if (!term) {
if (*c == term) {
shift_val++;
if (shift_val > 0) {
*(c-shift_val) = *c;
if (shift_val > 0) {
*(c-shift_val) = *c;
if (dodecode) {
char ch;
char *next;
char *end_out;
if (!out) {
switch (ch) {
char *new_out;
return out;
const char *start_of_var_name;
char tmp_store;
apr_size_t l;
++in;
return out;
++in;
++in;
if (val) {
else if (leave_name) {
char *new_out;
next += l;
char *new_out;
return out;
return out;
#ifdef HAVE_DRIVE_LETTERS
#ifdef NETWARE
while (*path) {
int dots = 0;
++dots;
#if defined(WIN32)
char *parsed_string;
return rc;
MAX_STRING_LEN, 0);
int founddupe = 0;
request_rec *p;
request_rec *q;
if (p != NULL) {
if (rr)
&include_module, r);
if (error_fmt) {
const char *val =
MAX_STRING_LEN, 0));
if (val) {
switch(encode) {
case E_NONE:
case E_URL:
case E_ENTITY:
char *parsed_string;
MAX_STRING_LEN, 0);
MAX_STRING_LEN, 0);
MAX_STRING_LEN, 0);
int ret=0;
if (error_fmt) {
return ret;
char *parsed_string;
MAX_STRING_LEN, 0);
int l, x, pos = 0;
char *parsed_string;
MAX_STRING_LEN, 0);
char *t_val;
int regex_error;
return (!regex_error);
enum token_type {
struct token {
char* value;
char ch;
int next = 0;
char qs = 0;
int tkn_fnd = 0;
return (char *) NULL;
return (char *) NULL;
switch (ch) {
return (string);
return (string);
return (string);
return (string);
return (string);
return (string);
if (!qs) {
if (!qs) {
switch (ch) {
if (!tkn_fnd) {
qs = 0;
string++;
if (tkn_fnd) {
if (qs) {
next = 0;
return (string);
struct parse_node {
const char *parse;
char* buffer;
int retval = 0;
*was_error = 0;
*was_unmatched = 0;
sizeof(struct parse_node));
(char *) NULL) {
case token_string:
#ifdef DEBUG_INCLUDE
case token_string:
NULL);
case token_eq:
case token_ne:
case token_and:
case token_or:
case token_lbrace:
case token_not:
case token_ge:
case token_gt:
case token_le:
case token_lt:
return retval;
case token_re:
#ifdef DEBUG_INCLUDE
case token_eq:
case token_ne:
case token_and:
case token_or:
case token_lbrace:
case token_not:
return retval;
case token_and:
case token_or:
#ifdef DEBUG_INCLUDE
return retval;
case token_string:
case token_re:
case token_group:
case token_not:
case token_eq:
case token_ne:
case token_and:
case token_or:
case token_ge:
case token_gt:
case token_le:
case token_lt:
case token_lbrace:
return retval;
case token_not:
#ifdef DEBUG_INCLUDE
case token_not:
case token_eq:
case token_ne:
case token_and:
case token_or:
case token_lbrace:
case token_ge:
case token_gt:
case token_le:
case token_lt:
return retval;
case token_eq:
case token_ne:
case token_ge:
case token_gt:
case token_le:
case token_lt:
#ifdef DEBUG_INCLUDE
return retval;
case token_string:
case token_re:
case token_group:
case token_lbrace:
case token_and:
case token_or:
case token_not:
case token_eq:
case token_ne:
case token_ge:
case token_gt:
case token_le:
case token_lt:
return retval;
case token_rbrace:
#ifdef DEBUG_INCLUDE
return retval;
case token_lbrace:
#ifdef DEBUG_INCLUDE
case token_not:
case token_eq:
case token_ne:
case token_and:
case token_or:
case token_lbrace:
case token_ge:
case token_gt:
case token_le:
case token_lt:
case token_string:
case token_re:
case token_group:
return retval;
case token_string:
#ifdef DEBUG_INCLUDE
MAX_STRING_LEN, 0);
case token_re:
return retval;
case token_and:
case token_or:
#ifdef DEBUG_INCLUDE
return retval;
case token_string:
case token_string:
#ifdef DEBUG_INCLUDE
#ifdef DEBUG_INCLUDE
case token_eq:
case token_ne:
#ifdef DEBUG_INCLUDE
return retval;
#ifdef DEBUG_INCLUDE
#ifdef DEBUG_INCLUDE
#ifdef DEBUG_INCLUDE
case token_ge:
case token_gt:
case token_le:
case token_lt:
#ifdef DEBUG_INCLUDE
return retval;
#ifdef DEBUG_INCLUDE
#ifdef DEBUG_INCLUDE
case token_not:
#ifdef DEBUG_INCLUDE
case token_group:
#ifdef DEBUG_INCLUDE
case token_lbrace:
return retval;
case token_rbrace:
return retval;
return retval;
return (retval);
#ifdef DEBUG_INCLUDE
r->filename);
if (was_error) {
if (was_unmatched) {
if (expr_ret) {
#ifdef DEBUG_INCLUDE
r->filename);
r->filename);
if (was_error) {
if (was_unmatched) {
if (expr_ret) {
#ifdef DEBUG_INCLUDE
r->filename);
char *parsed_string;
while (sub) {
MAX_STRING_LEN, 0);
r->filename);
MAX_STRING_LEN, 0);
*next = 0;
r->pool,
r->filename);
#ifdef MOD_INCLUDE_REDESIGN
const char *p, *ep;
return index;
if (p < ep) {
++pos;
if (p == ep) {
return index;
} while (p < ep);
return len;
const char *data,
const char *p, *ep;
*release = 0;
p = data;
++pos;
return (p - data);
if (p == ep) {
return (p - data);
++spos;
++*release;
++spos;
++*release;
--pos;
if (t == pos) {
if (pos) {
const char *p = data;
case PARSE_DIRECTIVE:
return (p - data);
case PARSE_DIRECTIVE_TAIL:
++pos;
if (p == ep) {
case PARSE_DIRECTIVE_POSTTAIL:
case PARSE_DIRECTIVE_POSTNAME:
return (p - data);
const char *p = data;
if (p < ep) {
return (p - data);
const char *p = data;
++pos;
return (p - data);
if (p == ep) {
return (p - data);
const char *p = data;
case PARSE_ARG:
return (p - data);
case PARSE_ARG_NAME:
if (p < ep) {
return (p - data);
case PARSE_ARG_POSTNAME:
while (*sp) {
++sp;
case PARSE_ARG_EQ:
if (p < ep) {
return (p - data);
case PARSE_ARG_PREVAL:
if (p < ep) {
return (p - data);
case PARSE_ARG_VAL_ESC:
case PARSE_ARG_VAL:
for (; p < ep; ++p) {
if (p == ep) {
return (p - data);
case PARSE_ARG_POSTVAL:
char *sp;
++sp;
++sp;
++shift;
if (shift) {
request_rec *r = f->r;
return APR_SUCCESS;
if (APR_BUCKET_IS_METADATA(b)) {
if (APR_BUCKET_IS_EOS(b)) {
if (APR_BUCKET_IS_FLUSH(b)) {
b = newb;
return rv;
len = 0;
return rv;
b = APR_BUCKET_NEXT(b);
case PARSE_PRE_HEAD:
b = newb;
case PARSE_HEAD:
f->c->bucket_alloc);
b = newb;
case PARSE_DIRECTIVE:
case PARSE_DIRECTIVE_POSTNAME:
case PARSE_DIRECTIVE_TAIL:
case PARSE_DIRECTIVE_POSTTAIL:
if (index) {
if (store) {
if (index) {
b = newb;
else if (index) {
b = newb;
case PARSE_PRE_ARG:
b = newb;
case PARSE_ARG:
case PARSE_ARG_NAME:
case PARSE_ARG_POSTNAME:
case PARSE_ARG_EQ:
case PARSE_ARG_PREVAL:
case PARSE_ARG_VAL:
case PARSE_ARG_VAL_ESC:
case PARSE_ARG_POSTVAL:
if (index) {
if (store) {
if (index) {
b = newb;
else if (index) {
b = newb;
case PARSE_TAIL:
case PARSE_TAIL_SEQ:
b = newb;
b = newb;
case PARSE_EXECUTE:
if (handle_func) {
char *tag;
while (carg) {
while (carg) {
return rv;
if (dummy) {
r->filename);
f->c->bucket_alloc));
return rv;
#ifndef MOD_INCLUDE_REDESIGN
int do_cleanup = 0;
: tmp_dptr;
return rv;
return rv;
apr_bucket **);
r->filename);
return APR_SUCCESS;
return (rv);
return rv;
return rv;
apr_bucket *b;
!APR_BUCKET_IS_EOS(b);
return rv;
return APR_SUCCESS;
return result;
return result;
return NULL;
return OK;
request_rec *r = f->r;
#ifdef MOD_INCLUDE_REDESIGN
if (!f->ctx) {
#ifdef MOD_INCLUDE_REDESIGN
ctx->r = f->r;
f->c->bucket_alloc);
f->c->bucket_alloc);
ap_add_cgi_vars(r);
/* Always unset the ETag/Last-Modified fields - see RFC2616 - 13.3.4.
#ifdef MOD_INCLUDE_REDESIGN
if (r->args) {
return send_parsed_content(f, b);
return send_parsed_content(&b, r, f);
if(ssi_pfn_register) {
return OK;
return NULL;
const char *p = msg;
if (apr_isspace(*p)) {
return NULL;
return NULL;
const char *p = msg;
if (apr_isspace(*p)) {
return NULL;
return NULL;
{NULL}
return DECLINED;
return DECLINED;
return DECLINED;
return DECLINED;
return DECLINED;