mod_alias.c revision 4d7e28c869788fb00bffda29a67f1b10e19f159d
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* ====================================================================
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * The Apache Software License, Version 1.1
bc8fd1b0b1afdf89b8d28eefa8cd74e26ba97986fielding * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * 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
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * 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.
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * 3. The end-user documentation included with the redistribution,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * if any, must include the following acknowledgment:
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * "This product includes software developed by the
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * Apache Software Foundation (http://www.apache.org/)."
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * Alternately, this acknowledgment may appear in the software itself,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * if and wherever such third-party acknowledgments normally appear.
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * 4. The names "Apache" and "Apache Software Foundation" must
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * not be used to endorse or promote products derived from this
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * software without prior written permission. For written
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * permission, please contact apache@apache.org.
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * 5. Products derived from this software may not be called "Apache",
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * nor may "Apache" appear in their name, without prior written
64185f9824e42f21ca7b9ae6c004484215c031a7rbb * permission of the Apache Software Foundation.
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * SUCH DAMAGE.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * ====================================================================
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * This software consists of voluntary contributions made by many
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * individuals on behalf of the Apache Software Foundation. For more
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * information on the Apache Software Foundation, please see
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * Portions of this software are based upon public domain software
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * originally written at the National Center for Supercomputing Applications,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * University of Illinois, Urbana-Champaign.
7708bd70088b64148d7d78fd84ede43ced63c713minfrin * http_alias.c: Stuff for dealing with directory aliases
36a72c96fc2dda27eadbae8a108fa428cc1419c1wrowe * Original by Rob McCool, rewritten in succession by David Robinson
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef struct {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *real;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *fake;
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef struct {
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef struct {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic void *create_alias_config(apr_pool_t *p, server_rec *s)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard (alias_server_conf *) apr_pcalloc(p, sizeof(alias_server_conf));
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard a->aliases = apr_array_make(p, 20, sizeof(alias_entry));
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard a->redirects = apr_array_make(p, 20, sizeof(alias_entry));
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic void *create_alias_dir_config(apr_pool_t *p, char *d)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding a->redirects = apr_array_make(p, 2, sizeof(alias_entry));
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void *merge_alias_config(apr_pool_t *p, void *basev, void *overridesv)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (alias_server_conf *) apr_pcalloc(p, sizeof(alias_server_conf));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding alias_server_conf *base = (alias_server_conf *) basev;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding alias_server_conf *overrides = (alias_server_conf *) overridesv;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding a->aliases = apr_array_append(p, overrides->aliases, base->aliases);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding a->redirects = apr_array_append(p, overrides->redirects, base->redirects);
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void *merge_alias_dir_config(apr_pool_t *p, void *basev, void *overridesv)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding alias_dir_conf *overrides = (alias_dir_conf *) overridesv;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding a->redirects = apr_array_append(p, overrides->redirects, base->redirects);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* need prototype for overlap check */
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic int alias_matches(const char *uri, const char *alias_fakename);
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic const char *add_alias_internal(cmd_parms *cmd, void *dummy,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *f, const char *r,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard alias_server_conf *conf = ap_get_module_config(s->module_config,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard alias_entry *entries = (alias_entry *)conf->aliases->elts;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* XX r can NOT be relative to DocumentRoot here... compat bug. */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard new->regexp = ap_pregcomp(cmd->pool, f, REG_EXTENDED);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return "Regular expression could not be compiled.";
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* XXX This may be optimized, but we must know that new->real
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * exists. If so, we can dir merge later, trusing new->real
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * and just canonicalizing the remainder. Not till I finish
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * cleaning out the old ap_canonical stuff first.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* check for overlapping (Script)Alias directives
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * and throw a warning if found one
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard "The %s command in line %d will probably never "
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard "match. Check previous %sAlias commands for "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding break; /* one warning per alias should be sufficient */
9e2bc52b9409a8d92ce1acd4f6127159a16cbff2ianhstatic const char *add_alias(cmd_parms *cmd, void *dummy, const char *f,
22d348febc3c258df246ac93e37945398dbf0348ianh const char *r)
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic const char *add_alias_regex(cmd_parms *cmd, void *dummy, const char *f,
1d7f1b96b49dafbd6cb414fb709cb85de2686a72chuck const char *r)
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic const char *add_redirect_internal(cmd_parms *cmd,
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe alias_server_conf *serverconf = ap_get_module_config(s->module_config,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard const char *f = arg2;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return "Regular expression could not be compiled.";
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return "URL to redirect to is missing";
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return "Redirect to non-URL";
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return "Redirect URL not valid for this status";
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowestatic const char *add_redirect(cmd_parms *cmd, void *dirconf,
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe const char *arg3)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return add_redirect_internal(cmd, dirconf, arg1, arg2, arg3, 0);
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic const char *add_redirect2(cmd_parms *cmd, void *dirconf,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return add_redirect_internal(cmd, dirconf, arg1, arg2, NULL, 0);
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic const char *add_redirect_regex(cmd_parms *cmd, void *dirconf,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard const char *arg3)
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return add_redirect_internal(cmd, dirconf, arg1, arg2, arg3, 1);
68ce856106f153813339db8670f6cd0ab8dea484minfrin "a fakename and a realname"),
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding AP_INIT_TAKE2("ScriptAlias", add_alias, "cgi-script", RSRC_CONF,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "a fakename and a realname"),
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding AP_INIT_TAKE23("Redirect", add_redirect, (void *) HTTP_MOVED_TEMPORARILY,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "an optional status, then document to be redirected and "
11c3b5180e1de6776035320b012a28bb146e7b46chuck "destination URL"),
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding AP_INIT_TAKE2("AliasMatch", add_alias_regex, NULL, RSRC_CONF,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "a regular expression and a filename"),
11c3b5180e1de6776035320b012a28bb146e7b46chuck AP_INIT_TAKE2("ScriptAliasMatch", add_alias_regex, "cgi-script", RSRC_CONF,
11c3b5180e1de6776035320b012a28bb146e7b46chuck "a regular expression and a filename"),
11c3b5180e1de6776035320b012a28bb146e7b46chuck "an optional status, then a regular expression and "
11c3b5180e1de6776035320b012a28bb146e7b46chuck "destination URL"),
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "a document to be redirected, then the destination URL"),
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "a document to be redirected, then the destination URL"),
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic int alias_matches(const char *uri, const char *alias_fakename)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* any number of '/' in the alias matches any number in
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the supplied URI, but there must be at least one...
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* Other characters are compared literally */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Check last alias path component matched all the way */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/')
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb /* Return number of characters from URI which matched (may be
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * greater than length of alias, since we may have matched
5babe00918c88eda487771fa6d6d4a1a19c0ced0chuck * doubled slashes)
35c9e4d2c0a6465746a98958ef756114834461e6minfrinstatic char *try_alias_list(request_rec *r, apr_array_header_t *aliases,
35c9e4d2c0a6465746a98958ef756114834461e6minfrin alias_entry *entries = (alias_entry *) aliases->elts;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard if (!ap_regexec(p->regexp, r->uri, p->regexp->re_nsub + 1, regm,
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrin /* Do not escape the query string or fragment. */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* need something non-null */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (l > 0) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding escurl = ap_os_escape_path(r->pool, r->uri + l, 1);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard found = apr_pstrcat(r->pool, p->real, r->uri + l, NULL);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (p->handler) { /* Set handler, and leave a note for mod_cgi */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding apr_table_setn(r->notes, "alias-forced-type", r->handler);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* XXX This is as SLOW as can be, next step, we optimize
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * and merge to whatever part of the found path was already
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * canonicalized. After I finish eliminating os canonical.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Better fail test for ap_server_root_relative needed here.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard alias_server_conf *serverconf = ap_get_module_config(sconf, &alias_module);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard if ((ret = try_alias_list(r, serverconf->redirects, 1, &status)) != NULL) {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* include QUERY_STRING if any */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin if ((ret = try_alias_list(r, serverconf->aliases, 0, &status)) != NULL) {
6bdb2c094666367615890147775bb18761216c8dminfrin (alias_dir_conf *) ap_get_module_config(dconf, &alias_module);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* It may have changed since last time, so try again */
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin if ((ret = try_alias_list(r, dirconf->redirects, 1, &status)) != NULL) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "incomplete redirection target of '%s' for "
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe "URI '%s' modified to '%s'",
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe "cannot redirect '%s' to '%s'; "
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe "target is not a valid absoluteURI or abs_path",
4224d5789080ea5586d49420da1e1996f5653bb5ianh ap_hook_translate_name(translate_alias_redir,NULL,aszSucc,APR_HOOK_MIDDLE);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_hook_fixups(fixup_redir,NULL,NULL,APR_HOOK_MIDDLE);
af952917c05e56874069e1e5f64e6473bb478b68minfrin merge_alias_dir_config, /* dir merger --- default is to override */