request.c revision c57336f883da78c094fdb20659be5b92a9431b15
60a4b2c422dcbb08a554fb193105c08da592718bpoirier/* ====================================================================
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * The Apache Software License, Version 1.1
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * reserved.
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * Redistribution and use in source and binary forms, with or without
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * modification, are permitted provided that the following conditions
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * 1. Redistributions of source code must retain the above copyright
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * notice, this list of conditions and the following disclaimer.
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * 2. Redistributions in binary form must reproduce the above copyright
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * notice, this list of conditions and the following disclaimer in
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * the documentation and/or other materials provided with the
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * distribution.
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * 3. The end-user documentation included with the redistribution,
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * if any, must include the following acknowledgment:
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung * "This product includes software developed by the
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * Apache Software Foundation (http://www.apache.org/)."
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * Alternately, this acknowledgment may appear in the software itself,
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * if and wherever such third-party acknowledgments normally appear.
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * 4. The names "Apache" and "Apache Software Foundation" must
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * not be used to endorse or promote products derived from this
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * software without prior written permission. For written
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * permission, please contact apache@apache.org.
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * 5. Products derived from this software may not be called "Apache",
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * nor may "Apache" appear in their name, without prior written
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * permission of the Apache Software Foundation.
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * SUCH DAMAGE.
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * ====================================================================
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * This software consists of voluntary contributions made by many
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * individuals on behalf of the Apache Software Foundation. For more
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * information on the Apache Software Foundation, please see
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * Portions of this software are based upon public domain software
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * originally written at the National Center for Supercomputing Applications,
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * University of Illinois, Urbana-Champaign.
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * http_request.c: functions to get and process requests
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * Rob McCool 3/21/93
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * Thoroughly revamped by rst for Apache. NB this file reads
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * best from the bottom up.
bcb2c4ef861e8f8260284631b6753e1088643c8asfAP_IMPLEMENT_HOOK_VOID(insert_filter, (request_rec *r), (r))
bcb2c4ef861e8f8260284631b6753e1088643c8asfAP_IMPLEMENT_HOOK_RUN_ALL(int,create_request,(request_rec *r),(r),OK,DECLINED)
bcb2c4ef861e8f8260284631b6753e1088643c8asfstatic int decl_die(int status, char *phase, request_rec *r)
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, 0, r,
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick/* This is the master logic for processing requests. Do NOT duplicate
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * this logic elsewhere, or the security model will be broken by future
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * API changes. Each phase must be individually optimized to pick up
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * redundant/duplicate calls by subrequests, and redirects.
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawickAP_DECLARE(int) ap_process_request_internal(request_rec *r)
0236ede61169f34359c234625a1d792b97d7db12nd /* Ignore embedded %2F's in path for proxy requests */
60a4b2c422dcbb08a554fb193105c08da592718bpoirier access_status = ap_unescape_url(r->parsed_uri.path);
60a4b2c422dcbb08a554fb193105c08da592718bpoirier ap_getparents(r->uri); /* OK --- shrinking transformations... */
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf /* All file subrequests are a huge pain... they cannot bubble through the
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * next several steps. Only file subrequests are allowed an empty uri,
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * otherwise let translate_name kill the request.
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf /* Reset to the server default config prior to running map_to_storage
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick /* This request wasn't in storage (e.g. TRACE) */
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick /* Excluding file-specific requests with no 'true' URI...
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf /* Rerun the location walk, which overrides any map_to_storage config.
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick /* Only on the main request! */
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick /* Skip authn/authz if the parent or prior request passed the authn/authz,
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * and that configuration didn't change (this requires optimized _walk()
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * functions in map_to_storage that use the same merge results given
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * identical input.) If the config changes, we must re-auth.
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick if (r->main && (r->main->per_dir_config == r->per_dir_config)) {
60a4b2c422dcbb08a554fb193105c08da592718bpoirier else if (r->prev && (r->prev->per_dir_config == r->per_dir_config)) {
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick switch (ap_satisfies(r)) {
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf if (((access_status = ap_run_check_user_id(r)) != 0) || !ap_auth_type(r)) {
b6529ec5115d80b7dedcfd0935746015b2096084minfrin ? "check user. No user file?"
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick : "perform authentication. AuthType not set!", r);
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick if (((access_status = ap_run_auth_checker(r)) != 0) || !ap_auth_type(r)) {
b6529ec5115d80b7dedcfd0935746015b2096084minfrin ? "check access. No groups file?"
b6529ec5115d80b7dedcfd0935746015b2096084minfrin : "perform authentication. AuthType not set!", r);
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf if (((access_status = ap_run_access_checker(r)) != 0) || !ap_auth_type(r)) {
b6529ec5115d80b7dedcfd0935746015b2096084minfrin ? "check access"
b6529ec5115d80b7dedcfd0935746015b2096084minfrin : "perform authentication. AuthType not set!", r);
b6529ec5115d80b7dedcfd0935746015b2096084minfrin if (((access_status = ap_run_check_user_id(r)) != 0) || !ap_auth_type(r)) {
b6529ec5115d80b7dedcfd0935746015b2096084minfrin ? "check user. No user file?"
b6529ec5115d80b7dedcfd0935746015b2096084minfrin : "perform authentication. AuthType not set!", r);
78f97ce162b66a0dbfd7af4dcd9984f162569b04minfrin if (((access_status = ap_run_auth_checker(r)) != 0) || !ap_auth_type(r)) {
78f97ce162b66a0dbfd7af4dcd9984f162569b04minfrin ? "check access. No groups file?"
78f97ce162b66a0dbfd7af4dcd9984f162569b04minfrin : "perform authentication. AuthType not set!", r);
60a4b2c422dcbb08a554fb193105c08da592718bpoirier /* XXX Must make certain the ap_run_type_checker short circuits mime
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * in mod-proxy for r->proxyreq && r->parsed_uri.scheme
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * && !strcmp(r->parsed_uri.scheme, "http")
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick /* The new insert_filter stage makes sense here IMHO. We are sure that
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * we are going to run the request now, so we may as well insert filters
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * if any are available. Since the goal of this phase is to allow all
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * modules to insert a filter if they want to, this filter returns
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * void. I just can't see any way that this filter can reasonably
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * fail, either your modules inserts something or it doesn't. rbb
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf/* Useful caching structures to repeat _walk/merge sequences as required
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * when a subrequest or redirect reuses substantially the same config.
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * Directive order in the httpd.conf file and its Includes significantly
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * impact this optimization. Grouping common blocks at the front of the
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * config that are less likely to change between a request and
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * its subrequests, or between a request and its redirects reduced
60a4b2c422dcbb08a554fb193105c08da592718bpoirier * the work of these functions significantly.
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sftypedef struct walk_walked_t {
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf ap_conf_vector_t *matched; /* A dir_conf sections we matched */
60a4b2c422dcbb08a554fb193105c08da592718bpoirier ap_conf_vector_t *merged; /* The dir_conf merged result */
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawicktypedef struct walk_cache_t {
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf ap_conf_vector_t **dir_conf_tested;/* The sections we matched against */
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf ap_conf_vector_t *dir_conf_merged;/* Base per_dir_config */
60a4b2c422dcbb08a554fb193105c08da592718bpoirier ap_conf_vector_t *per_dir_result; /* per_dir_config += walked result */
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick apr_array_header_t *walked; /* The list of walk_walked_t results */
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sfstatic walk_cache_t *prep_walk_cache(const char *cache_name, request_rec *r)
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf /* Find the most relevant, recent entry to work from. That would be
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * this request (on the second call), or the parent request of a
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * subrequest, or the prior request of an internal redirect. Provide
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * this _walk()er with a copy it is allowed to munge. If there is no
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf * parent or prior cached request, then create a new walk cache.
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf cache->walked = apr_array_make(r->pool, 4, sizeof(walk_walked_t));
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick apr_pool_userdata_setn(cache, cache_name, NULL, r->pool);
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick/*****************************************************************
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick * Getting and checking directory configuration. Also checks the
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick * FollowSymlinks and FollowSymOwner stuff, since this is really the
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick * only place that can happen (barring a new mid_dir_walk callout).
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick * We can't do it as an access_checker module function which gets
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick * called with the final per_dir_config, since we could have a directory
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf * with FollowSymLinks disabled, which contains a symlink to another
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick * with a .htaccess file which turns FollowSymLinks back on --- and
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick * access in such a case must be denied. So, whatever it is that
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick * checks FollowSymLinks needs to know the state of the options as
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick * they change, all the way down.
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick * We don't want people able to serve up pipes, or unix sockets, or other
33e4ab6c78a779cb3f72f7afed0fef9068f1b822trawick * scary things. Note that symlink tests are performed later.
68e7d4f7d80c3e5ed94185cb28100bc786e4304atrawick ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
68e7d4f7d80c3e5ed94185cb28100bc786e4304atrawick "object is not a file, directory or symlink: %s",
68e7d4f7d80c3e5ed94185cb28100bc786e4304atrawick * resolve_symlink must _always_ be called on an APR_LNK file type!
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf * It will resolve the actual target file type, modification date, etc,
68e7d4f7d80c3e5ed94185cb28100bc786e4304atrawick * and provide any processing required for symlink evaluation.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * Path must already be cleaned, no trailing slash, no multi-slashes,
2509f1cd3be884abbe4852e15b8da00bebaad5b1poirier * and don't call this on the root!
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * Simply, the number of times we deref a symlink are minimal compared
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * to the number of times we had an extra lstat() since we 'weren't sure'.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * To optimize, we stat() anything when given (opts & OPT_SYM_LINKS), otherwise
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * we start off with an lstat(). Every lstat() must be dereferenced in case
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * it points at a 'nasty' - we must always rerun check_safe_file (or similar.)
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawickstatic int resolve_symlink(char *d, apr_finfo_t *lfi, int opts, apr_pool_t *p)
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick if ((res = apr_stat(&fi, d, lfi->valid, p)) != APR_SUCCESS)
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick /* Give back the target */
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick /* OPT_SYM_OWNER only works if we can get the owner of
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * both the file and symlink. First fill in a missing
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * owner of the symlink, then get the info of the target.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick if ((res = apr_lstat(&fi, d, lfi->valid | APR_FINFO_OWNER, p))
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick if ((res = apr_stat(&fi, d, lfi->valid, p)) != APR_SUCCESS)
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick if (apr_compare_users(fi.user, lfi->user) != APR_SUCCESS)
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick /* Give back the target */
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick/*****************************************************************
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * Getting and checking directory configuration. Also checks the
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * FollowSymlinks and FollowSymOwner stuff, since this is really the
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * only place that can happen (barring a new mid_dir_walk callout).
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * We can't do it as an access_checker module function which gets
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * called with the final per_dir_config, since we could have a directory
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * with FollowSymLinks disabled, which contains a symlink to another
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * with a .htaccess file which turns FollowSymLinks back on --- and
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * access in such a case must be denied. So, whatever it is that
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * checks FollowSymLinks needs to know the state of the options as
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * they change, all the way down.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick core_server_config *sconf = ap_get_module_config(r->server->module_config,
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick ap_conf_vector_t **sec_ent = (ap_conf_vector_t **) sconf->sec_dir->elts;
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick /* XXX: Better (faster) tests needed!!!
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * "OK" as a response to a real problem is not _OK_, but to allow broken
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * modules to proceed, we will permit the not-a-path filename to pass here.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * We must catch it later if it's heading for the core handler. Leave an
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * INFO note here for module debugging.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick if (r->filename == NULL || !ap_os_is_path_absolute(r->pool, r->filename)) {
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick "Module bug? Request filename path %s is missing or "
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick "or not absolute for uri %s",
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * r->path_info tracks the remaining source path.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * r->filename tracks the path as we build it.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * we begin our adventure at the root...
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick if ((rv = apr_filepath_merge(&entry_dir, NULL, r->filename,
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
8cef90cad1b259d4a94f6095aa30439c60549a5drbowen "Module bug? Request filename path %s is invalid or "
8cef90cad1b259d4a94f6095aa30439c60549a5drbowen "or not absolute for uri %s",
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * Go down the directory hierarchy. Where we have to check for symlinks,
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * do so. Where a .htaccess file has permission to override anything,
46fc29754beed5aa71b9dd9a69a85cc840b307f8minfrin * try to find one.
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick cache = prep_walk_cache("ap_directory_walk::cache", r);
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick entry_dir = ap_make_dirstr_parent(r->pool, entry_dir);
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick else if (r->filename[strlen(r->filename) - 1] != '/')
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick entry_dir = apr_pstrcat(r->pool, r->filename, "/", NULL);
9cb641b95a976f28161ff3eb5dc71105a8f75ddeminfrin /* If we have a file already matches the path of r->filename,
9cb641b95a976f28161ff3eb5dc71105a8f75ddeminfrin * and the vhost's list of directory sections hasn't changed,
46fc29754beed5aa71b9dd9a69a85cc840b307f8minfrin * we can skip rewalking the directory_walk entries.
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick if (cache->cached && ((r->finfo.filetype == APR_REG)
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick /* Well this looks really familiar! If our end-result (per_dir_result)
b97ba9a0b0f1bdad0bd7b4c5cb32319c2976b0aftrawick * didn't change, we have absolutely nothing to do :)
46fc29754beed5aa71b9dd9a69a85cc840b307f8minfrin * Otherwise (as is the case with most dir_merged/file_merged requests)
46fc29754beed5aa71b9dd9a69a85cc840b307f8minfrin * we must merge our dir_conf_merged onto this new r->per_dir_config.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick /* We start now_merged from NULL since we want to build
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * a locations list that can be merged to any vhost.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts;
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * We must play our own mimi-merge game here, for the few
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * running dir_config values we care about within dir_walk.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * We didn't start the merge from r->per_dir_config, so we
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick * accumulate opts and override as we merge, from the globals.
2d5f033e0b60accdc5c92470a71c6e9cd6c90803trawick this_dir = ap_get_module_config(r->per_dir_config, &core_module);
5cd08ee4a8f5a665e656f70048a1268a02bc0e73sf /* XXX: Remerge path_info, or we are broken. Needs more thought.
60a4b2c422dcbb08a554fb193105c08da592718bpoirier r->path_info = ap_make_full_path(r->pool, r->filename,
60a4b2c422dcbb08a554fb193105c08da592718bpoirier (const char **)&r->path_info,
sec_idx = 0;
int res;
char *seg_name;
char *delim;
if (matches) {
++last_walk;
--matches;
goto minimerge;
matches = 0;
if (now_merged)
* See core.c::merge_core_dir_configs() for explanation.
if (!this_dir)
if (res)
return res;
if (htaccess_conf) {
if (matches) {
++last_walk;
--matches;
goto minimerge2;
matches = 0;
if (now_merged)
* See core.c::merge_core_dir_configs() for explanation.
if (this_dir)
if (delim) {
++seg_name;
if (!*seg_name)
return res;
r->filename);
++seg;
if (!entry_core->r)
if (matches) {
++last_walk;
--matches;
goto minimerge;
matches = 0;
if (now_merged)
if (matches)
x * APR_DIR test. But if you accessed /symlink/index.html, for example,
if (now_merged)
r->per_dir_config,
return OK;
&core_module);
const char *entry_uri;
if (!num_sec) {
return OK;
/* Location and LocationMatch differ on their behaviour w.r.t. multiple
* Otherwise (as is the case with most dir_merged/file_merged requests)
return OK;
return OK;
if (entry_core->r
if (matches) {
++last_walk;
--matches;
matches = 0;
if (now_merged)
if (matches)
if (now_merged)
r->per_dir_config,
return OK;
&core_module);
const char *test_file;
return OK;
if (!num_sec) {
return OK;
return OK;
return OK;
int sec_idx;
if (entry_core->r
if (matches) {
++last_walk;
--matches;
matches = 0;
if (now_merged)
if (matches)
if (now_merged)
r->per_dir_config,
return OK;
return rr;
if (next_filter) {
if (APR_BUCKET_IS_EOS(e)) {
return APR_SUCCESS;
if (!reqs_arr)
const char *new_file,
const request_rec *r,
int res;
char *udir;
return rnew;
const request_rec *r,
const request_rec *r,
int res;
char *fdir;
char *udir;
return rnew;
return rnew;
const request_rec *r,
int res;
char *fdir;
return rnew;
return rnew;
int retval;
return retval;