mod_rewrite.c revision 254becf0cdcf0d9631da62ae317c477f6366119c
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd/* ====================================================================
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * The Apache Software License, Version 1.1
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * Copyright (c) 2000 The Apache Software Foundation. All rights
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * reserved.
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * Redistribution and use in source and binary forms, with or without
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * modification, are permitted provided that the following conditions
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * are met:
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * 1. Redistributions of source code must retain the above copyright
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * notice, this list of conditions and the following disclaimer.
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * 2. Redistributions in binary form must reproduce the above copyright
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * notice, this list of conditions and the following disclaimer in
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * the documentation and/or other materials provided with the
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * distribution.
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * 3. The end-user documentation included with the redistribution,
4b6b68ba97661e61b45440c2e520a1fed92169e2nd * if any, must include the following acknowledgment:
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * "This product includes software developed by the
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * Apache Software Foundation (http://www.apache.org/)."
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * Alternately, this acknowledgment may appear in the software itself,
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * if and wherever such third-party acknowledgments normally appear.
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * 4. The names "Apache" and "Apache Software Foundation" must
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * not be used to endorse or promote products derived from this
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * software without prior written permission. For written
4930be147adf9e3f6d3ca9313a6524f9bf654b2dnd * permission, please contact apache@apache.org.
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * 5. Products derived from this software may not be called "Apache",
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * nor may "Apache" appear in their name, without prior written
7eaf2873de4b3d99c119c9b1f0e3465ce00c0359nd * permission of the Apache Software Foundation.
4930be147adf9e3f6d3ca9313a6524f9bf654b2dnd * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4b6b68ba97661e61b45440c2e520a1fed92169e2nd * SUCH DAMAGE.
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd * ====================================================================
4b6b68ba97661e61b45440c2e520a1fed92169e2nd * This software consists of voluntary contributions made by many
4b6b68ba97661e61b45440c2e520a1fed92169e2nd * individuals on behalf of the Apache Software Foundation. For more
4b6b68ba97661e61b45440c2e520a1fed92169e2nd * information on the Apache Software Foundation, please see
4b6b68ba97661e61b45440c2e520a1fed92169e2nd * Portions of this software are based upon public domain software
4b6b68ba97661e61b45440c2e520a1fed92169e2nd * originally written at the National Center for Supercomputing Applications,
4b6b68ba97661e61b45440c2e520a1fed92169e2nd * University of Illinois, Urbana-Champaign.
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** _ __ ___ ___ __| | _ __ _____ ___ __(_) |_ ___
4b6b68ba97661e61b45440c2e520a1fed92169e2nd** | '_ ` _ \ / _ \ / _` | | '__/ _ \ \ /\ / / '__| | __/ _ \
6e6cc280299826341f2e79ad56134d763a54fe43nd** | | | | | | (_) | (_| | | | | __/\ V V /| | | | || __/
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** |_| |_| |_|\___/ \__,_|___|_| \___| \_/\_/ |_| |_|\__\___|
4b6b68ba97661e61b45440c2e520a1fed92169e2nd** URL Rewriting Module
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** This module uses a rule-based rewriting engine (based on a
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** regular-expression parser) to rewrite requested URLs on the fly.
4b6b68ba97661e61b45440c2e520a1fed92169e2nd** It supports an unlimited number of additional rule conditions (which can
f5e4573f2a3ca4b7d7d10bfb50950fa7eff27efbnilgun** operate on a lot of variables, even on HTTP headers) for granular
f5e4573f2a3ca4b7d7d10bfb50950fa7eff27efbnilgun** matching and even external database lookups (either via plain text
f5e4573f2a3ca4b7d7d10bfb50950fa7eff27efbnilgun** tables, DBM hash files or even external processes) for advanced URL
f5e4573f2a3ca4b7d7d10bfb50950fa7eff27efbnilgun** substitution.
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** It operates on the full URLs (including the PATH_INFO part) both in
4b6b68ba97661e61b45440c2e520a1fed92169e2nd** per-server context (httpd.conf) and per-dir context (.htaccess) and even
4b6b68ba97661e61b45440c2e520a1fed92169e2nd** can generate QUERY_STRING parts on result. The rewriting result finally
4b6b68ba97661e61b45440c2e520a1fed92169e2nd** can lead to internal subprocessing, external request redirection or even
4b6b68ba97661e61b45440c2e520a1fed92169e2nd** to internal proxy throughput.
4b6b68ba97661e61b45440c2e520a1fed92169e2nd** This module was originally written in April 1996 and
4930be147adf9e3f6d3ca9313a6524f9bf654b2dnd** gifted exclusively to the The Apache Software Foundation in July 1997 by
4930be147adf9e3f6d3ca9313a6524f9bf654b2dnd** Ralf S. Engelschall
4930be147adf9e3f6d3ca9313a6524f9bf654b2dnd** rse@engelschall.com
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** +-------------------------------------------------------+
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** | static module configuration
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** +-------------------------------------------------------+
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** Our interface to the Apache server kernel:
4b6b68ba97661e61b45440c2e520a1fed92169e2nd** o Runtime logic of a request is as following:
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** while(request or subrequest)
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** foreach(stage #0...#9)
4930be147adf9e3f6d3ca9313a6524f9bf654b2dnd** foreach(module) (**)
4b6b68ba97661e61b45440c2e520a1fed92169e2nd** try to run hook
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** o the order of modules at (**) is the inverted order as
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** given in the "Configuration" file, i.e. the last module
4b6b68ba97661e61b45440c2e520a1fed92169e2nd** specified is the first one called for each hook!
b3027c7641b1104ee50404cca6868e5101a7ca45nd** The core module is always the last!
f42fe4acde21e2937220a00f5977d6e4544c8721nilgun** o there are two different types of result checking and
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd** continue processing:
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd** for hook #0,#1,#4,#5,#6,#8:
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd** hook run loop stops on first modules which gives
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd** back a result != DECLINED, i.e. it usually returns OK
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd** which says "OK, module has handled this _stage_" and for #1
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd** this have not to mean "Ok, the filename is now valid".
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd** for hook #2,#3,#7,#9:
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd** all hooks are run, independend of result
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** o at the last stage, the core module always
008ab149b6efb915d8e0034c0b8266f8c3e3f872nd** - says "HTTP_BAD_REQUEST" if r->filename does not begin with "/"
. ./helpers/find-dbm-lib
{ NULL }
{ NULL }
static void register_hooks(void)
static int proxy_available;
static int once_through = 0;
static const char *lockname;
a->rewriteloglevel = 0;
a->server = s;
sizeof(rewrite_perdir_conf));
sconf =
return NULL;
const char *err;
return err;
const char *name)
return NULL;
return NULL;
return NULL;
const char *a2)
#ifndef NO_DBM_REWRITEMAP
return NULL;
const char *error;
return error;
return NULL;
const char *a1)
return NULL;
const char *in_str)
char *a1;
char *a2;
char *a3;
char *cp;
const char *err;
int rc;
return err;
cp++;
== NULL);
if (rc) {
return NULL;
char *str)
char *cp;
char *cp1;
char *cp2;
char *cp3;
char *key;
char *val;
const char *err;
return err;
return NULL;
return NULL;
const char *in_str)
char *a1;
char *a2;
char *a3;
char *cp;
const char *err;
int mode;
return err;
cp++;
sizeof(rewritecond_entry));
sizeof(rewritecond_entry));
return NULL;
char *str)
char *cp;
char *cp1;
char *cp2;
char *cp3;
char *key;
char *val;
const char *err;
return err;
return NULL;
int status = 0;
if (i < MAX_ENV_FLAGS) {
return NULL;
server_rec *s)
rewritelock_create(s, p);
for (; s; s = s->next) {
open_rewritelog(s, p);
if (once_through > 0)
run_rewritemap_programs(s, p);
once_through++;
void *sconf;
const char *var;
const char *thisserver;
char *thisport;
const char *thisurl;
const char *ccp;
unsigned int port;
return DECLINED;
return DECLINED;
r->filename);
if (!proxy_available) {
return HTTP_FORBIDDEN;
r->filename);
return OK;
n = r->status;
return HTTP_FORBIDDEN;
return HTTP_GONE;
return DECLINED;
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 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;
sizeof(regmatch));
return rc;
char *endp;
goto skip;
goto skip;
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;
char *newuri;
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;
#ifdef NETWARE