mod_rewrite.c revision 6f984345bbfa9342dde1f2b7b8c35b7987d078af
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * The Apache Software License, Version 1.1
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 2000 The Apache Software Foundation. All rights
842ae4bd224140319ae7feec1872b93dfd491143fielding * reserved.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Redistribution and use in source and binary forms, with or without
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * modification, are permitted provided that the following conditions
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 1. Redistributions of source code must retain the above copyright
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * notice, this list of conditions and the following disclaimer.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 2. Redistributions in binary form must reproduce the above copyright
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * notice, this list of conditions and the following disclaimer in
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the documentation and/or other materials provided with the
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh * distribution.
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh * 3. The end-user documentation included with the redistribution,
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh * if any, must include the following acknowledgment:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * "This product includes software developed by the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Apache Software Foundation (http://www.apache.org/)."
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * Alternately, this acknowledgment may appear in the software itself,
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * if and wherever such third-party acknowledgments normally appear.
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * 4. The names "Apache" and "Apache Software Foundation" must
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * not be used to endorse or promote products derived from this
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * software without prior written permission. For written
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * permission, please contact apache@apache.org.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * 5. Products derived from this software may not be called "Apache",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * nor may "Apache" appear in their name, without prior written
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * permission of the Apache Software Foundation.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
51af95bb51b5084e883bad250b2afa2838e9ceebfielding * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
d4f1d9c1ff112a8ab9bee31f196973761329b236rbb * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
7fae9cc4639013f3c04c085547256c68814aee8ftrawick * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
7fae9cc4639013f3c04c085547256c68814aee8ftrawick * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
7fae9cc4639013f3c04c085547256c68814aee8ftrawick * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
7fae9cc4639013f3c04c085547256c68814aee8ftrawick * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
36ef8f77bffe75d1aa327882be1b5bdbe2ff567asf * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * SUCH DAMAGE.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * ====================================================================
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * This software consists of voluntary contributions made by many
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * individuals on behalf of the Apache Software Foundation. For more
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * information on the Apache Software Foundation, please see
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Portions of this software are based upon public domain software
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * originally written at the National Center for Supercomputing Applications,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * University of Illinois, Urbana-Champaign.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** _ __ ___ ___ __| | _ __ _____ ___ __(_) |_ ___
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** | '_ ` _ \ / _ \ / _` | | '__/ _ \ \ /\ / / '__| | __/ _ \
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** | | | | | | (_) | (_| | | | | __/\ V V /| | | | || __/
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** |_| |_| |_|\___/ \__,_|___|_| \___| \_/\_/ |_| |_|\__\___|
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** URL Rewriting Module
785be1b6298010956622771c870ab3cd8ca57a2faaron** This module uses a rule-based rewriting engine (based on a
785be1b6298010956622771c870ab3cd8ca57a2faaron** regular-expression parser) to rewrite requested URLs on the fly.
785be1b6298010956622771c870ab3cd8ca57a2faaron** It supports an unlimited number of additional rule conditions (which can
785be1b6298010956622771c870ab3cd8ca57a2faaron** operate on a lot of variables, even on HTTP headers) for granular
785be1b6298010956622771c870ab3cd8ca57a2faaron** matching and even external database lookups (either via plain text
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim** tables, DBM hash files or even external processes) for advanced URL
7697b1b7376a532163c621e050b70c90dcb15d66covener** substitution.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** It operates on the full URLs (including the PATH_INFO part) both in
f4b96a996afbc46872f57ad1450e6ee1c8f13707jorton** per-server context (httpd.conf) and per-dir context (.htaccess) and even
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** can generate QUERY_STRING parts on result. The rewriting result finally
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** can lead to internal subprocessing, external request redirection or even
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** to internal proxy throughput.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** This module was originally written in April 1996 and
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** gifted exclusively to the The Apache Software Foundation in July 1997 by
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** Ralf S. Engelschall
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** rse@engelschall.com
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** +-------------------------------------------------------+
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** | static module configuration
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** +-------------------------------------------------------+
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** Our interface to the Apache server kernel:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** o Runtime logic of a request is as following:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** while(request or subrequest)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** foreach(stage #0...#9)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** foreach(module) (**)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** try to run hook
e8f95a682820a599fe41b22977010636be5c2717jim** o the order of modules at (**) is the inverted order as
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick** given in the "Configuration" file, i.e. the last module
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** specified is the first one called for each hook!
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick** The core module is always the last!
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick** o there are two different types of result checking and
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick** continue processing:
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski** for hook #0,#1,#4,#5,#6,#8:
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick** hook run loop stops on first modules which gives
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick** back a result != DECLINED, i.e. it usually returns OK
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** which says "OK, module has handled this _stage_" and for #1
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick** this have not to mean "Ok, the filename is now valid".
785be1b6298010956622771c870ab3cd8ca57a2faaron** for hook #2,#3,#7,#9:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** all hooks are run, independend of result
3c290fd0361d6d9d84d97725eaf299456bddd6cfsf** o at the last stage, the core module always
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick** - says "HTTP_BAD_REQUEST" if r->filename does not begin with "/"
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames** - prefix URL with document_root or replaced server_root
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames** with document_root and sets r->filename
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames** - always return a "OK" independed if the file really exists
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames /* The section for the Configure script:
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * XXX: this needs updating for apache-2.0 configuration method
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * MODULE-DEFINITION-START
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * Name: rewrite_module
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * ConfigStart
560f6ac786d611b858b2bad932713d9e971f0716trawick if [ "x$found_dbm" = "x1" ]; then
560f6ac786d611b858b2bad932713d9e971f0716trawick echo " enabling DBM support for mod_rewrite"
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick echo " disabling DBM support for mod_rewrite"
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick echo " (perhaps you need to add -ldbm, -lndbm or -lgdbm to EXTRA_LIBS)"
7bf77d70b6830636bc36e6b76a228c301be23ff7brianp CFLAGS="$CFLAGS -DNO_DBM_REWRITEMAP"
7bf77d70b6830636bc36e6b76a228c301be23ff7brianp * ConfigEnd
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * MODULE-DEFINITION-END
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick /* the module (predeclaration) */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* the cache */
de00ec7378227d05be63ecd2053ebbb01b940023jorton /* whether proxy module is available or not */
de00ec7378227d05be63ecd2053ebbb01b940023jortonstatic const char *lockname;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick** +-------------------------------------------------------+
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid** | configuration directive handling
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid** +-------------------------------------------------------+
97c78987224dcd037076d393aad1867c26b2c8cftrawick** per-server configuration structure handling
97c78987224dcd037076d393aad1867c26b2c8cftrawickstatic void *config_server_create(apr_pool_t *p, server_rec *s)
97c78987224dcd037076d393aad1867c26b2c8cftrawick a = (rewrite_server_conf *)apr_pcalloc(p, sizeof(rewrite_server_conf));
785be1b6298010956622771c870ab3cd8ca57a2faaron a->rewritemaps = apr_make_array(p, 2, sizeof(rewritemap_entry));
785be1b6298010956622771c870ab3cd8ca57a2faaron a->rewriteconds = apr_make_array(p, 2, sizeof(rewritecond_entry));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding a->rewriterules = apr_make_array(p, 2, sizeof(rewriterule_entry));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return (void *)a;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void *config_server_merge(apr_pool_t *p, void *basev, void *overridesv)
785be1b6298010956622771c870ab3cd8ca57a2faaron a = (rewrite_server_conf *)apr_pcalloc(p, sizeof(rewrite_server_conf));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * local directives override
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and anything else is inherited
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding a->rewriteloglevel = overrides->rewriteloglevel != 0
c5d006b2861d49c61bcf79316163e30611c6fd08trawick a->rewritelogfile = overrides->rewritelogfile != NULL
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim a->rewritemaps = apr_append_arrays(p, overrides->rewritemaps,
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim a->rewriteconds = apr_append_arrays(p, overrides->rewriteconds,
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier a->rewriterules = apr_append_arrays(p, overrides->rewriterules,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * local directives override
f4b96a996afbc46872f57ad1450e6ee1c8f13707jorton * and anything else gets defaults
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return (void *)a;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** per-directory configuration structure handling
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void *config_perdir_create(apr_pool_t *p, char *path)
785be1b6298010956622771c870ab3cd8ca57a2faaron a = (rewrite_perdir_conf *)apr_pcalloc(p, sizeof(rewrite_perdir_conf));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding a->rewriteconds = apr_make_array(p, 2, sizeof(rewritecond_entry));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding a->rewriterules = apr_make_array(p, 2, sizeof(rewriterule_entry));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* make sure it has a trailing slash */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return (void *)a;
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawickstatic void *config_perdir_merge(apr_pool_t *p, void *basev, void *overridesv)
a7ed9c525f9460187f327cea953bf90ecf1bdc51gstein a->rewriteconds = apr_append_arrays(p, overrides->rewriteconds,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding a->rewriterules = apr_append_arrays(p, overrides->rewriterules,
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick return (void *)a;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick** the configuration commands
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *cmd_rewriteengine(cmd_parms *cmd,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (rewrite_server_conf *)ap_get_module_config(cmd->server->module_config,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding sconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED);
785be1b6298010956622771c870ab3cd8ca57a2faaron else /* is per-directory command */ {
785be1b6298010956622771c870ab3cd8ca57a2faaron dconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *cmd_rewriteoptions(cmd_parms *cmd,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *err;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_get_module_config(cmd->server->module_config, &rewrite_module);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else { /* is per-directory command */
e8f95a682820a599fe41b22977010636be5c2717jimstatic const char *cmd_rewriteoptions_setoption(apr_pool_t *p, int *options,
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener const char *name)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_pstrcat(p, "RewriteOptions: unknown option '",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *cmd_rewritelog(cmd_parms *cmd, void *dconf, const char *a1)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_get_module_config(cmd->server->module_config, &rewrite_module);
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covenerstatic const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, const char *a1)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_get_module_config(cmd->server->module_config, &rewrite_module);
7c6f514f2ef9b98f58b8f8a5f534eb78a75f29f2jortonstatic const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, const char *a1,
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf const char *a2)
7c6f514f2ef9b98f58b8f8a5f534eb78a75f29f2jorton ap_get_module_config(cmd->server->module_config, &rewrite_module);
785be1b6298010956622771c870ab3cd8ca57a2faaron newmap->checkfile = apr_pstrcat(cmd->pool, a2+4, NDBM_FILE_SUFFIX, NULL);
785be1b6298010956622771c870ab3cd8ca57a2faaron return apr_pstrdup(cmd->pool, "RewriteMap: cannot use NDBM mapfile, "
785be1b6298010956622771c870ab3cd8ca57a2faaron "because no NDBM support is compiled in");
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier return apr_pstrcat(cmd->pool, "RewriteMap: internal map not found:",
7697b1b7376a532163c621e050b70c90dcb15d66covener if (newmap->checkfile && (sconf->state == ENGINE_ENABLED)
7697b1b7376a532163c621e050b70c90dcb15d66covener && (apr_stat(&st, newmap->checkfile, APR_FINFO_NORM,
785be1b6298010956622771c870ab3cd8ca57a2faaron "RewriteMap: map file or program not found:",
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanfstatic const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, const char *a1)
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf const char *error;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf if ((error = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanfstatic const char *cmd_rewritebase(cmd_parms *cmd, void *in_dconf,
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf const char *a1)
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim return "RewriteBase: only valid in per-directory config files";
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim return "RewriteBase: empty URL not allowed";
7697b1b7376a532163c621e050b70c90dcb15d66covener return "RewriteBase: argument is not a valid URL";
7697b1b7376a532163c621e050b70c90dcb15d66covenerstatic const char *cmd_rewritecond(cmd_parms *cmd, void *in_dconf,
7697b1b7376a532163c621e050b70c90dcb15d66covener const char *in_str)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *err;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_get_module_config(cmd->server->module_config, &rewrite_module);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* make a new entry in the internal temporary rewrite rule list */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else { /* is per-directory command */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* parse the argument line ourself */
785be1b6298010956622771c870ab3cd8ca57a2faaron return apr_pstrcat(cmd->pool, "RewriteCond: bad argument line '", str,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* arg1: the input string */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* arg3: optional flags field
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (this have to be first parsed, because we need to
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding know if the regex should be compiled with ICASE!) */
785be1b6298010956622771c870ab3cd8ca57a2faaron if ((err = cmd_rewritecond_parseflagfield(cmd->pool, newcond,
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* arg2: the pattern
7697b1b7376a532163c621e050b70c90dcb15d66covener try to compile the regexp to test if is ok */
785be1b6298010956622771c870ab3cd8ca57a2faaron /* now be careful: Under the POSIX regex library
785be1b6298010956622771c870ab3cd8ca57a2faaron we can compile the pattern for case insensitive matching,
785be1b6298010956622771c870ab3cd8ca57a2faaron under the old V8 library we have to do it self via a hack */
785be1b6298010956622771c870ab3cd8ca57a2faaron rc = ((regexp = ap_pregcomp(cmd->pool, cp, REG_EXTENDED|REG_ICASE))
7697b1b7376a532163c621e050b70c90dcb15d66covener rc = ((regexp = ap_pregcomp(cmd->pool, cp, REG_EXTENDED)) == NULL);
785be1b6298010956622771c870ab3cd8ca57a2faaron "RewriteCond: cannot compile regular expression '",
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic const char *cmd_rewritecond_parseflagfield(apr_pool_t *p,
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *err;
785be1b6298010956622771c870ab3cd8ca57a2faaron return "RewriteCond: bad flag delimiters";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding str[strlen(str)-1] = ','; /* for simpler parsing */
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick /* skip whitespaces */
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick for ( ; (*cp == ' ' || *cp == '\t') && *cp != '\0'; cp++)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((err = cmd_rewritecond_setflag(p, cfg, key, val)) != NULL) {
e08076ca56e6cb68b30846b9e9339061058aae6dpoirierstatic const char *cmd_rewritecond_setflag(apr_pool_t *p, rewritecond_entry *cfg,
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf return apr_pstrcat(p, "RewriteCond: unknown flag '", key, "'", NULL);
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanfstatic const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf,
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf const char *in_str)
9c518951a46c7a12e20876827bb2e84ef87d3c11jerenkrantz const char *err;
9c518951a46c7a12e20876827bb2e84ef87d3c11jerenkrantz ap_get_module_config(cmd->server->module_config, &rewrite_module);
4f133508c93204c06e1acba9774ff184e5812606niq /* make a new entry in the internal rewrite rule list */
4f133508c93204c06e1acba9774ff184e5812606niq else { /* is per-directory command */
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick /* parse the argument line ourself */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_pstrcat(cmd->pool, "RewriteRule: bad argument line '", str,
43c3e6a4b559b76b750c245ee95e2782c15b4296jim /* arg3: optional flags field */
0db1b9810f06c0e3c537e0e0dfbc30160c308526trawick if ((err = cmd_rewriterule_parseflagfield(cmd->pool, newrule,
3c8b3749225668f06abbb2b023a833a2cef46931brianp /* arg1: the pattern
3c8b3749225668f06abbb2b023a833a2cef46931brianp * try to compile the regexp to test if is ok
785be1b6298010956622771c870ab3cd8ca57a2faaron if ((regexp = ap_pregcomp(cmd->pool, cp, mode)) == NULL) {
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick "RewriteRule: cannot compile regular expression '",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* arg2: the output string
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf * replace the $<N> by \<n> which is needed by the currently
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf * used Regular Expression library
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf * TODO: Is this still required for PCRE? If not, does it *work* with PCRE?
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* now, if the server or per-dir config holds an
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * array of RewriteCond entries, we take it for us
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and clear the array
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else { /* is per-directory command */
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic const char *cmd_rewriterule_parseflagfield(apr_pool_t *p,
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *err;
785be1b6298010956622771c870ab3cd8ca57a2faaron return "RewriteRule: bad flag delimiters";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding str[strlen(str)-1] = ','; /* for simpler parsing */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* skip whitespaces */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for ( ; (*cp == ' ' || *cp == '\t') && *cp != '\0'; cp++)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for ( ; (*(cp2-1) == ' ' || *(cp2-1) == '\t'); cp2--)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((err = cmd_rewriterule_setflag(p, cfg, key, val)) != NULL) {
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic const char *cmd_rewriterule_setflag(apr_pool_t *p, rewriterule_entry *cfg,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return "RewriteRule: invalid HTTP response code "
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "for flag 'R'";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0; (cfg->env[i] != NULL) && (i < MAX_ENV_FLAGS); i++)
785be1b6298010956622771c870ab3cd8ca57a2faaron return "RewriteRule: too many environment flags 'E'";
f7407ba6bea5ed1151cfcefcfa774b531c26eecdrpluem return apr_pstrcat(p, "RewriteRule: unknown flag '", key, "'", NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** Global Module Initialization
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** [called from read_config() after all
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** config commands were already called]
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_get_userdata(&data, userdata_key, s->process->pool);
785be1b6298010956622771c870ab3cd8ca57a2faaron /* check if proxy module is available */
785be1b6298010956622771c870ab3cd8ca57a2faaron proxy_available = (ap_find_linked_module("mod_proxy.c") != NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* create the rewriting lockfiles in the parent */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((rv = apr_create_lock (&rewrite_log_lock, APR_MUTEX, APR_LOCKALL,
785be1b6298010956622771c870ab3cd8ca57a2faaron "mod_rewrite: could not create rewrite_log_lock");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_register_cleanup(p, (void *)s, rewritelock_remove, apr_null_cleanup);
51af95bb51b5084e883bad250b2afa2838e9ceebfielding /* step through the servers and
785be1b6298010956622771c870ab3cd8ca57a2faaron * - open each rewriting logfile
785be1b6298010956622771c870ab3cd8ca57a2faaron * - open the RewriteMap prg:xxx programs
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (; s; s = s->next) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** Per-Child Module Initialization
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** [called after a child process is spawned]
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void init_child(apr_pool_t *p, server_rec *s)
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna rv = apr_child_init_lock (&rewrite_mapr_lock, lockname, p);
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna "mod_rewrite: could not init rewrite_mapr_lock "
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna "in child");
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna /* create the lookup cache */
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna** +-------------------------------------------------------+
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna** | runtime hooks
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna** +-------------------------------------------------------+
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna** URI-to-filename hook
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna** [used for the rewriting engine triggered by
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna** the per-server 'RewriteRule' directives]
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna const char *var;
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna const char *thisurl;
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna const char *ccp;
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna unsigned int port;
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna * retrieve the config structures
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding conf = (rewrite_server_conf *)ap_get_module_config(sconf,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * only do something under runtime if the engine is really enabled,
8f8ec0957334f50b7ac11359f90490ee467258eedreid * else return immediately!
785be1b6298010956622771c870ab3cd8ca57a2faaron * check for the ugly API case of a virtual host section where no
785be1b6298010956622771c870ab3cd8ca57a2faaron * mod_rewrite directives exists. In this situation we became no chance
785be1b6298010956622771c870ab3cd8ca57a2faaron * by the API to setup our default per-server config so we have to
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * on-the-fly assume we have the default config. But because the default
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * config has a disabled rewriting engine we are lucky because can
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * just stop operating now.
785be1b6298010956622771c870ab3cd8ca57a2faaron * add the SCRIPT_URL variable to the env. this is a bit complicated
785be1b6298010956622771c870ab3cd8ca57a2faaron * due to the fact that apache uses subrequests and internal redirects
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf var = apr_pstrcat(r->pool, "REDIRECT_", ENVVAR_SCRIPT_URL, NULL);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf apr_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, r->uri);
r->filename);
if (!proxy_available) {
return HTTP_FORBIDDEN;
r->filename);
return OK;
n = r->status;
return HTTP_FORBIDDEN;
return HTTP_GONE;
return DECLINED;
#if APR_HAS_USER
return HTTP_BAD_REQUEST;
(r->filename +
r->filename);
return OK;
return DECLINED;
if (t == NULL) {
return DECLINED;
r->filename, t);
r->content_type = t;
return OK;
char *cp;
char *cp2;
const char *ccp;
char *prefix;
char *ofilename;
return DECLINED;
return DECLINED;
return DECLINED;
return HTTP_FORBIDDEN;
return DECLINED;
return OK;
n = r->status;
return HTTP_FORBIDDEN;
return HTTP_GONE;
return HTTP_BAD_REQUEST;
return OK;
r->filename+l);
return OK;
return DECLINED;
return DECLINED;
return DECLINED;
return OK;
char *perdir)
int changed;
int rc;
changed = 0;
loop:
p = &entries[i];
if (rc) {
goto loop;
if (p->skip > 0) {
s = p->skip;
p = &entries[i];
p = &entries[i];
return changed;
char *perdir)
char *uri;
char *output;
const char *vary;
int prefixstrip;
int failed;
int rc;
prefixstrip = 0;
sizeof(regmatch));
failed = 0;
c = &conds[i];
if (rc == 0) {
c = &conds[i];
if (rc == 0) {
if (failed) {
p->forced_mimetype);
reduce_uri(r);
r->filename);
p->forced_mimetype);
int rc;
rc = 0;
#if !defined(OS2)
sizeof(regmatch));
return rc;
char *endp;
goto skip;
goto skip;
if (result) {
char *var;
span = 0;
skip:
space--;
char *olduri;
if (q != NULL) {
if (qsappend) {
r->filename);
char *cp;
unsigned short port;
char *portp;
char *hostp;
char *url;
char *olduri;
c = *cp;
*cp = c;
const char *thisserver;
char *thisport;
int port;
#if APR_HAS_USER
char *newuri;
char *homedir;
return newuri;
void *sconf;
rewritemap_entry *s;
char *value;
s = &entries[i];
return NULL;
if ((value =
return value;
return NULL;
#ifndef NO_DBM_REWRITEMAP
return NULL;
if ((value =
return value;
return NULL;
return NULL;
if ((value =
return value;
return value;
return NULL;
if ((value =
return NULL;
return value;
return NULL;
char *cpT;
char *curkey;
char *curval;
return NULL;
if (skip == 0)
++cpT;
if (skip == 0)
return value;
#ifndef NO_DBM_REWRITEMAP
return value;
#ifndef NO_WRITEV
return NULL;
if (rewrite_mapr_lock) {
#ifdef NO_WRITEV
buf[i++] = c;
if (rewrite_mapr_lock) {
return NULL;
char *key)
cp++) {
return value;
cp++) {
return value;
char *value;
return value;
char *value;
return value;
static int rewrite_rand_init_done = 0;
static void rewrite_rand_init(void)
if (!rewrite_rand_init_done) {
static int rewrite_rand(int l, int h)
char *buf;
return value;
return buf;
const char *fname;
char *str1;
char *ruser;
const char *rhost;
(unsigned long)(r->server), (unsigned long)r,
return APR_SUCCESS;
#ifdef SIGHUP
!= APR_SUCCESS) ||
if (fpin) {
if (fpout) {
if (fperr) {
return (rc);
const char *result;
#ifndef WIN32
/* XXX: wow this has gotta be slow if you actually use it for a lot, recalculates exploded time for each variable */
return (char *)result; \
return NULL;
cache *c;
return NULL;
return NULL;
return NULL;
return NULL;
return n % CACHE_TLB_ROWS;
char *key)
for (i=0; i < CACHE_TLB_COLS; ++i) {
return NULL;
return &elt[j];
return NULL;
cacheentry *e)
cachelist *l;
cacheentry *e;
cachetlbentry *t;
int found_list;
found_list = 0;
if (e != NULL) {
if (!found_list) {
sizeof(cachetlbentry));
for (i=0; i<CACHE_TLB_ROWS; ++i) {
for (j=0; j<CACHE_TLB_COLS; ++j)
cachelist *l;
cacheentry *e;
if (e != NULL)
return NULL;
const char *subst)
char *output;
return output;
char *cp;
int isquoted;
cp++; \
isquoted = 0; \
cp++; \
cp++; \
char *cp;
char *cp;
for (i = 0; i < n1; i++) {
int depth;
else if (*s == left) {
++depth;
return NULL;
int depth;
return NULL;
else if (*s == left) {
++depth;
return NULL;
#ifdef NETWARE
{ NULL }