mod_include.c revision 024cd9589e52cf11ce765dfddb5b5f0c6e421a48
6ae232055d4d8a97267517c5e50074c2c819941and/* ====================================================================
6ae232055d4d8a97267517c5e50074c2c819941and * The Apache Software License, Version 1.1
6ae232055d4d8a97267517c5e50074c2c819941and * Copyright (c) 2000 The Apache Software Foundation. All rights
6ae232055d4d8a97267517c5e50074c2c819941and * reserved.
6ae232055d4d8a97267517c5e50074c2c819941and * Redistribution and use in source and binary forms, with or without
6ae232055d4d8a97267517c5e50074c2c819941and * modification, are permitted provided that the following conditions
6ae232055d4d8a97267517c5e50074c2c819941and * are met:
6ae232055d4d8a97267517c5e50074c2c819941and * 1. Redistributions of source code must retain the above copyright
6ae232055d4d8a97267517c5e50074c2c819941and * notice, this list of conditions and the following disclaimer.
6ae232055d4d8a97267517c5e50074c2c819941and * 2. Redistributions in binary form must reproduce the above copyright
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * notice, this list of conditions and the following disclaimer in
6ae232055d4d8a97267517c5e50074c2c819941and * the documentation and/or other materials provided with the
6ae232055d4d8a97267517c5e50074c2c819941and * distribution.
6ae232055d4d8a97267517c5e50074c2c819941and * 3. The end-user documentation included with the redistribution,
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * if any, must include the following acknowledgment:
6ae232055d4d8a97267517c5e50074c2c819941and * "This product includes software developed by the
4b3a8afbfcea8b265d179a122bf40dfedd1ce280takashi * Apache Software Foundation (http://www.apache.org/)."
6ae232055d4d8a97267517c5e50074c2c819941and * Alternately, this acknowledgment may appear in the software itself,
6ae232055d4d8a97267517c5e50074c2c819941and * if and wherever such third-party acknowledgments normally appear.
6ae232055d4d8a97267517c5e50074c2c819941and * 4. The names "Apache" and "Apache Software Foundation" must
fac8c35bfb158112226ab43ddf84d59daca5dc30nd * not be used to endorse or promote products derived from this
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung * software without prior written permission. For written
6ae232055d4d8a97267517c5e50074c2c819941and * permission, please contact apache@apache.org.
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem * 5. Products derived from this software may not be called "Apache",
6ae232055d4d8a97267517c5e50074c2c819941and * nor may "Apache" appear in their name, without prior written
6ae232055d4d8a97267517c5e50074c2c819941and * permission of the Apache Software Foundation.
6ae232055d4d8a97267517c5e50074c2c819941and * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
6ae232055d4d8a97267517c5e50074c2c819941and * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
6ae232055d4d8a97267517c5e50074c2c819941and * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6ae232055d4d8a97267517c5e50074c2c819941and * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
6ae232055d4d8a97267517c5e50074c2c819941and * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6ae232055d4d8a97267517c5e50074c2c819941and * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6ae232055d4d8a97267517c5e50074c2c819941and * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
6ae232055d4d8a97267517c5e50074c2c819941and * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6ae232055d4d8a97267517c5e50074c2c819941and * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
6ae232055d4d8a97267517c5e50074c2c819941and * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
6ae232055d4d8a97267517c5e50074c2c819941and * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6ae232055d4d8a97267517c5e50074c2c819941and * SUCH DAMAGE.
6ae232055d4d8a97267517c5e50074c2c819941and * ====================================================================
6ae232055d4d8a97267517c5e50074c2c819941and * This software consists of voluntary contributions made by many
6ae232055d4d8a97267517c5e50074c2c819941and * individuals on behalf of the Apache Software Foundation. For more
6ae232055d4d8a97267517c5e50074c2c819941and * information on the Apache Software Foundation, please see
6ae232055d4d8a97267517c5e50074c2c819941and * Portions of this software are based upon public domain software
6ae232055d4d8a97267517c5e50074c2c819941and * originally written at the National Center for Supercomputing Applications,
6ae232055d4d8a97267517c5e50074c2c819941and * University of Illinois, Urbana-Champaign.
6ae232055d4d8a97267517c5e50074c2c819941and * http_include.c: Handles the server-parsed HTML documents
6ae232055d4d8a97267517c5e50074c2c819941and * Original by Rob McCool; substantial fixups by David Robinson;
6ae232055d4d8a97267517c5e50074c2c819941and * incorporated into the Apache module framework by rst.
6ae232055d4d8a97267517c5e50074c2c819941andstatic APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *ssi_pfn_register;
6ae232055d4d8a97267517c5e50074c2c819941and/* ------------------------ Environment function -------------------------- */
6ae232055d4d8a97267517c5e50074c2c819941and/* XXX: could use ap_table_overlap here */
6ae232055d4d8a97267517c5e50074c2c819941andstatic void add_include_vars(request_rec *r, char *timefmt)
6ae232055d4d8a97267517c5e50074c2c819941and apr_table_setn(e, "DATE_LOCAL", ap_ht_time(r->pool, date, timefmt, 0));
6ae232055d4d8a97267517c5e50074c2c819941and apr_table_setn(e, "DATE_GMT", ap_ht_time(r->pool, date, timefmt, 1));
6ae232055d4d8a97267517c5e50074c2c819941and if (apr_get_username(&pwname, r->finfo.user, r->pool) == APR_SUCCESS) {
6ae232055d4d8a97267517c5e50074c2c819941and/* --------------------------- Parser functions --------------------------- */
6ae232055d4d8a97267517c5e50074c2c819941and/* This function returns either a pointer to the split bucket containing the
6ae232055d4d8a97267517c5e50074c2c819941and * first byte of the BEGINNING_SEQUENCE (after finding a complete match) or it
6ae232055d4d8a97267517c5e50074c2c819941and * returns NULL if no match found.
6ae232055d4d8a97267517c5e50074c2c819941andstatic apr_bucket *find_start_sequence(apr_bucket *dptr, include_ctx_t *ctx,
6ae232055d4d8a97267517c5e50074c2c819941and const char *c;
6ae232055d4d8a97267517c5e50074c2c819941and const char *buf;
6ae232055d4d8a97267517c5e50074c2c819941and /* XXX handle retcodes */
6ae232055d4d8a97267517c5e50074c2c819941and /* We want to split the bucket at the '<'. */
6ae232055d4d8a97267517c5e50074c2c819941and apr_bucket_split(ctx->head_start_bucket, ctx->head_start_index);
6ae232055d4d8a97267517c5e50074c2c819941and /* The reason for this, is that we need to make sure
6ae232055d4d8a97267517c5e50074c2c819941and * that we catch cases like <<!--#. This makes the
6ae232055d4d8a97267517c5e50074c2c819941and * second check after the original check fails.
6ae232055d4d8a97267517c5e50074c2c819941and * If parse_pos was already 0 then we already checked this.
6ae232055d4d8a97267517c5e50074c2c819941and if (*c == str[0]) {
6ae232055d4d8a97267517c5e50074c2c819941andstatic apr_bucket *find_end_sequence(apr_bucket *dptr, include_ctx_t *ctx, apr_bucket_brigade *bb)
6ae232055d4d8a97267517c5e50074c2c819941and const char *c;
6ae232055d4d8a97267517c5e50074c2c819941and const char *buf;
6ae232055d4d8a97267517c5e50074c2c819941and /* XXX handle retcodes */
6ae232055d4d8a97267517c5e50074c2c819941and /* We want to split the bucket at the '>'. The
6ae232055d4d8a97267517c5e50074c2c819941and * end of the END_SEQUENCE is in the current bucket.
6ae232055d4d8a97267517c5e50074c2c819941and * The beginning might be in a previous bucket.
6ae232055d4d8a97267517c5e50074c2c819941and if ((c - buf) > 0) {
6ae232055d4d8a97267517c5e50074c2c819941and /* The reason for this, is that we need to make sure
6ae232055d4d8a97267517c5e50074c2c819941and * that we catch cases like --->. This makes the
6ae232055d4d8a97267517c5e50074c2c819941and * second check after the original check fails.
6ae232055d4d8a97267517c5e50074c2c819941and * If parse_pos was already 0 then we already checked this.
6ae232055d4d8a97267517c5e50074c2c819941and if (*c == str[0]) {
6ae232055d4d8a97267517c5e50074c2c819941and/* This function culls through the buckets that have been set aside in the
6ae232055d4d8a97267517c5e50074c2c819941and * ssi_tag_brigade and copies just the directive part of the SSI tag (none
6ae232055d4d8a97267517c5e50074c2c819941and * of the start and end delimiter bytes are copied).
6ae232055d4d8a97267517c5e50074c2c819941andstatic apr_status_t get_combined_directive (include_ctx_t *ctx,
6ae232055d4d8a97267517c5e50074c2c819941and const char *tmp_from;
6ae232055d4d8a97267517c5e50074c2c819941and /* If the tag length is longer than the tmp buffer, allocate space. */
6ae232055d4d8a97267517c5e50074c2c819941and if ((ctx->combined_tag = apr_pcalloc(r->pool, ctx->tag_length + 1)) == NULL) {
6ae232055d4d8a97267517c5e50074c2c819941and } /* Else, just use the temp buffer. */
6ae232055d4d8a97267517c5e50074c2c819941and /* Prime the pump. Start at the beginning of the tag... */
6ae232055d4d8a97267517c5e50074c2c819941and apr_bucket_read (dptr, &tmp_from, &tmp_from_len, 0); /* Read the bucket... */
6ae232055d4d8a97267517c5e50074c2c819941and /* Adjust the pointer to start at the tag within the bucket... */
6ae232055d4d8a97267517c5e50074c2c819941and /* Loop through the buckets from the tag_start_bucket until before
6ae232055d4d8a97267517c5e50074c2c819941and * the tail_start_bucket copying the contents into the buffer.
6ae232055d4d8a97267517c5e50074c2c819941and /* Adjust the count to stop at the beginning of the tail. */
6ae232055d4d8a97267517c5e50074c2c819941and } while ((!done) &&
6ae232055d4d8a97267517c5e50074c2c819941and ((ctx->curr_tag_pos - ctx->combined_tag) < ctx->tag_length));
6ae232055d4d8a97267517c5e50074c2c819941and * decodes a string containing html entities or numeric character references.
4b3a8afbfcea8b265d179a122bf40dfedd1ce280takashi * 's' is overwritten with the decoded string.
6ae232055d4d8a97267517c5e50074c2c819941and * If 's' is syntatically incorrect, then the followed fixups will be made:
6ae232055d4d8a97267517c5e50074c2c819941and * unknown entities will be left undecoded;
6ae232055d4d8a97267517c5e50074c2c819941and * references to unused numeric characters will be deleted.
6ae232055d4d8a97267517c5e50074c2c819941and * In particular, � will not be decoded, but will be deleted.
6ae232055d4d8a97267517c5e50074c2c819941and/* maximum length of any ISO-LATIN-1 HTML entity name. */
static void decodehtml(char *s)
int val, i, j;
const char *ents;
int shift_val = 0;
*tag_val = c;
if (shift_val > 0) {
*(c-shift_val) = *c;
if (shift_val > 0) {
*(c-shift_val) = *c;
if (dodecode) {
char ch;
char *end_out;
switch (ch) {
const char *start_of_var_name;
char tmp_store;
size_t l;
++in;
++in;
++in;
if (val) {
else if (leave_name) {
next += l;
#ifdef HAVE_DRIVE_LETTERS
#ifdef NETWARE
while (*path) {
int dots = 0;
++dots;
#if defined(WIN32)
++path;
int founddupe = 0;
request_rec *p;
request_rec *q;
if (p != NULL) {
if (rr)
if (!error_fmt) {
if (error_fmt) {
!= NESTED_INCLUDE_MAGIC) {
int b_copy = 0;
if (val) {
switch(encode) {
int ret=0;
if (error_fmt) {
return ret;
else if (!size) {
int l, x, pos = 0;
char *t_val;
int regex_error;
return (!regex_error);
enum token_type {
struct token {
int *unmatched)
char ch;
int next = 0;
int 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;
++string;
if (qs) {
next = 0;
return (string);
struct parse_node {
const char *parse;
int retval = 0;
*was_error = 0;
*was_unmatched = 0;
sizeof(struct parse_node));
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_and:
case token_or:
#ifdef DEBUG_INCLUDE
goto RETURN;
case token_string:
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_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_group:
goto RETURN;
case token_string:
#ifdef DEBUG_INCLUDE
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;
int len;
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
if (was_error) {
if (was_unmatched) {
if (expr_ret) {
#ifdef DEBUG_INCLUDE
if (was_error) {
if (was_unmatched) {
if (expr_ret) {
#ifdef DEBUG_INCLUDE
r->filename);
ap_filter_t *f)
int ret;
int do_cleanup = 0;
r->filename);
enum xbithack {
#ifdef XBITHACK
return result;
return NULL;
request_rec *r = f->r;
if (!f->ctx) {
return APR_ENOMEM;
ap_add_cgi_vars(r);
send_parsed_content(&b, r, f);
if (parent) {
return OK;
if(ssi_pfn_register) {
{NULL}