mod_include.c revision 98233523481f8c5d0de5a8c9a99c5b41c3b2d632
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* ====================================================================
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * The Apache Software License, Version 1.1
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * reserved.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Redistribution and use in source and binary forms, with or without
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * modification, are permitted provided that the following conditions
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * 1. Redistributions of source code must retain the above copyright
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * notice, this list of conditions and the following disclaimer.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * 2. Redistributions in binary form must reproduce the above copyright
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * notice, this list of conditions and the following disclaimer in
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the documentation and/or other materials provided with the
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * distribution.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * 3. The end-user documentation included with the redistribution,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * if any, must include the following acknowledgment:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * "This product includes software developed by the
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Apache Software Foundation (http://www.apache.org/)."
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Alternately, this acknowledgment may appear in the software itself,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * if and wherever such third-party acknowledgments normally appear.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * 4. The names "Apache" and "Apache Software Foundation" must
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * not be used to endorse or promote products derived from this
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * software without prior written permission. For written
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * permission, please contact apache@apache.org.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * 5. Products derived from this software may not be called "Apache",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * nor may "Apache" appear in their name, without prior written
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * permission of the Apache Software Foundation.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * SUCH DAMAGE.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * ====================================================================
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * This software consists of voluntary contributions made by many
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * individuals on behalf of the Apache Software Foundation. For more
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * information on the Apache Software Foundation, please see
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Portions of this software are based upon public domain software
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * originally written at the National Center for Supercomputing Applications,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * University of Illinois, Urbana-Champaign.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * http_include.c: Handles the server-parsed HTML documents
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Original by Rob McCool; substantial fixups by David Robinson;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * incorporated into the Apache module framework by rst.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* helper for Latin1 <-> entity encoding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define RAW_ASCII_CHAR(ch) apr_xlate_conv_byte(ap_hdrs_from_ascii, \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (unsigned char)ch)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#else /* APR_CHARSET_EBCDIC */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif /* !APR_CHARSET_EBCDIC */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * +-------------------------------------------------------+
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * | Types and Structures
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * +-------------------------------------------------------+
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* sll used for string expansion */
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef struct result_item {
33098ea43d4392be70012a7c45a16639abb12439fielding const char *string;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* conditional expression parser stuff */
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef enum {
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef struct {
d96aa158770d3f83cb59cf0f2f7402e175f7dfccrbb const char *value;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *s;
d96aa158770d3f83cb59cf0f2f7402e175f7dfccrbbtypedef struct parse_node {
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef enum {
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef struct {
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef struct {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* main parser states */
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef enum {
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef struct arg_item {
407cde44becba3694e7c3d81ac99b5d86f4b03a9rbbtypedef struct {
407cde44becba3694e7c3d81ac99b5d86f4b03a9rbb const char *source;
407cde44becba3694e7c3d81ac99b5d86f4b03a9rbb const char *rexp;
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef struct {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding unsigned int T[256];
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding unsigned int x;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding apr_size_t parse_pos; /* parse position of partial matches */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *end_seq;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding char *directive; /* name of the current directive */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding apr_size_t directive_len; /* length of the current directive name */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding arg_item_t *current_arg; /* currently parsed argument */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding backref_t *re; /* NULL if there wasn't a regex yet */
407cde44becba3694e7c3d81ac99b5d86f4b03a9rbb * +-------------------------------------------------------+
407cde44becba3694e7c3d81ac99b5d86f4b03a9rbb * | Debugging Utilities
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh * +-------------------------------------------------------+
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (name) = apr_palloc((ctx)->dpool, sizeof(*(name))); \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (name)->parent = (name)->left = (name)->right = NULL; \
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void debug_printf(include_ctx_t *ctx, const char *fmt, ...)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding APR_BRIGADE_INSERT_TAIL(ctx->intern->debug.bb, apr_bucket_pool_create(
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define DUMP__CHILD(ctx, is, node, child) if (1) { \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding debug_printf(ctx, "!!! Parse tree is not consistent !!!\n"); \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding debug_printf(ctx, "Parent of " #child " child node is " \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "NULL.\n"); \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding debug_printf(ctx, "Parent of " #child " child node " \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "points to another node (of type %s)!\n", \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding continue; \
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void debug_dump_tree(include_ctx_t *ctx, parse_node_t *root)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding debug_printf(ctx, "%s%s (%s)\n", is, current->token.s,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (!current->right || current->right->dump_done) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding is = apr_pstrmemdup(ctx->dpool, is, strlen(is) - 4);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if ((!current->left || current->left->dump_done) &&
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding is = apr_pstrmemdup(ctx->dpool, is, strlen(is) - 4);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* it is possible to call this function within the parser loop, to see
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * how the tree is built. That way, we must cleanup after us to dump
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * always the whole tree
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (d__t->type == TOKEN_STRING || d__t->type == TOKEN_RE) { \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding DEBUG_PRINTF(((ctx), " Found: %s (%s)\n", d__t->s, d__t->value)); \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding char c = '"'; \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding debug_printf((ctx), " Evaluate: %s (%s) -> %c\n", (node)->token.s,\
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding debug_printf((ctx), " Evaluate: %s (Left: %s; Right: %s) -> %c\n",\
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (((node)->left->done) ? ((node)->left->value ?"1":"0") \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding : "short circuited"), \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (((node)->right->done) ? ((node)->right->value?"1":"0") \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding : "short circuited"), \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if ((node)->right->token.type == TOKEN_RE) c = '/'; \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding debug_printf((ctx), " Compare: %s (\"%s\" with %c%s%c) -> %c\n", \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding debug_printf((ctx), " Evaluate: %s -> %c\n", (node)->token.s, \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding DEBUG_PRINTF(((ctx), " Unmatched %c\n", (char)(unmatched))); \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding DEBUG_PRINTF(((ctx), "**** %s cond status=\"%c\"\n", (text), \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define DEBUG_DUMP_TREE(ctx, root) debug_dump_tree(ctx, root)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#else /* DEBUG_INCLUDE */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define TYPE_TOKEN(token, ttype) (token)->type = ttype
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (name) = apr_palloc((ctx)->dpool, sizeof(*(name))); \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (name)->parent = (name)->left = (name)->right = NULL; \
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif /* !DEBUG_INCLUDE */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * +-------------------------------------------------------+
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * | Static Module Data
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * +-------------------------------------------------------+
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* global module structure */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* function handlers for include directives */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* forward declaration of handler registry */
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *ssi_pfn_register;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* Sentinel value to store in subprocess_env for items that
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * shouldn't be evaluated until/unless they're actually used
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic const char lazy_eval_sentinel;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* default values */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * +-------------------------------------------------------+
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * +-------------------------------------------------------+
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * decodes a string containing html entities or numeric character references.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * 's' is overwritten with the decoded string.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * If 's' is syntatically incorrect, then the followed fixups will be made:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * unknown entities will be left undecoded;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * references to unused numeric characters will be deleted.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * In particular, � will not be decoded, but will be deleted.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* maximum length of any ISO-LATIN-1 HTML entity name. */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* The following is a shrinking transformation, therefore safe. */
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void decodehtml(char *s)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *ents;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "\333THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "\325Oslash\330Ugrave\331Uacute\332Yacute\335agrave\340"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "aacute\341atilde\343ccedil\347egrave\350eacute\351igrave"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "\354iacute\355ntilde\361ograve\362oacute\363otilde\365"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Do a fast scan through the string until we find anything
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * that needs more complicated handling
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (; *s != '&'; s++) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (*s == '\0') {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (p = s; *s != '\0'; s++, p++) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (*s != '&') {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* find end of entity */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* is it numeric ? */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (j = 2, val = 0; j < i && apr_isdigit(s[j]); j++) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (j < i || val <= 8 || (val >= 11 && val <= 31) ||
d96aa158770d3f83cb59cf0f2f7402e175f7dfccrbb p--; /* no data to output */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* wrong length */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding continue; /* skip it */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (ents = entlist[j]; *ents != '\0'; ents += i) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *p = RAW_ASCII_CHAR(((const unsigned char *) ents)[j]);
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void add_include_vars(request_rec *r, const char *timefmt)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding apr_table_setn(e, "DOCUMENT_PATH_INFO", r->path_info);
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic const char *add_include_vars_lazy(request_rec *r, const char *var)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (include_dir_config *)ap_get_module_config(r->per_dir_config,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding val = ap_ht_time(r->pool, r->request_time, conf->default_time_fmt, 0);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (include_dir_config *)ap_get_module_config(r->per_dir_config,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding val = ap_ht_time(r->pool, r->request_time, conf->default_time_fmt, 1);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (include_dir_config *)ap_get_module_config(r->per_dir_config,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding val = ap_ht_time(r->pool, r->finfo.mtime, conf->default_time_fmt, 0);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (apr_get_username(&val, r->finfo.user, r->pool) != APR_SUCCESS) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic const char *get_include_var(const char *var, include_ctx_t *ctx)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *val;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Handle $0 .. $9 from the last regex evaluated.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * The choice of returning NULL strings on not-found,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * v.s. empty strings on an empty match is deliberate.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "regex capture $%d "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "regex capture $%d is out of range (last regex "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (re->match[idx].rm_so < 0 || re->match[idx].rm_eo < 0) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding val = apr_pstrmemdup(ctx->dpool, re->source + re->match[idx].rm_so,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Do variable substitution on strings
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * (Note: If out==NULL, this function allocs a buffer for the resulting
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * string from ctx->pool. The return value is always the parsed string)
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic char *ap_ssi_parse_string(include_ctx_t *ctx, const char *in, char *out,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *p;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* sanity check, out && !length is not supported */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* fast exit */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ret = apr_pstrmemdup(ctx->pool, in, (length && length <= inlen)
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh /* well, actually something to do */
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh memcpy(out, in, (out+span <= eout) ? span : (eout-out));
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh current = result = apr_palloc(ctx->dpool, sizeof(*result));
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh /* loop for specials */
23cfa61aaed581f103070c8733a493b31f990f9brbb if ((out && out >= eout) || (length && outlen >= length)) {
23cfa61aaed581f103070c8733a493b31f990f9brbb /* prepare next entry */
23cfa61aaed581f103070c8733a493b31f990f9brbb current->next = apr_palloc(ctx->dpool, sizeof(*current->next));
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh * escaped character
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh if (*p == '\\') {
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh * variable expansion
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh else { /* *p == '$' */
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh if (*++p == '{') {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Missing '}' on "
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh /* empty name results in a copy of '$' in the output string */
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh *out++ = *p++;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if ((out && out >= eout) || (length && outlen >= length)) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* check the remainder */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding current->next = apr_palloc(ctx->dpool, sizeof(*current->next));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding memcpy(out, p, (out+span <= eout) ? span : (eout-out));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* assemble result */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *ep;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding memcpy(out, result->string, (out+result->len <= ep)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * +-------------------------------------------------------+
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * | Conditional Expression Parser
b79b743d4cff02d6a830bb7118826a2fd608742amartin * +-------------------------------------------------------+
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic APR_INLINE int re_check(include_ctx_t *ctx, const char *string,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *rexp)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding compiled = ap_pregcomp(ctx->dpool, rexp, REG_EXTENDED);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->intern->r, "unable to "
b79b743d4cff02d6a830bb7118826a2fd608742amartin re = ctx->intern->re = apr_palloc(ctx->pool, sizeof(*re));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding rc = !ap_regexec(compiled, string, MAX_NMATCH, re->match, 0);
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic int get_ptoken(apr_pool_t *pool, const char **parse, token_t *token)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *p;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Skip leading white space */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding TYPE_TOKEN(token, TOKEN_STRING); /* the default type */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding switch (*(*parse)++) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* It's a string or regex token
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Now search for the next token, which finishes this string
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding p = *parse = token->value = unmatched ? *parse : p;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (!*(++*parse)) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding switch (**parse) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *c++ = *++e;
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *error = "Invalid expression \"%s\" in file %s";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding unsigned regex = 0;
44c46ef733836b32585d135d2d90856e7cfd9929rbb /* Create Parse Tree */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding while (1) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* uncomment this to see how the tree a built:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * DEBUG_DUMP_TREE(ctx, root);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding was_unmatched = get_ptoken(ctx->dpool, &parse, &new->token);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, expr,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding while (current && current->token.type != TOKEN_LBRACE) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, expr, r->filename);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Evaluate Parse Tree */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_parse_string(ctx, current->token.value, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "Invalid expression \"%s\" in file %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_parse_string(ctx, current->left->token.value,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding current->left->value = !!*current->left->token.value;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* short circuit evaluation */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ((current->token.type == TOKEN_AND && !current->left->value) ||
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (current->token.type == TOKEN_OR && current->left->value))) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_parse_string(ctx,current->right->token.value,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding current->right->value = !!*current->right->token.value;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "Invalid expression \"%s\" in file %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_parse_string(ctx, current->left->token.value, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_parse_string(ctx, current->right->token.value, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding current->value = re_check(ctx, current->left->token.value,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding current->value = !strcmp(current->left->token.value,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "Invalid expression \"%s\" in file %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_parse_string(ctx, current->left->token.value, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_parse_string(ctx, current->right->token.value, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding current->value = strcmp(current->left->token.value,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding case TOKEN_GE: current->value = current->value >= 0; break;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding case TOKEN_GT: current->value = current->value > 0; break;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding case TOKEN_LE: current->value = current->value <= 0; break;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding case TOKEN_LT: current->value = current->value < 0; break;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding default: current->value = 0; break; /* should not happen */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding error = "No operator before regex in expr \"%s\" in file %s";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding error = "internal parser error in \"%s\" in file %s";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, expr,r->filename);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * +-------------------------------------------------------+
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * | Action Handlers
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * +-------------------------------------------------------+
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Extract the next tag name and value.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * If there are no more tags, set the tag name to NULL.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * The tag value is html decoded if dodecode is non-zero.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * The tag value may be NULL if there is no tag value..
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void ap_ssi_get_tag_and_value(include_ctx_t *ctx, char **tag,
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic int find_file(request_rec *r, const char *directive, const char *tag,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* be safe; only files in this directory or below allowed */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "in parsed file %s";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* note: it is okay to pass NULL for the "next filter" since
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding we never attempt to "run" this sub request. */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (rr->status == HTTP_OK && rr->finfo.filetype != 0) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding APR_FINFO_GPROT | APR_FINFO_MIN, rr->pool)) != APR_SUCCESS
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding error_fmt = "unable to get information about \"%s\" "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "in parsed file %s";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding error_fmt = "unable to lookup information about \"%s\" "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "in parsed file %s";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* note: it is okay to pass NULL for the "next filter" since
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding we never attempt to "run" this sub request. */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (rr->status == HTTP_OK && rr->finfo.filetype != 0) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unable to get "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "information about \"%s\" in parsed file %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unknown parameter \"%s\" "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#include virtual|file="..." [virtual|file="..."] ... -->
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic apr_status_t handle_include(include_ctx_t *ctx, ap_filter_t *f,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding 0, r, "missing argument for include element in %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding while (1) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, SSI_VALUE_DECODED);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (strcmp(tag, "virtual") && strcmp(tag, "file")) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unknown parameter "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding parsed_string = ap_ssi_parse_string(ctx, tag_val, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* be safe; only files in this directory or below allowed */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding error_fmt = "unable to include file \"%s\" in parsed file %s";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding rr = ap_sub_req_lookup_uri(parsed_string, r, f->next);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding error_fmt = "unable to include \"%s\" in parsed file %s";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (!error_fmt && (ctx->flags & SSI_FLAG_NO_EXEC) &&
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding rr->content_type && strncmp(rr->content_type, "text/", 5)) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding error_fmt = "unable to include potential exec \"%s\" in parsed "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* try to avoid recursive includes. We do this by walking
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * up the r->main list of subrequests, and at each level
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * walking back through any internal redirects. At each
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * step, we compare the filenames and the URIs.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * The filename comparison catches a recursive include
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * with an ever-changing URL, eg.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#include virtual=
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * "$REQUEST_URI/$QUERY_STRING?$QUERY_STRING/x" -->
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * which, although they would eventually be caught because
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * we have a limit on the length of files, etc., can
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * recurse for a while.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * The URI comparison catches the case where the filename
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * is changed while processing the request, so the
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * current name is never the same as any previous one.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * This can happen with "DocumentRoot /foo" when you
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * request "/" on the server and it includes "/".
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * This only applies to modules such as mod_dir that
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * (somewhat improperly) mess with r->filename outside
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * of a filename translation phase.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (q = p; q; q = q->prev) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding error_fmt = "Recursive include of \"%s\" in parsed file %s";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* See the Kludge in includes_filter for why.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Basically, it puts a bread crumb in here, then looks
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * for the crumb later to see if its been here.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_set_module_config(rr->request_config, &include_module, r);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding error_fmt = "unable to include \"%s\" in parsed file %s";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error_fmt, tag_val,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* destroy the sub request */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#echo [encoding="..."] var="..." [encoding="..."] var="..." ... -->
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic apr_status_t handle_echo(include_ctx_t *ctx, ap_filter_t *f,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding 0, r, "missing argument for echo element in %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding while (1) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, SSI_VALUE_DECODED);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *val;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding val = get_include_var(ap_ssi_parse_string(ctx, tag_val, NULL,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding sconf = ap_get_module_config(r->server->module_config,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unknown value "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "\"%s\" to parameter \"encoding\" of tag echo in "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unknown parameter "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#config [timefmt="..."] [sizefmt="..."] [errmsg="..."] -->
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic apr_status_t handle_config(include_ctx_t *ctx, ap_filter_t *f,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding 0, r, "missing argument for config element in %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding while (1) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, SSI_VALUE_RAW);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ctx->error_str = ap_ssi_parse_string(ctx, tag_val, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ctx->time_str = ap_ssi_parse_string(ctx, tag_val, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding apr_table_setn(env, "DATE_LOCAL", ap_ht_time(r->pool, date,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding apr_table_setn(env, "DATE_GMT", ap_ht_time(r->pool, date,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding parsed_string = ap_ssi_parse_string(ctx, tag_val, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unknown value "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "\"%s\" to parameter \"sizefmt\" of tag config "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unknown parameter "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#fsize virtual|file="..." [virtual|file="..."] ... -->
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic apr_status_t handle_fsize(include_ctx_t *ctx, ap_filter_t *f,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding 0, r, "missing argument for fsize element in %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding while (1) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, SSI_VALUE_DECODED);
b79b743d4cff02d6a830bb7118826a2fd608742amartin parsed_string = ap_ssi_parse_string(ctx, tag_val, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (!find_file(r, "fsize", tag, parsed_string, &finfo)) {
e8d9dd6a2f39d9c1a647b0b513de84e39e2235ebbjh buf = apr_strfsize(finfo.size, apr_palloc(ctx->pool, 5));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding tmp = apr_psprintf(ctx->dpool, "%" APR_OFF_T_FMT, finfo.size);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (x = 0; x < l; ++x) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (x && !((l - x) % 3)) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (len == l) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (pos = x = 0; x < l; ++x) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (x && !((l - x) % 3)) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(buf, len,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#flastmod virtual|file="..." [virtual|file="..."] ... -->
b79b743d4cff02d6a830bb7118826a2fd608742amartinstatic apr_status_t handle_flastmod(include_ctx_t *ctx, ap_filter_t *f,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding 0, r, "missing argument for flastmod element in %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding while (1) {
b79b743d4cff02d6a830bb7118826a2fd608742amartin ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, SSI_VALUE_DECODED);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding parsed_string = ap_ssi_parse_string(ctx, tag_val, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (!find_file(r, "flastmod", tag, parsed_string, &finfo)) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding t_val = ap_ht_time(ctx->pool, finfo.mtime, ctx->time_str, 0);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(t_val, t_len,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#if expr="..." -->
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic apr_status_t handle_if(include_ctx_t *ctx, ap_filter_t *f,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ? "too many arguments for if element in %s"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding : "missing expr argument for if element in %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_get_tag_and_value(ctx, &tag, &expr, SSI_VALUE_RAW);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unknown parameter \"%s\" "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "missing expr value for if "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding DEBUG_PRINTF((ctx, "**** if expr=\"%s\"\n", expr));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ctx->flags |= (SSI_FLAG_PRINTING | SSI_FLAG_COND_TRUE);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#elif expr="..." -->
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic apr_status_t handle_elif(include_ctx_t *ctx, ap_filter_t *f,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (!(ctx->if_nesting_level)) ? APLOG_ERR : APLOG_WARNING,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ? "too many arguments for if element in %s"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding : "missing expr argument for if element in %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_get_tag_and_value(ctx, &tag, &expr, SSI_VALUE_RAW);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unknown parameter \"%s\" "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "missing expr in elif "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding DEBUG_PRINTF((ctx, "**** elif expr=\"%s\"\n", expr));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ctx->flags |= (SSI_FLAG_PRINTING | SSI_FLAG_COND_TRUE);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#else -->
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic apr_status_t handle_else(include_ctx_t *ctx, ap_filter_t *f,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (!(ctx->if_nesting_level)) ? APLOG_ERR : APLOG_WARNING,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding 0, r, "else directive does not take tags in %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ctx->flags |= (SSI_FLAG_PRINTING | SSI_FLAG_COND_TRUE);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#endif -->
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic apr_status_t handle_endif(include_ctx_t *ctx, ap_filter_t *f,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (!(ctx->if_nesting_level)) ? APLOG_ERR : APLOG_WARNING,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding 0, r, "endif directive does not take tags in %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ctx->flags |= (SSI_FLAG_PRINTING | SSI_FLAG_COND_TRUE);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#set var="..." value="..." ... -->
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic apr_status_t handle_set(include_ctx_t *ctx, ap_filter_t *f,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding 0, r, "missing argument for set element in %s",
d96aa158770d3f83cb59cf0f2f7402e175f7dfccrbb /* we need to use the 'main' request pool to set notes as that is
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * a notes lifetime
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding while (1) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, SSI_VALUE_DECODED);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "variable must "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "precede value in set directive in %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding parsed_string = ap_ssi_parse_string(ctx, tag_val, NULL, 0,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding apr_table_setn(r->subprocess_env, apr_pstrdup(p, var),
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Invalid tag for set "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <!--#printenv -->
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic apr_status_t handle_printenv(include_ctx_t *ctx, ap_filter_t *f,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding 0, r, "printenv directive does not take tags in %s",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* get key */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding key_text = ap_escape_html(ctx->dpool, elts[i].key);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* get value */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding val_text = ap_escape_html(ctx->dpool, elts[i].val);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* assemble result */
b859b5654eeba0b8995b7a46975121029cceda78fielding APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(key_val, kv_length-1,
return APR_SUCCESS;
const char *skip;
while (p < he) {
skip = p;
if (p != pi) {
skip = p;
return hl;
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;
intern->r = r;
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) {
return rv;
r->filename);
f->c->bucket_alloc));
return rv;
return OK;
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.
if (r->args) {
return send_parsed_content(f, b);
return DECLINED;
return DECLINED;
return DECLINED;
return DECLINED;
return DECLINED;
return result;
return result;
return NULL;
const char *tag)
const char *p = tag;
if (apr_isspace(*p)) {
return NULL;
const char *tag)
const char *p = tag;
if (apr_isspace(*p)) {
return NULL;
const char *msg)
return NULL;
const char *msg)
return NULL;
const char *fmt)
return NULL;
if(ssi_pfn_register) {
return OK;
{NULL}