mod_dir.c revision 97d1c0756ebea92a6ffcd0d88359311c59740dbc
0734f81384d5f2528bb119f89d135043a280d5b2minfrin/* ====================================================================
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * The Apache Software License, Version 1.1
0734f81384d5f2528bb119f89d135043a280d5b2minfrin *
d96cf063f04828102edbb0b4987c34b490e2731cnd * Copyright (c) 2000 The Apache Software Foundation. All rights
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * reserved.
0734f81384d5f2528bb119f89d135043a280d5b2minfrin *
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * Redistribution and use in source and binary forms, with or without
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * modification, are permitted provided that the following conditions
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * are met:
0734f81384d5f2528bb119f89d135043a280d5b2minfrin *
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * 1. Redistributions of source code must retain the above copyright
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * notice, this list of conditions and the following disclaimer.
0734f81384d5f2528bb119f89d135043a280d5b2minfrin *
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * 2. Redistributions in binary form must reproduce the above copyright
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * notice, this list of conditions and the following disclaimer in
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * the documentation and/or other materials provided with the
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * distribution.
0734f81384d5f2528bb119f89d135043a280d5b2minfrin *
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * 3. The end-user documentation included with the redistribution,
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * if any, must include the following acknowledgment:
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * "This product includes software developed by the
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * Apache Software Foundation (http://www.apache.org/)."
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * Alternately, this acknowledgment may appear in the software itself,
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * if and wherever such third-party acknowledgments normally appear.
0734f81384d5f2528bb119f89d135043a280d5b2minfrin *
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * 4. The names "Apache" and "Apache Software Foundation" must
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * not be used to endorse or promote products derived from this
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * software without prior written permission. For written
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * permission, please contact apache@apache.org.
0734f81384d5f2528bb119f89d135043a280d5b2minfrin *
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * 5. Products derived from this software may not be called "Apache",
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * nor may "Apache" appear in their name, without prior written
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * permission of the Apache Software Foundation.
0734f81384d5f2528bb119f89d135043a280d5b2minfrin *
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh * SUCH DAMAGE.
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh * ====================================================================
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh *
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar * This software consists of voluntary contributions made by many
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh * individuals on behalf of the Apache Software Foundation. For more
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh * information on the Apache Software Foundation, please see
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh * <http://www.apache.org/>.
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh *
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh * Portions of this software are based upon public domain software
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh * originally written at the National Center for Supercomputing Applications,
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar * University of Illinois, Urbana-Champaign.
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh */
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh/*
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh * mod_dir.c: handle default index files, and trailing-/ redirects
0734f81384d5f2528bb119f89d135043a280d5b2minfrin */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin#include "ap_config.h"
0734f81384d5f2528bb119f89d135043a280d5b2minfrin#include "httpd.h"
0734f81384d5f2528bb119f89d135043a280d5b2minfrin#include "http_config.h"
0734f81384d5f2528bb119f89d135043a280d5b2minfrin#include "http_core.h"
0734f81384d5f2528bb119f89d135043a280d5b2minfrin#include "http_request.h"
0734f81384d5f2528bb119f89d135043a280d5b2minfrin#include "http_protocol.h"
0734f81384d5f2528bb119f89d135043a280d5b2minfrin#include "http_log.h"
0734f81384d5f2528bb119f89d135043a280d5b2minfrin#include "http_main.h"
0734f81384d5f2528bb119f89d135043a280d5b2minfrin#include "util_script.h"
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrinmodule MODULE_VAR_EXPORT dir_module;
04e37a05e8fe2c057cfcc546f382d99fa79894c0gryzor
0734f81384d5f2528bb119f89d135043a280d5b2minfrintypedef struct dir_config_struct {
0734f81384d5f2528bb119f89d135043a280d5b2minfrin ap_array_header_t *index_names;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin} dir_config_rec;
9da97ff0bac3a0ff56a9cdebe6e5ab563636aa86jailletc
0734f81384d5f2528bb119f89d135043a280d5b2minfrin#define DIR_CMD_PERMS OR_INDEXES
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrinstatic const char *add_index(cmd_parms *cmd, void *dummy, char *arg)
0734f81384d5f2528bb119f89d135043a280d5b2minfrin{
0734f81384d5f2528bb119f89d135043a280d5b2minfrin dir_config_rec *d = dummy;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin if (!d->index_names) {
0734f81384d5f2528bb119f89d135043a280d5b2minfrin d->index_names = ap_make_array(cmd->pool, 2, sizeof(char *));
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh }
0734f81384d5f2528bb119f89d135043a280d5b2minfrin *(char **)ap_push_array(d->index_names) = arg;
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh return NULL;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin}
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrinstatic const command_rec dir_cmds[] =
0734f81384d5f2528bb119f89d135043a280d5b2minfrin{
0734f81384d5f2528bb119f89d135043a280d5b2minfrin {"DirectoryIndex", add_index, NULL,
0734f81384d5f2528bb119f89d135043a280d5b2minfrin DIR_CMD_PERMS, ITERATE,
0734f81384d5f2528bb119f89d135043a280d5b2minfrin "a list of file names"},
0734f81384d5f2528bb119f89d135043a280d5b2minfrin {NULL}
0734f81384d5f2528bb119f89d135043a280d5b2minfrin};
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrinstatic void *create_dir_config(ap_pool_t *p, char *dummy)
0734f81384d5f2528bb119f89d135043a280d5b2minfrin{
0734f81384d5f2528bb119f89d135043a280d5b2minfrin dir_config_rec *new =
0734f81384d5f2528bb119f89d135043a280d5b2minfrin (dir_config_rec *) ap_pcalloc(p, sizeof(dir_config_rec));
9da97ff0bac3a0ff56a9cdebe6e5ab563636aa86jailletc
0734f81384d5f2528bb119f89d135043a280d5b2minfrin new->index_names = NULL;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin return (void *) new;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin}
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrinstatic void *merge_dir_configs(ap_pool_t *p, void *basev, void *addv)
0734f81384d5f2528bb119f89d135043a280d5b2minfrin{
0734f81384d5f2528bb119f89d135043a280d5b2minfrin dir_config_rec *new = (dir_config_rec *) ap_pcalloc(p, sizeof(dir_config_rec));
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh dir_config_rec *base = (dir_config_rec *) basev;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin dir_config_rec *add = (dir_config_rec *) addv;
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh
0734f81384d5f2528bb119f89d135043a280d5b2minfrin new->index_names = add->index_names ? add->index_names : base->index_names;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin return new;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin}
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrinstatic int handle_dir(request_rec *r)
f8080c631d40d9f23da18c91116ca59d8d5468f6covener{
0734f81384d5f2528bb119f89d135043a280d5b2minfrin dir_config_rec *d =
0734f81384d5f2528bb119f89d135043a280d5b2minfrin (dir_config_rec *) ap_get_module_config(r->per_dir_config,
0734f81384d5f2528bb119f89d135043a280d5b2minfrin &dir_module);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin char *dummy_ptr[1];
0734f81384d5f2528bb119f89d135043a280d5b2minfrin char **names_ptr;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin int num_names;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin int error_notfound = 0;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
9da97ff0bac3a0ff56a9cdebe6e5ab563636aa86jailletc if (r->uri[0] == '\0' || r->uri[strlen(r->uri) - 1] != '/') {
0734f81384d5f2528bb119f89d135043a280d5b2minfrin char *ifile;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin if (r->args != NULL)
0734f81384d5f2528bb119f89d135043a280d5b2minfrin ifile = ap_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri),
0734f81384d5f2528bb119f89d135043a280d5b2minfrin "/", "?", r->args, NULL);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin else
0734f81384d5f2528bb119f89d135043a280d5b2minfrin ifile = ap_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri),
0734f81384d5f2528bb119f89d135043a280d5b2minfrin "/", NULL);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh ap_table_setn(r->headers_out, "Location",
0734f81384d5f2528bb119f89d135043a280d5b2minfrin ap_construct_url(r->pool, ifile, r));
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh return HTTP_MOVED_PERMANENTLY;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin }
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin /* KLUDGE --- make the sub_req lookups happen in the right directory.
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * Fixing this in the sub_req_lookup functions themselves is difficult,
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * and would probably break virtual includes...
0734f81384d5f2528bb119f89d135043a280d5b2minfrin */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin if (r->filename[strlen(r->filename) - 1] != '/') {
0734f81384d5f2528bb119f89d135043a280d5b2minfrin r->filename = ap_pstrcat(r->pool, r->filename, "/", NULL);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin }
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin if (d->index_names) {
0734f81384d5f2528bb119f89d135043a280d5b2minfrin names_ptr = (char **)d->index_names->elts;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin num_names = d->index_names->nelts;
9da97ff0bac3a0ff56a9cdebe6e5ab563636aa86jailletc }
0734f81384d5f2528bb119f89d135043a280d5b2minfrin else {
0734f81384d5f2528bb119f89d135043a280d5b2minfrin dummy_ptr[0] = AP_DEFAULT_INDEX;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin names_ptr = dummy_ptr;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin num_names = 1;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin }
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin for (; num_names; ++names_ptr, --num_names) {
0734f81384d5f2528bb119f89d135043a280d5b2minfrin char *name_ptr = *names_ptr;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin request_rec *rr = ap_sub_req_lookup_uri(name_ptr, r);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin if (rr->status == HTTP_OK && rr->finfo.filetype == APR_REG) {
0734f81384d5f2528bb119f89d135043a280d5b2minfrin char *new_uri = ap_escape_uri(r->pool, rr->uri);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin if (rr->args != NULL)
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh new_uri = ap_pstrcat(r->pool, new_uri, "?", rr->args, NULL);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin else if (r->args != NULL)
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh new_uri = ap_pstrcat(r->pool, new_uri, "?", r->args, NULL);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin ap_destroy_sub_req(rr);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin ap_internal_redirect(new_uri, r);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin return OK;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin }
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin /* If the request returned a redirect, propagate it to the client */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin if (ap_is_HTTP_REDIRECT(rr->status) ||
0734f81384d5f2528bb119f89d135043a280d5b2minfrin (rr->status == HTTP_NOT_ACCEPTABLE && num_names == 1)) {
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin error_notfound = rr->status;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin r->notes = ap_overlay_tables(r->pool, r->notes, rr->notes);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin r->headers_out = ap_overlay_tables(r->pool, r->headers_out,
9da97ff0bac3a0ff56a9cdebe6e5ab563636aa86jailletc rr->headers_out);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin r->err_headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
0734f81384d5f2528bb119f89d135043a280d5b2minfrin rr->err_headers_out);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin return error_notfound;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin }
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin /* If the request returned something other than 404 (or 200),
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * it means the module encountered some sort of problem. To be
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * secure, we should return the error, rather than create
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * along a (possibly unsafe) directory index.
0734f81384d5f2528bb119f89d135043a280d5b2minfrin *
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * So we store the error, and if none of the listed files
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * exist, we return the last error response we got, instead
0734f81384d5f2528bb119f89d135043a280d5b2minfrin * of a directory listing.
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin if (rr->status && rr->status != HTTP_NOT_FOUND && rr->status != HTTP_OK)
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh error_notfound = rr->status;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin ap_destroy_sub_req(rr);
0734f81384d5f2528bb119f89d135043a280d5b2minfrin }
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin if (error_notfound)
0734f81384d5f2528bb119f89d135043a280d5b2minfrin return error_notfound;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin if (r->method_number != M_GET)
0734f81384d5f2528bb119f89d135043a280d5b2minfrin return DECLINED;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin /* nothing for us to do, pass on through */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrin return DECLINED;
0734f81384d5f2528bb119f89d135043a280d5b2minfrin}
9da97ff0bac3a0ff56a9cdebe6e5ab563636aa86jailletc
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrinstatic const handler_rec dir_handlers[] =
0734f81384d5f2528bb119f89d135043a280d5b2minfrin{
0734f81384d5f2528bb119f89d135043a280d5b2minfrin {DIR_MAGIC_TYPE, handle_dir},
0734f81384d5f2528bb119f89d135043a280d5b2minfrin {NULL}
0734f81384d5f2528bb119f89d135043a280d5b2minfrin};
0734f81384d5f2528bb119f89d135043a280d5b2minfrin
0734f81384d5f2528bb119f89d135043a280d5b2minfrinmodule MODULE_VAR_EXPORT dir_module = {
0734f81384d5f2528bb119f89d135043a280d5b2minfrin STANDARD20_MODULE_STUFF,
0734f81384d5f2528bb119f89d135043a280d5b2minfrin create_dir_config, /* create per-directory config structure */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin merge_dir_configs, /* merge per-directory config structures */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin NULL, /* create per-server config structure */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin NULL, /* merge per-server config structures */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin dir_cmds, /* command ap_table_t */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin dir_handlers, /* handlers */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin NULL /* register hooks */
0734f81384d5f2528bb119f89d135043a280d5b2minfrin};
d84dc356814b255affe3abe2ad93ce17f98e632chumbedooh