mod_include.c revision 34d7c69235d0bc7ac9e2f121c4890c309bb39d20
38dc50ae00a1ea57fa41500d74f4e818747e3cefpquerna/* ====================================================================
7d5ac94fda90b837211dadf2585c0fe8c5dc3e5djerenkrantz * The Apache Software License, Version 1.1
ecf8d72af432e53e4c0661fb99dfda8061507bfajerenkrantz * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
62f7716b14b71603a8004434ca3536902bfb8899wrowe * reserved.
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * Redistribution and use in source and binary forms, with or without
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * modification, are permitted provided that the following conditions
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * 1. Redistributions of source code must retain the above copyright
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * notice, this list of conditions and the following disclaimer.
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * 2. Redistributions in binary form must reproduce the above copyright
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * notice, this list of conditions and the following disclaimer in
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * the documentation and/or other materials provided with the
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * distribution.
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * 3. The end-user documentation included with the redistribution,
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * if any, must include the following acknowledgment:
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * "This product includes software developed by the
38dc50ae00a1ea57fa41500d74f4e818747e3cefpquerna * Apache Software Foundation (http://www.apache.org/)."
366616a5cc6212cbf7134ccf877f965d668c6b04wrowe * Alternately, this acknowledgment may appear in the software itself,
ecf8d72af432e53e4c0661fb99dfda8061507bfajerenkrantz * if and wherever such third-party acknowledgments normally appear.
80464b326874ee15d74742ae39708ec3f2eae1d7wrowe * 4. The names "Apache" and "Apache Software Foundation" must
80464b326874ee15d74742ae39708ec3f2eae1d7wrowe * not be used to endorse or promote products derived from this
38dc50ae00a1ea57fa41500d74f4e818747e3cefpquerna * software without prior written permission. For written
2534e869d2ba209bd0c43717ea80992e6de0c51djim * permission, please contact apache@apache.org.
53e66a2931d02e84628ba946055cc92e56b43db8wrowe * 5. Products derived from this software may not be called "Apache",
53e66a2931d02e84628ba946055cc92e56b43db8wrowe * nor may "Apache" appear in their name, without prior written
cd365a1ad6798c1faef19b445c00ae97eb94a234pquerna * permission of the Apache Software Foundation.
6507aa1a5709a9122f2e0b9be8bb9bd6d78715c3pquerna * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
b6c98ce4a43f123af0a691fd7b833efcf0ce1d6apquerna * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
af4c982a7cf4515f124935f99a329744035fc699slive * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
f610c7c704235bc327dbe9b62982f5b3f8e30a77wrowe * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
f610c7c704235bc327dbe9b62982f5b3f8e30a77wrowe * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
d96ee8cda2799e1f2743c1603adeb4833ed0e15fslive * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ecf8d72af432e53e4c0661fb99dfda8061507bfajerenkrantz * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
ecf8d72af432e53e4c0661fb99dfda8061507bfajerenkrantz * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * SUCH DAMAGE.
ecf8d72af432e53e4c0661fb99dfda8061507bfajerenkrantz * ====================================================================
d96ee8cda2799e1f2743c1603adeb4833ed0e15fslive * This software consists of voluntary contributions made by many
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * individuals on behalf of the Apache Software Foundation. For more
f610c7c704235bc327dbe9b62982f5b3f8e30a77wrowe * information on the Apache Software Foundation, please see
5ca8e11fadb6f7a8d9d0367c1800205c99d4bcd6jerenkrantz * Portions of this software are based upon public domain software
62f7716b14b71603a8004434ca3536902bfb8899wrowe * originally written at the National Center for Supercomputing Applications,
45b0e1c775c1cfed6473c9e5304179ccb9609f53stoddard * University of Illinois, Urbana-Champaign.
a74ee4396fe11ffc1ca05837a59e497c905eedc3sf * http_include.c: Handles the server-parsed HTML documents
a74ee4396fe11ffc1ca05837a59e497c905eedc3sf * Original by Rob McCool; substantial fixups by David Robinson;
a74ee4396fe11ffc1ca05837a59e497c905eedc3sf * incorporated into the Apache module framework by rst.
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowestatic APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *ssi_pfn_register;
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe/*****************************************************************
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * XBITHACK. Sigh... NB it's configurable per-directory; the compile-time
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * option only changes the default.
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe unsigned int T[256];
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe unsigned int x;
f4cb04eb78da02a38fcdd87489dc7b660107d55fjerenkrantztypedef struct {
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowetypedef struct {
53e66a2931d02e84628ba946055cc92e56b43db8wrowe/* ------------------------ Environment function -------------------------- */
53e66a2931d02e84628ba946055cc92e56b43db8wrowe/* Sentinel value to store in subprocess_env for items that
828333c93c6c11a4b46154302515e35cc6982f12sctemme * shouldn't be evaluated until/unless they're actually used
1b3f48fd6b1ccb8745f908e40156c5a85ca3c347jerenkrantzstatic const char lazy_eval_sentinel;
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowestatic void add_include_vars(request_rec *r, char *timefmt)
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe apr_table_setn(e, "DOCUMENT_PATH_INFO", r->path_info);
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowestatic const char *add_include_vars_lazy(request_rec *r, const char *var)
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe (include_dir_config *)ap_get_module_config(r->per_dir_config,
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe val = ap_ht_time(r->pool, r->request_time, conf->default_time_fmt, 0);
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe (include_dir_config *)ap_get_module_config(r->per_dir_config,
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe val = ap_ht_time(r->pool, r->request_time, conf->default_time_fmt, 1);
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe (include_dir_config *)ap_get_module_config(r->per_dir_config,
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe val = ap_ht_time(r->pool, r->finfo.mtime, conf->default_time_fmt, 0);
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe if (apr_get_username(&val, r->finfo.user, r->pool) != APR_SUCCESS) {
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowestatic const char *get_include_var(request_rec *r, include_ctx_t *ctx,
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe const char *var)
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe const char *val;
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe /* Handle $0 .. $9 from the last regex evaluated.
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * The choice of returning NULL strings on not-found,
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * v.s. empty strings on an empty match is deliberate.
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe/* --------------------------- Parser functions --------------------------- */
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe/* This is an implementation of the BNDM search algorithm.
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * Fast and Flexible String Matching by Combining Bit-parallelism and
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * Suffix Automata (2001)
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * Gonzalo Navarro, Mathieu Raffinot
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * http://www-igm.univ-mlv.fr/~raffinot/ftp/jea2001.ps.gz
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * Initial code submitted by Sascha Schumann.
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe/* Precompile the bndm_t data structure. */
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowestatic void bndm_compile(bndm_t *t, const char *n, apr_size_t nl)
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe unsigned int x;
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe t->T[(unsigned char) *n++] |= x;
828333c93c6c11a4b46154302515e35cc6982f12sctemme t->x = x - 1;
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe/* Implements the BNDM search algorithm (as described above).
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * n - the pattern to search for
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * nl - length of the pattern to search for
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * h - the string to look in
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * hl - length of the string to look for
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * t - precompiled bndm structure against the pattern
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * Returns the count of character that is the first match or hl if no
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * match is found.
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowestatic apr_size_t bndm(const char *n, apr_size_t nl, const char *h,
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe const char *skip;
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe unsigned int *T, x, d;
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe p = pi + nl; /* compare window right to left. point to the first char */
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe while (p < he) {
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe d &= T[(unsigned char) *p--];
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe if ((d & 1)) {
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe return p - h + 1;
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe } while (d);
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe/* We've now found a start sequence tag... */
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowestatic apr_bucket* found_start_sequence(apr_bucket *dptr,
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe /* We want to split the bucket at the '<'. */
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe /* Split the bucket with the start of the tag in it */
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe apr_bucket_split(ctx->head_start_bucket, ctx->head_start_index);
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe /* If it was a one bucket match */
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe ctx->tag_start_index = tagStart - ctx->head_start_index;
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe/* This function returns either a pointer to the split bucket containing the
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * first byte of the BEGINNING_SEQUENCE (after finding a complete match) or it
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe * returns NULL if no match found.
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowestatic apr_bucket *find_start_sequence(apr_bucket *dptr, include_ctx_t *ctx,
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe const char *c;
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe const char *buf;
bce58f79020e39e5ac5de398fe08b4f8a1e19970pgollucci rv = apr_bucket_read(dptr, &buf, &len, APR_NONBLOCK_READ);
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe apr_bucket_split(start_bucket, ctx->head_start_index);
28c4fe67d75f8f26504d75b7aa8dc5d868032888wrowe rv = apr_bucket_read(dptr, &buf, &len, APR_BLOCK_READ);
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe /* Set our buffer to use. */
820e91baab4f9a45001d668698d2fae3501cb4b0trawick /* The last bucket had a left over partial match that we need to
820e91baab4f9a45001d668698d2fae3501cb4b0trawick * complete.
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe /* False alarm... */
9e86ff266f053757dd96dab7cf4bc53aaaaa583ewrowe /* Consider the case where we have <!-- at the end of the bucket. */
62f7716b14b71603a8004434ca3536902bfb8899wrowe /* The reason for this, is that we need to make sure
62f7716b14b71603a8004434ca3536902bfb8899wrowe * that we catch cases like <<!--#. This makes the
62f7716b14b71603a8004434ca3536902bfb8899wrowe * second check after the original check fails.
62f7716b14b71603a8004434ca3536902bfb8899wrowe * If parse_pos was already 0 then we already checked this.
if (*c == str[0]) {
return NULL;
const char *buf;
int read_done = 0;
return dptr;
if (!read_done) {
return NULL;
c = buf;
return (tmp_buck);
if (!apr_isspace(*c)) {
if (!apr_isspace(*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;
int shift_val = 0;
while (apr_islower(*c)) {
term = *c++;
*tag_val = c;
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;
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)
++path;
char *parsed_string;
MAX_STRING_LEN, 0);
int founddupe = 0;
request_rec *p;
request_rec *q;
if (p != NULL) {
if (rr)
&include_module, r);
if (!error_fmt) {
int rv;
return rc;
if (error_fmt) {
if (val) {
switch(encode) {
case E_NONE:
case E_URL:
case E_ENTITY:
r->pool);
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) {
* but that is (IMHO) even less readable/maintainable than the goto.
if (!qs) {
switch (ch) {
if (!tkn_fnd) {
qs = 0;
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:
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:
goto RETURN;
case token_re:
#ifdef DEBUG_INCLUDE
case token_eq:
case token_ne:
case token_and:
case token_or:
case token_lbrace:
case token_not:
goto RETURN;
case token_and:
case token_or:
#ifdef DEBUG_INCLUDE
goto RETURN;
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:
goto RETURN;
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:
goto RETURN;
case token_eq:
case token_ne:
case token_ge:
case token_gt:
case token_le:
case token_lt:
#ifdef DEBUG_INCLUDE
goto RETURN;
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:
goto RETURN;
case token_rbrace:
#ifdef DEBUG_INCLUDE
goto RETURN;
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:
goto RETURN;
case token_string:
#ifdef DEBUG_INCLUDE
MAX_STRING_LEN, 0);
case token_re:
goto RETURN;
case token_and:
case token_or:
#ifdef DEBUG_INCLUDE
goto RETURN;
case token_string:
case token_string:
#ifdef DEBUG_INCLUDE
#ifdef DEBUG_INCLUDE
case token_eq:
case token_ne:
#ifdef DEBUG_INCLUDE
goto RETURN;
#ifdef DEBUG_INCLUDE
#ifdef DEBUG_INCLUDE
#ifdef DEBUG_INCLUDE
case token_ge:
case token_gt:
case token_le:
case token_lt:
#ifdef DEBUG_INCLUDE
goto RETURN;
#ifdef DEBUG_INCLUDE
#ifdef DEBUG_INCLUDE
case token_not:
#ifdef DEBUG_INCLUDE
case token_group:
#ifdef DEBUG_INCLUDE
case token_lbrace:
goto RETURN;
case token_rbrace:
goto RETURN;
goto RETURN;
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;
r->filename);
MAX_STRING_LEN, 0);
*next = 0;
r->pool);
r->filename);
int do_cleanup = 0;
return rv;
return rv;
apr_bucket **);
r->filename);
return APR_SUCCESS;
return (rv);
return rv;
return rv;
return APR_SUCCESS;
return result;
return result;
return NULL;
request_rec *r = f->r;
if (!f->ctx) {
ap_add_cgi_vars(r);
/* Always unset the ETag/Last-Modified fields - see RFC2616 - 13.3.4.
return send_parsed_content(&b, r, f);
if(ssi_pfn_register) {
return OK;
return NULL;
return NULL;
return NULL;
return NULL;
{NULL}
return DECLINED;
return DECLINED;
return DECLINED;
return DECLINED;
return DECLINED;