mod_setenvif.c revision 5116c0fd82197f5bf0bbe33155cd36a452fcf6ce
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * The Apache Software License, Version 1.1
842ae4bd224140319ae7feec1872b93dfd491143fielding *
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
842ae4bd224140319ae7feec1872b93dfd491143fielding * reserved.
842ae4bd224140319ae7feec1872b93dfd491143fielding *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Redistribution and use in source and binary forms, with or without
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * modification, are permitted provided that the following conditions
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * are met:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 1. Redistributions of source code must retain the above copyright
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * notice, this list of conditions and the following disclaimer.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 2. Redistributions in binary form must reproduce the above copyright
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * notice, this list of conditions and the following disclaimer in
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * the documentation and/or other materials provided with the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * distribution.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
e8f95a682820a599fe41b22977010636be5c2717jim * 3. The end-user documentation included with the redistribution,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * if any, must include the following acknowledgment:
e8f95a682820a599fe41b22977010636be5c2717jim * "This product includes software developed by the
1747d30b98aa1bdbc43994c02cd46ab4cb9319e4fielding * Apache Software Foundation (http://www.apache.org/)."
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Alternately, this acknowledgment may appear in the software itself,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * if and wherever such third-party acknowledgments normally appear.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 4. The names "Apache" and "Apache Software Foundation" must
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * not be used to endorse or promote products derived from this
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * software without prior written permission. For written
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * permission, please contact apache@apache.org.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 5. Products derived from this software may not be called "Apache",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * nor may "Apache" appear in their name, without prior written
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * permission of the Apache Software Foundation.
5c0419d51818eb02045cf923a9fe456127a44c60wrowe *
5c0419d51818eb02045cf923a9fe456127a44c60wrowe * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
d266c3777146d36a4c23c17aad6f153aebea1bf4jorton * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
d266c3777146d36a4c23c17aad6f153aebea1bf4jorton * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
d266c3777146d36a4c23c17aad6f153aebea1bf4jorton * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
d266c3777146d36a4c23c17aad6f153aebea1bf4jorton * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SUCH DAMAGE.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * ====================================================================
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes *
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * This software consists of voluntary contributions made by many
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * individuals on behalf of the Apache Software Foundation. For more
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * information on the Apache Software Foundation, please see
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * <http://www.apache.org/>.
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes *
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * Portions of this software are based upon public domain software
cd3bbd6d2df78d6c75e5d159a81ef8bdd5f70df9trawick * originally written at the National Center for Supercomputing Applications,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * University of Illinois, Urbana-Champaign.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
0568280364eb026393be492ebc732795c4934643jorton/*
0568280364eb026393be492ebc732795c4934643jorton * mod_setenvif.c
0568280364eb026393be492ebc732795c4934643jorton * Set environment variables based on matching request headers or
0568280364eb026393be492ebc732795c4934643jorton * attributes against regex strings
0568280364eb026393be492ebc732795c4934643jorton *
0568280364eb026393be492ebc732795c4934643jorton * Paul Sutton <paul@ukweb.com> 27 Oct 1996
0568280364eb026393be492ebc732795c4934643jorton * Based on mod_browser by Alexei Kosut <akosut@organic.com>
0568280364eb026393be492ebc732795c4934643jorton */
0568280364eb026393be492ebc732795c4934643jorton
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Used to set environment variables based on the incoming request headers,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * or some selected other attributes of the request (e.g., the remote host
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * name).
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Usage:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SetEnvIf name regex var ...
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
796e4a7141265d8ed7036e4628161c6eafb2a789jorton * where name is either a HTTP request header name, or one of the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * special values (see below). The 'value' of the header (or the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * value of the special value from below) are compared against the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * regex argument. If this is a simple string, a simple sub-string
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * match is performed. Otherwise, a request expression match is
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * done. If the value matches the string or regular expression, the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * environment variables listed as var ... are set. Each var can
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * be in one of three formats: var, which sets the named variable
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * (the value value "1"); var=value, which sets the variable to
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * the given value; or !var, which unsets the variable is it has
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * been previously set.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Normally the strings are compared with regard to case. To ignore
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * case, use the directive SetEnvIfNoCase instead.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Special values for 'name' are:
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * remote_host Remote host name (if available)
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe * remote_addr Remote IP address
e8f95a682820a599fe41b22977010636be5c2717jim * remote_user Remote authenticated user (if any)
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe * request_method Request method (GET, POST, etc)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * request_uri Requested URI
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Examples:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * To set the enviroment variable LOCALHOST if the client is the local
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * machine:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SetEnvIf remote_addr 127.0.0.1 LOCALHOST
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
713a2b68bac4aeb1e9c48785006c0732451039depquerna * To set LOCAL if the client is the local host, or within our company's
713a2b68bac4aeb1e9c48785006c0732451039depquerna * domain (192.168.10):
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SetEnvIf remote_addr 192.168.10. LOCAL
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SetEnvIf remote_addr 127.0.0.1 LOCALHOST
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * This could be written as:
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe *
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe * SetEnvIf remote_addr (127.0.0.1|192.168.10.) LOCAL
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "apr.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "apr_strings.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define APR_WANT_STRFUNC
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "apr_want.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "ap_config.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "httpd.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "http_config.h"
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes#include "http_core.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "http_log.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "http_protocol.h"
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesenum special {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SPECIAL_NOT,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SPECIAL_REMOTE_ADDR,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SPECIAL_REMOTE_HOST,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SPECIAL_REMOTE_USER,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SPECIAL_REQUEST_URI,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SPECIAL_REQUEST_METHOD,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SPECIAL_REQUEST_PROTOCOL
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholestypedef struct {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *name; /* header name */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *regex; /* regex to match against */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes regex_t *preg; /* compiled regex */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_table_t *features; /* env vars to set (or unset) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes enum special special_type; /* is it a "special" header ? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int icase; /* ignoring case? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes} sei_entry;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholestypedef struct {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_array_header_t *conditionals;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes} sei_cfg_rec;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesmodule AP_MODULE_DECLARE_DATA setenvif_module;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe * These routines, the create- and merge-config functions, are called
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * for both the server-wide and the per-directory contexts. This is
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * because the different definitions are used at different times; the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * server-wide ones are used in the post-read-request phase, and the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * per-directory ones are used during the header-parse phase (after
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * the URI has been mapped to a file and we have anything from the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * .htaccess file and <Directory> and <Files> containers).
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void *create_setenvif_config(apr_pool_t *p)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sei_cfg_rec *new = (sei_cfg_rec *) apr_palloc(p, sizeof(sei_cfg_rec));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->conditionals = apr_array_make(p, 20, sizeof(sei_entry));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return (void *) new;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void *create_setenvif_config_svr(apr_pool_t *p, server_rec *dummy)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return create_setenvif_config(p);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
8113dac419143273351446c3ad653f3fe5ba5cfdwrowestatic void *create_setenvif_config_dir(apr_pool_t *p, char *dummy)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return create_setenvif_config(p);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void *merge_setenvif_config(apr_pool_t *p, void *basev, void *overridesv)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes sei_cfg_rec *a = apr_pcalloc(p, sizeof(sei_cfg_rec));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sei_cfg_rec *base = basev, *overrides = overridesv;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes a->conditionals = apr_array_append(p, base->conditionals,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes overrides->conditionals);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return a;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * any non-NULL magic constant will do... used to indicate if REG_ICASE should
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * be used
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes */
e8f95a682820a599fe41b22977010636be5c2717jim#define ICASE_MAGIC ((void *)(&setenvif_module))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define SEI_MAGIC_HEIRLOOM "setenvif-phase-flag"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *add_setenvif_core(cmd_parms *cmd, void *mconfig,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *fname, const char *args)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes char *regex;
68d5e906a21c3abe1ebd0da30d2f0e8e4c2ad28cjim const char *feature;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sei_cfg_rec *sconf;
b08925593f214f621161742925dcf074a8047e0acovener sei_entry *new;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sei_entry *entries;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin char *var;
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes int i;
e8f95a682820a599fe41b22977010636be5c2717jim int beenhere = 0;
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes int icase;
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /*
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * Determine from our context into which record to put the entry.
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * cmd->path == NULL means we're in server-wide context; otherwise,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * we're dealing with a per-directory setting.
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes sconf = (cmd->path != NULL)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ? (sei_cfg_rec *) mconfig
ebe5305f8b22507374358f32b74d12fb50c05a25covener : (sei_cfg_rec *) ap_get_module_config(cmd->server->module_config,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes &setenvif_module);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes entries = (sei_entry *) sconf->conditionals->elts;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* get regex */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes regex = ap_getword_conf(cmd->pool, &args);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!*regex) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return apr_pstrcat(cmd->pool, "Missing regular expression for ",
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes cmd->cmd->name, NULL);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * If we've already got a sei_entry with the same name we want to
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * just copy the name pointer... so that later on we can compare
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * two header names just by comparing the pointers.
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes for (i = 0; i < sconf->conditionals->nelts; ++i) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes new = &entries[i];
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!strcasecmp(new->name, fname)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fname = new->name;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes break;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* if the last entry has an identical headername and regex then
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * merge with it
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes i = sconf->conditionals->nelts - 1;
ebe5305f8b22507374358f32b74d12fb50c05a25covener icase = cmd->info == ICASE_MAGIC;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (i < 0
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes || entries[i].name != fname
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes || entries[i].icase != icase
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes || strcmp(entries[i].regex, regex)) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* no match, create a new entry */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
54d22ed1c429b903b029bbd62621f11a9e286137minfrin new = apr_array_push(sconf->conditionals);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes new->name = fname;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes new->regex = regex;
ebe5305f8b22507374358f32b74d12fb50c05a25covener new->icase = icase;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes new->preg = ap_pregcomp(cmd->pool, regex,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes (REG_EXTENDED | REG_NOSUB
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes | (icase ? REG_ICASE : 0)));
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (new->preg == NULL) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return apr_pstrcat(cmd->pool, cmd->cmd->name,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes " regex could not be compiled.", NULL);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->features = apr_table_make(cmd->pool, 2);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
b08925593f214f621161742925dcf074a8047e0acovener if (!strcasecmp(fname, "remote_addr")) {
b08925593f214f621161742925dcf074a8047e0acovener new->special_type = SPECIAL_REMOTE_ADDR;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
7add8f7fb048534390571801b7794f71cd9e127abnicholes else if (!strcasecmp(fname, "remote_host")) {
7add8f7fb048534390571801b7794f71cd9e127abnicholes new->special_type = SPECIAL_REMOTE_HOST;
ebe5305f8b22507374358f32b74d12fb50c05a25covener }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes else if (!strcasecmp(fname, "remote_user")) {
7add8f7fb048534390571801b7794f71cd9e127abnicholes new->special_type = SPECIAL_REMOTE_USER;
7add8f7fb048534390571801b7794f71cd9e127abnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes else if (!strcasecmp(fname, "request_uri")) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes new->special_type = SPECIAL_REQUEST_URI;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes else if (!strcasecmp(fname, "request_method")) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes new->special_type = SPECIAL_REQUEST_METHOD;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
7add8f7fb048534390571801b7794f71cd9e127abnicholes else if (!strcasecmp(fname, "request_protocol")) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes new->special_type = SPECIAL_REQUEST_PROTOCOL;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes else {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes new->special_type = SPECIAL_NOT;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes else {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes new = &entries[i];
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
7add8f7fb048534390571801b7794f71cd9e127abnicholes for ( ; ; ) {
7add8f7fb048534390571801b7794f71cd9e127abnicholes feature = ap_getword_conf(cmd->pool, &args);
141e1368614dc7564e1627671361b01b4869b491bnicholes if (!*feature) {
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes break;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes beenhere++;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
e8f95a682820a599fe41b22977010636be5c2717jim var = ap_getword(cmd->pool, &feature, '=');
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (*feature) {
ebe5305f8b22507374358f32b74d12fb50c05a25covener apr_table_setn(new->features, var, feature);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes else if (*var == '!') {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes apr_table_setn(new->features, var + 1, "!");
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes else {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes apr_table_setn(new->features, var, "1");
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes }
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (!beenhere) {
e8f95a682820a599fe41b22977010636be5c2717jim return apr_pstrcat(cmd->pool, "Missing envariable expression for ",
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes cmd->cmd->name, NULL);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return NULL;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic const char *add_setenvif(cmd_parms *cmd, void *mconfig,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *args)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes char *fname;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* get header name */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes fname = ap_getword_conf(cmd->pool, &args);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (!*fname) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return apr_pstrcat(cmd->pool, "Missing header-field name for ",
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes cmd->cmd->name, NULL);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return add_setenvif_core(cmd, mconfig, fname, args);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes/*
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * This routine handles the BrowserMatch* directives. It simply turns around
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * and feeds them, with the appropriate embellishments, to the general-purpose
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * command handler.
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic const char *add_browser(cmd_parms *cmd, void *mconfig, const char *args)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return add_setenvif_core(cmd, mconfig, "User-Agent", args);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic const command_rec setenvif_module_cmds[] =
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes AP_INIT_RAW_ARGS("SetEnvIf", add_setenvif, NULL,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes OR_FILEINFO, "A header-name, regex and a list of variables."),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes AP_INIT_RAW_ARGS("SetEnvIfNoCase", add_setenvif, ICASE_MAGIC,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes OR_FILEINFO, "a header-name, regex and a list of variables."),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes AP_INIT_RAW_ARGS("BrowserMatch", add_browser, NULL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes OR_FILEINFO, "A browser regex and a list of variables."),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes AP_INIT_RAW_ARGS("BrowserMatchNoCase", add_browser, ICASE_MAGIC,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes OR_FILEINFO, "A browser regex and a list of variables."),
e8f95a682820a599fe41b22977010636be5c2717jim { NULL },
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * This routine gets called at two different points in request processing:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * once before the URI has been translated (during the post-read-request
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * phase) and once after (during the header-parse phase). We use different
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * config records for the two different calls to reduce overhead (by not
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * re-doing the server-wide settings during directory processing), and
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * signal which call it is by having the earlier one pass a flag to the
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * later one.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic int match_headers(request_rec *r)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes sei_cfg_rec *sconf;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes sei_entry *entries;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes apr_table_entry_t *elts;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *val;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes int i, j;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes char *last_name;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (apr_table_get(r->notes, SEI_MAGIC_HEIRLOOM) == NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_table_set(r->notes, SEI_MAGIC_HEIRLOOM, "post-read done");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sconf = (sei_cfg_rec *) ap_get_module_config(r->server->module_config,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes &setenvif_module);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes sconf = (sei_cfg_rec *) ap_get_module_config(r->per_dir_config,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes &setenvif_module);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes entries = (sei_entry *) sconf->conditionals->elts;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes last_name = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes val = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (i = 0; i < sconf->conditionals->nelts; ++i) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sei_entry *b = &entries[i];
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* Optimize the case where a bunch of directives in a row use the
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * same header. Remember we don't need to strcmp the two header
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * names because we made sure the pointers were equal during
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * configuration.
54d22ed1c429b903b029bbd62621f11a9e286137minfrin */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (b->name != last_name) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin last_name = b->name;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin switch (b->special_type) {
e8f95a682820a599fe41b22977010636be5c2717jim case SPECIAL_REMOTE_ADDR:
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe val = r->connection->remote_ip;
8a03cd420b800a2428f49f4617293de9b2387b20jorton break;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin case SPECIAL_REMOTE_HOST:
54d22ed1c429b903b029bbd62621f11a9e286137minfrin val = ap_get_remote_host(r->connection, r->per_dir_config,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin REMOTE_NAME, NULL);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin break;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin case SPECIAL_REMOTE_USER:
54d22ed1c429b903b029bbd62621f11a9e286137minfrin val = r->user;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin break;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin case SPECIAL_REQUEST_URI:
54d22ed1c429b903b029bbd62621f11a9e286137minfrin val = r->uri;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin break;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin case SPECIAL_REQUEST_METHOD:
54d22ed1c429b903b029bbd62621f11a9e286137minfrin val = r->method;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin break;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin case SPECIAL_REQUEST_PROTOCOL:
54d22ed1c429b903b029bbd62621f11a9e286137minfrin val = r->protocol;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin break;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin case SPECIAL_NOT:
edc346c3223efd41e6a2057c37cea69744b73dccwrowe val = apr_table_get(r->headers_in, b->name);
edc346c3223efd41e6a2057c37cea69744b73dccwrowe if (val == NULL) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin val = apr_table_get(r->subprocess_env, b->name);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin break;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /*
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * A NULL value indicates that the header field or special entity
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * wasn't present or is undefined. Represent that as an empty string
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * so that REs like "^$" will work and allow envariable setting
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * based on missing or empty field.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (val == NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes val = "";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim if (!ap_regexec(b->preg, val, 0, NULL, 0)) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe apr_array_header_t *arr = apr_table_elts(b->features);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes elts = (apr_table_entry_t *) arr->elts;
e8f95a682820a599fe41b22977010636be5c2717jim
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe for (j = 0; j < arr->nelts; ++j) {
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe if (!strcmp(elts[j].val, "!")) {
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe apr_table_unset(r->subprocess_env, elts[j].key);
f0f6f1b90ab582896f8a7d56d85bd62a55e57d90covener }
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe else {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin apr_table_setn(r->subprocess_env, elts[j].key, elts[j].val);
560fd0658902ab57754616c172d8953e69fc4722bnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return DECLINED;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void register_hooks(apr_pool_t *p)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_header_parser(match_headers, NULL, NULL, APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_post_read_request(match_headers, NULL, NULL, APR_HOOK_MIDDLE);
560fd0658902ab57754616c172d8953e69fc4722bnicholes}
560fd0658902ab57754616c172d8953e69fc4722bnicholes
560fd0658902ab57754616c172d8953e69fc4722bnicholesmodule AP_MODULE_DECLARE_DATA setenvif_module =
560fd0658902ab57754616c172d8953e69fc4722bnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes STANDARD20_MODULE_STUFF,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes create_setenvif_config_dir, /* dir config creater */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes merge_setenvif_config, /* dir merger --- default is to override */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes create_setenvif_config_svr, /* server config */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes merge_setenvif_config, /* merge server configs */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes setenvif_module_cmds, /* command apr_table_t */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes register_hooks /* register hooks */
e8f95a682820a599fe41b22977010636be5c2717jim};
e8f95a682820a599fe41b22977010636be5c2717jim