842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * http://www.apache.org/licenses/LICENSE-2.0
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * Unless required by applicable law or agreed to in writing, software
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * distributed under the License is distributed on an "AS IS" BASIS,
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * See the License for the specific language governing permissions and
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * limitations under the License.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/*
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * mod_dir.c: handle default index files, and trailing-/ redirects
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
b6055b7832a0e4d0818416252fff5925aaebae4brbb#include "apr_strings.h"
78b046ee9f769d9609ea1157177d5467e4700c89covener#include "apr_lib.h"
2d71630471d1c23f0137309e3c3957c633ecbfd6rbb#include "ap_config.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "httpd.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "http_config.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "http_core.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "http_request.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "http_protocol.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "http_log.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "http_main.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "util_script.h"
cc06c8e7a7e785b46083984731b701d0c5447c72covener#include "mod_rewrite.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
3d96ee83babeec32482c9082c9426340cee8c44dwrowemodule AP_MODULE_DECLARE_DATA dir_module;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
2d84861186d70e5396751ba308bb90c8a7db47acndtypedef enum {
128148f61cfed630b051d26e3e2018f774b21595covener MODDIR_OFF = 0,
128148f61cfed630b051d26e3e2018f774b21595covener MODDIR_ON,
128148f61cfed630b051d26e3e2018f774b21595covener MODDIR_UNSET
128148f61cfed630b051d26e3e2018f774b21595covener} moddir_cfg;
2d84861186d70e5396751ba308bb90c8a7db47acnd
78b046ee9f769d9609ea1157177d5467e4700c89covener#define REDIRECT_OFF 0
78b046ee9f769d9609ea1157177d5467e4700c89covener#define REDIRECT_UNSET 1
78b046ee9f769d9609ea1157177d5467e4700c89covener
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingtypedef struct dir_config_struct {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_array_header_t *index_names;
128148f61cfed630b051d26e3e2018f774b21595covener moddir_cfg do_slash;
111436a32ba1254291e4883292fb116d15fe8f64covener moddir_cfg checkhandler;
78b046ee9f769d9609ea1157177d5467e4700c89covener int redirect_index;
e991c6fc032c59eb6cb751d9d382e933a53a2866niq const char *dflt;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding} dir_config_rec;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define DIR_CMD_PERMS OR_INDEXES
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
4f9a74ad7e44b0464f7cf56525a205d788becacbtrawickstatic const char *add_index(cmd_parms *cmd, void *dummy, const char *arg)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding dir_config_rec *d = dummy;
b6d2c204c150843e48f6787c1090ae75b718896ecovener const char *t, *w;
b6d2c204c150843e48f6787c1090ae75b718896ecovener int count = 0;
7076b40ea4800c8f91c4c0948f9c98c1bacbe96crpluem
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (!d->index_names) {
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron d->index_names = apr_array_make(cmd->pool, 2, sizeof(char *));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
b6d2c204c150843e48f6787c1090ae75b718896ecovener
b6d2c204c150843e48f6787c1090ae75b718896ecovener t = arg;
7076b40ea4800c8f91c4c0948f9c98c1bacbe96crpluem while ((w = ap_getword_conf(cmd->pool, &t)) && w[0]) {
7076b40ea4800c8f91c4c0948f9c98c1bacbe96crpluem if (count == 0 && !strcasecmp(w, "disabled")) {
b6d2c204c150843e48f6787c1090ae75b718896ecovener /* peek to see if "disabled" is first in a series of arguments */
b6d2c204c150843e48f6787c1090ae75b718896ecovener const char *tt = t;
4e0565f42481dff87062cbfc55a2ecaa36b92e83sf const char *ww = ap_getword_conf(cmd->temp_pool, &tt);
34243b1c811496ed65f33a321a61612b8b8627ebjailletc if (ww[0] == '\0') {
b6d2c204c150843e48f6787c1090ae75b718896ecovener /* "disabled" is first, and alone */
b158fcda2fabac5e85b75e51cadc918d3eb4a218covener apr_array_clear(d->index_names);
b94e9fbfc855aa89c2a7340c5ca9da5d1cb9f7e3covener break;
b6d2c204c150843e48f6787c1090ae75b718896ecovener }
b6d2c204c150843e48f6787c1090ae75b718896ecovener }
b6d2c204c150843e48f6787c1090ae75b718896ecovener *(const char **)apr_array_push(d->index_names) = w;
b6d2c204c150843e48f6787c1090ae75b718896ecovener count++;
63de18ba5e922ffaab500317d7d1d0ad6b27b7e2covener }
b6d2c204c150843e48f6787c1090ae75b718896ecovener
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return NULL;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
2d84861186d70e5396751ba308bb90c8a7db47acndstatic const char *configure_slash(cmd_parms *cmd, void *d_, int arg)
2d84861186d70e5396751ba308bb90c8a7db47acnd{
2d84861186d70e5396751ba308bb90c8a7db47acnd dir_config_rec *d = d_;
2d84861186d70e5396751ba308bb90c8a7db47acnd
128148f61cfed630b051d26e3e2018f774b21595covener d->do_slash = arg ? MODDIR_ON : MODDIR_OFF;
2d84861186d70e5396751ba308bb90c8a7db47acnd return NULL;
2d84861186d70e5396751ba308bb90c8a7db47acnd}
111436a32ba1254291e4883292fb116d15fe8f64covenerstatic const char *configure_checkhandler(cmd_parms *cmd, void *d_, int arg)
111436a32ba1254291e4883292fb116d15fe8f64covener{
111436a32ba1254291e4883292fb116d15fe8f64covener dir_config_rec *d = d_;
111436a32ba1254291e4883292fb116d15fe8f64covener
111436a32ba1254291e4883292fb116d15fe8f64covener d->checkhandler = arg ? MODDIR_ON : MODDIR_OFF;
111436a32ba1254291e4883292fb116d15fe8f64covener return NULL;
111436a32ba1254291e4883292fb116d15fe8f64covener}
78b046ee9f769d9609ea1157177d5467e4700c89covenerstatic const char *configure_redirect(cmd_parms *cmd, void *d_, const char *arg1)
78b046ee9f769d9609ea1157177d5467e4700c89covener{
78b046ee9f769d9609ea1157177d5467e4700c89covener dir_config_rec *d = d_;
78b046ee9f769d9609ea1157177d5467e4700c89covener int status;
78b046ee9f769d9609ea1157177d5467e4700c89covener
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim if (!strcasecmp(arg1, "ON"))
78b046ee9f769d9609ea1157177d5467e4700c89covener status = HTTP_MOVED_TEMPORARILY;
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim else if (!strcasecmp(arg1, "OFF"))
78b046ee9f769d9609ea1157177d5467e4700c89covener status = REDIRECT_OFF;
78b046ee9f769d9609ea1157177d5467e4700c89covener else if (!strcasecmp(arg1, "permanent"))
78b046ee9f769d9609ea1157177d5467e4700c89covener status = HTTP_MOVED_PERMANENTLY;
78b046ee9f769d9609ea1157177d5467e4700c89covener else if (!strcasecmp(arg1, "temp"))
78b046ee9f769d9609ea1157177d5467e4700c89covener status = HTTP_MOVED_TEMPORARILY;
78b046ee9f769d9609ea1157177d5467e4700c89covener else if (!strcasecmp(arg1, "seeother"))
78b046ee9f769d9609ea1157177d5467e4700c89covener status = HTTP_SEE_OTHER;
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim else if (apr_isdigit(*arg1)) {
78b046ee9f769d9609ea1157177d5467e4700c89covener status = atoi(arg1);
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim if (!ap_is_HTTP_REDIRECT(status)) {
78b046ee9f769d9609ea1157177d5467e4700c89covener return "DirectoryIndexRedirect only accepts values between 300 and 399";
78b046ee9f769d9609ea1157177d5467e4700c89covener }
78b046ee9f769d9609ea1157177d5467e4700c89covener }
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim else {
78b046ee9f769d9609ea1157177d5467e4700c89covener return "DirectoryIndexRedirect ON|OFF|permanent|temp|seeother|3xx";
78b046ee9f769d9609ea1157177d5467e4700c89covener }
2d84861186d70e5396751ba308bb90c8a7db47acnd
78b046ee9f769d9609ea1157177d5467e4700c89covener d->redirect_index = status;
78b046ee9f769d9609ea1157177d5467e4700c89covener return NULL;
78b046ee9f769d9609ea1157177d5467e4700c89covener}
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic const command_rec dir_cmds[] =
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
80370e62044bea458bcd0545c59cb864ed117b04niq AP_INIT_TAKE1("FallbackResource", ap_set_string_slot,
e991c6fc032c59eb6cb751d9d382e933a53a2866niq (void*)APR_OFFSETOF(dir_config_rec, dflt),
e991c6fc032c59eb6cb751d9d382e933a53a2866niq DIR_CMD_PERMS, "Set a default handler"),
b6d2c204c150843e48f6787c1090ae75b718896ecovener AP_INIT_RAW_ARGS("DirectoryIndex", add_index, NULL, DIR_CMD_PERMS,
4f9a74ad7e44b0464f7cf56525a205d788becacbtrawick "a list of file names"),
2d84861186d70e5396751ba308bb90c8a7db47acnd AP_INIT_FLAG("DirectorySlash", configure_slash, NULL, DIR_CMD_PERMS,
2d84861186d70e5396751ba308bb90c8a7db47acnd "On or Off"),
111436a32ba1254291e4883292fb116d15fe8f64covener AP_INIT_FLAG("DirectoryCheckHandler", configure_checkhandler, NULL, DIR_CMD_PERMS,
111436a32ba1254291e4883292fb116d15fe8f64covener "On or Off"),
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim AP_INIT_TAKE1("DirectoryIndexRedirect", configure_redirect,
78b046ee9f769d9609ea1157177d5467e4700c89covener NULL, DIR_CMD_PERMS, "On, Off, or a 3xx status code."),
78b046ee9f769d9609ea1157177d5467e4700c89covener
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding {NULL}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding};
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void *create_dir_config(apr_pool_t *p, char *dummy)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron dir_config_rec *new = apr_pcalloc(p, sizeof(dir_config_rec));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding new->index_names = NULL;
128148f61cfed630b051d26e3e2018f774b21595covener new->do_slash = MODDIR_UNSET;
111436a32ba1254291e4883292fb116d15fe8f64covener new->checkhandler = MODDIR_UNSET;
78b046ee9f769d9609ea1157177d5467e4700c89covener new->redirect_index = REDIRECT_UNSET;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return (void *) new;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void *merge_dir_configs(apr_pool_t *p, void *basev, void *addv)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron dir_config_rec *new = apr_pcalloc(p, sizeof(dir_config_rec));
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron dir_config_rec *base = (dir_config_rec *)basev;
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron dir_config_rec *add = (dir_config_rec *)addv;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding new->index_names = add->index_names ? add->index_names : base->index_names;
2d84861186d70e5396751ba308bb90c8a7db47acnd new->do_slash =
128148f61cfed630b051d26e3e2018f774b21595covener (add->do_slash == MODDIR_UNSET) ? base->do_slash : add->do_slash;
111436a32ba1254291e4883292fb116d15fe8f64covener new->checkhandler =
111436a32ba1254291e4883292fb116d15fe8f64covener (add->checkhandler == MODDIR_UNSET) ? base->checkhandler : add->checkhandler;
78b046ee9f769d9609ea1157177d5467e4700c89covener new->redirect_index=
78b046ee9f769d9609ea1157177d5467e4700c89covener (add->redirect_index == REDIRECT_UNSET) ? base->redirect_index : add->redirect_index;
e991c6fc032c59eb6cb751d9d382e933a53a2866niq new->dflt = add->dflt ? add->dflt : base->dflt;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return new;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
e991c6fc032c59eb6cb751d9d382e933a53a2866niqstatic int fixup_dflt(request_rec *r)
e991c6fc032c59eb6cb751d9d382e933a53a2866niq{
e991c6fc032c59eb6cb751d9d382e933a53a2866niq dir_config_rec *d = ap_get_module_config(r->per_dir_config, &dir_module);
e991c6fc032c59eb6cb751d9d382e933a53a2866niq const char *name_ptr;
e991c6fc032c59eb6cb751d9d382e933a53a2866niq request_rec *rr;
e991c6fc032c59eb6cb751d9d382e933a53a2866niq int error_notfound = 0;
1eda27e7224742a68c18c09a7f5ae233363465a4niq
e991c6fc032c59eb6cb751d9d382e933a53a2866niq name_ptr = d->dflt;
5695f522f64e4b842be9dc438666fd91a89cc10bgryzor if ((name_ptr == NULL) || !(strcasecmp(name_ptr,"disabled"))){
a1efede5943e76f1fcdf10494de41704c9ba70f1niq return DECLINED;
a1efede5943e76f1fcdf10494de41704c9ba70f1niq }
80370e62044bea458bcd0545c59cb864ed117b04niq /* XXX: if FallbackResource points to something that doesn't exist,
a1efede5943e76f1fcdf10494de41704c9ba70f1niq * this may recurse until it hits the limit for internal redirects
a1efede5943e76f1fcdf10494de41704c9ba70f1niq * before returning an Internal Server Error.
a1efede5943e76f1fcdf10494de41704c9ba70f1niq */
a1efede5943e76f1fcdf10494de41704c9ba70f1niq
a1efede5943e76f1fcdf10494de41704c9ba70f1niq /* The logic of this function is basically cloned and simplified
a1efede5943e76f1fcdf10494de41704c9ba70f1niq * from fixup_dir below. See the comments there.
a1efede5943e76f1fcdf10494de41704c9ba70f1niq */
e991c6fc032c59eb6cb751d9d382e933a53a2866niq if (r->args != NULL) {
e991c6fc032c59eb6cb751d9d382e933a53a2866niq name_ptr = apr_pstrcat(r->pool, name_ptr, "?", r->args, NULL);
e991c6fc032c59eb6cb751d9d382e933a53a2866niq }
e991c6fc032c59eb6cb751d9d382e933a53a2866niq rr = ap_sub_req_lookup_uri(name_ptr, r, r->output_filters);
e991c6fc032c59eb6cb751d9d382e933a53a2866niq if (rr->status == HTTP_OK
e991c6fc032c59eb6cb751d9d382e933a53a2866niq && ( (rr->handler && !strcmp(rr->handler, "proxy-server"))
e991c6fc032c59eb6cb751d9d382e933a53a2866niq || rr->finfo.filetype == APR_REG)) {
e991c6fc032c59eb6cb751d9d382e933a53a2866niq ap_internal_fast_redirect(rr, r);
e991c6fc032c59eb6cb751d9d382e933a53a2866niq return OK;
e991c6fc032c59eb6cb751d9d382e933a53a2866niq }
e991c6fc032c59eb6cb751d9d382e933a53a2866niq else if (ap_is_HTTP_REDIRECT(rr->status)) {
e991c6fc032c59eb6cb751d9d382e933a53a2866niq
e991c6fc032c59eb6cb751d9d382e933a53a2866niq apr_pool_join(r->pool, rr->pool);
e991c6fc032c59eb6cb751d9d382e933a53a2866niq r->notes = apr_table_overlay(r->pool, r->notes, rr->notes);
e991c6fc032c59eb6cb751d9d382e933a53a2866niq r->headers_out = apr_table_overlay(r->pool, r->headers_out,
e991c6fc032c59eb6cb751d9d382e933a53a2866niq rr->headers_out);
e991c6fc032c59eb6cb751d9d382e933a53a2866niq r->err_headers_out = apr_table_overlay(r->pool, r->err_headers_out,
e991c6fc032c59eb6cb751d9d382e933a53a2866niq rr->err_headers_out);
e991c6fc032c59eb6cb751d9d382e933a53a2866niq error_notfound = rr->status;
e991c6fc032c59eb6cb751d9d382e933a53a2866niq }
e991c6fc032c59eb6cb751d9d382e933a53a2866niq else if (rr->status && rr->status != HTTP_NOT_FOUND
e991c6fc032c59eb6cb751d9d382e933a53a2866niq && rr->status != HTTP_OK) {
e991c6fc032c59eb6cb751d9d382e933a53a2866niq error_notfound = rr->status;
e991c6fc032c59eb6cb751d9d382e933a53a2866niq }
e991c6fc032c59eb6cb751d9d382e933a53a2866niq
e991c6fc032c59eb6cb751d9d382e933a53a2866niq ap_destroy_sub_req(rr);
e991c6fc032c59eb6cb751d9d382e933a53a2866niq if (error_notfound) {
e991c6fc032c59eb6cb751d9d382e933a53a2866niq return error_notfound;
e991c6fc032c59eb6cb751d9d382e933a53a2866niq }
e991c6fc032c59eb6cb751d9d382e933a53a2866niq
e991c6fc032c59eb6cb751d9d382e933a53a2866niq /* nothing for us to do, pass on through */
e991c6fc032c59eb6cb751d9d382e933a53a2866niq return DECLINED;
e991c6fc032c59eb6cb751d9d382e933a53a2866niq}
d7d0366a6a8a3530c4d2ea722ba869171a81fd88trawick
0958c822c32923b9848a73b2f4c94eab07fb416drbbstatic int fixup_dir(request_rec *r)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe dir_config_rec *d;
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe char *dummy_ptr[1];
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe char **names_ptr;
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe int num_names;
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe int error_notfound = 0;
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe /* In case mod_mime wasn't present, and no handler was assigned. */
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe if (!r->handler) {
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe r->handler = DIR_MAGIC_TYPE;
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe }
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron /* Never tolerate path_info on dir requests */
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe if (r->path_info && *r->path_info) {
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe return DECLINED;
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe }
e95f5a6ebefb83d0e8a82cbc4db7d354957a817dben
2d84861186d70e5396751ba308bb90c8a7db47acnd d = (dir_config_rec *)ap_get_module_config(r->per_dir_config,
2d84861186d70e5396751ba308bb90c8a7db47acnd &dir_module);
2d84861186d70e5396751ba308bb90c8a7db47acnd
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe /* Redirect requests that are not '/' terminated */
e8f95a682820a599fe41b22977010636be5c2717jim if (r->uri[0] == '\0' || r->uri[strlen(r->uri) - 1] != '/')
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding char *ifile;
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe
2d84861186d70e5396751ba308bb90c8a7db47acnd if (!d->do_slash) {
2d84861186d70e5396751ba308bb90c8a7db47acnd return DECLINED;
2d84861186d70e5396751ba308bb90c8a7db47acnd }
2d84861186d70e5396751ba308bb90c8a7db47acnd
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe /* Only redirect non-get requests if we have no note to warn
e8f95a682820a599fe41b22977010636be5c2717jim * that this browser cannot handle redirs on non-GET requests
e8f95a682820a599fe41b22977010636be5c2717jim * (such as Microsoft's WebFolders).
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron if ((r->method_number != M_GET)
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe && apr_table_get(r->subprocess_env, "redirect-carefully")) {
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe return DECLINED;
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe }
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron if (r->args != NULL) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ifile = apr_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri),
bb8b22a3708a815a8fcd0c8d5c8de46c25240cc1jailletc "/?", r->args, NULL);
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron }
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron else {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ifile = apr_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri),
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe "/", NULL);
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_table_setn(r->headers_out, "Location",
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe ap_construct_url(r->pool, ifile, r));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return HTTP_MOVED_PERMANENTLY;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
c0905aec36b287200b8a255b33fba6c975752bdfgstein
f06e7c4b1bce6b6491e5de0b7998d3f5696b293dchrisd if (r->method_number != M_GET && r->method_number != M_POST) {
f06e7c4b1bce6b6491e5de0b7998d3f5696b293dchrisd return DECLINED;
f06e7c4b1bce6b6491e5de0b7998d3f5696b293dchrisd }
f06e7c4b1bce6b6491e5de0b7998d3f5696b293dchrisd
111436a32ba1254291e4883292fb116d15fe8f64covener if (d->checkhandler == MODDIR_ON && strcmp(r->handler, DIR_MAGIC_TYPE)) {
111436a32ba1254291e4883292fb116d15fe8f64covener return DECLINED;
111436a32ba1254291e4883292fb116d15fe8f64covener }
111436a32ba1254291e4883292fb116d15fe8f64covener
cc06c8e7a7e785b46083984731b701d0c5447c72covener /* we're running between mod_rewrites fixup and its internal redirect handler, step aside */
179565be4043d7e5f9161aa75271fa0a001866d9covener if (!strcmp(r->handler, REWRITE_REDIRECT_HANDLER_NAME)) {
cc06c8e7a7e785b46083984731b701d0c5447c72covener return DECLINED;
cc06c8e7a7e785b46083984731b701d0c5447c72covener }
cc06c8e7a7e785b46083984731b701d0c5447c72covener
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (d->index_names) {
d54c6537f5f5a7bc54ec37ce8dbe04193605043astoddard names_ptr = (char **)d->index_names->elts;
d54c6537f5f5a7bc54ec37ce8dbe04193605043astoddard num_names = d->index_names->nelts;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding else {
d54c6537f5f5a7bc54ec37ce8dbe04193605043astoddard dummy_ptr[0] = AP_DEFAULT_INDEX;
d54c6537f5f5a7bc54ec37ce8dbe04193605043astoddard names_ptr = dummy_ptr;
d54c6537f5f5a7bc54ec37ce8dbe04193605043astoddard num_names = 1;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (; num_names; ++names_ptr, --num_names) {
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe /* XXX: Is this name_ptr considered escaped yet, or not??? */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding char *name_ptr = *names_ptr;
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe request_rec *rr;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe /* Once upon a time args were handled _after_ the successful redirect.
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe * But that redirect might then _refuse_ the given r->args, creating
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe * a nasty tangle. It seems safer to consider the r->args while we
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe * determine if name_ptr is our viable index, and therefore set them
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe * up correctly on redirect.
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron if (r->args != NULL) {
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe name_ptr = apr_pstrcat(r->pool, name_ptr, "?", r->args, NULL);
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
433dcb1fbaae82d36634f5120bff71a04296904ddirkx rr = ap_sub_req_lookup_uri(name_ptr, r, r->output_filters);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
a4be7c7d73005dedac190ce6cb68ab4dd38383bbcolm /* The sub request lookup is very liberal, and the core map_to_storage
a4be7c7d73005dedac190ce6cb68ab4dd38383bbcolm * handler will almost always result in HTTP_OK as /foo/index.html
e8f95a682820a599fe41b22977010636be5c2717jim * may be /foo with PATH_INFO="/index.html", or even / with
a4be7c7d73005dedac190ce6cb68ab4dd38383bbcolm * PATH_INFO="/foo/index.html". To get around this we insist that the
a4be7c7d73005dedac190ce6cb68ab4dd38383bbcolm * the index be a regular filetype.
a4be7c7d73005dedac190ce6cb68ab4dd38383bbcolm *
e8f95a682820a599fe41b22977010636be5c2717jim * Another reason is that the core handler also makes the assumption
e8f95a682820a599fe41b22977010636be5c2717jim * that if r->finfo is still NULL by the time it gets called, the
a4be7c7d73005dedac190ce6cb68ab4dd38383bbcolm * file does not exist.
a4be7c7d73005dedac190ce6cb68ab4dd38383bbcolm */
a4be7c7d73005dedac190ce6cb68ab4dd38383bbcolm if (rr->status == HTTP_OK
eea521297270de3f9ae70d8822f8665c513de574nd && ( (rr->handler && !strcmp(rr->handler, "proxy-server"))
eea521297270de3f9ae70d8822f8665c513de574nd || rr->finfo.filetype == APR_REG)) {
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim if (ap_is_HTTP_REDIRECT(d->redirect_index)) {
78b046ee9f769d9609ea1157177d5467e4700c89covener apr_table_setn(r->headers_out, "Location", ap_construct_url(r->pool, rr->uri, r));
78b046ee9f769d9609ea1157177d5467e4700c89covener return d->redirect_index;
78b046ee9f769d9609ea1157177d5467e4700c89covener }
78b046ee9f769d9609ea1157177d5467e4700c89covener
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe ap_internal_fast_redirect(rr, r);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return OK;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
e8f95a682820a599fe41b22977010636be5c2717jim
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* If the request returned a redirect, propagate it to the client */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron if (ap_is_HTTP_REDIRECT(rr->status)
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron || (rr->status == HTTP_NOT_ACCEPTABLE && num_names == 1)
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron || (rr->status == HTTP_UNAUTHORIZED && num_names == 1)) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe apr_pool_join(r->pool, rr->pool);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding error_notfound = rr->status;
066877f1a045103acfdd376d48cdd473c33f409bdougm r->notes = apr_table_overlay(r->pool, r->notes, rr->notes);
066877f1a045103acfdd376d48cdd473c33f409bdougm r->headers_out = apr_table_overlay(r->pool, r->headers_out,
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron rr->headers_out);
066877f1a045103acfdd376d48cdd473c33f409bdougm r->err_headers_out = apr_table_overlay(r->pool, r->err_headers_out,
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron rr->err_headers_out);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return error_notfound;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* If the request returned something other than 404 (or 200),
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * it means the module encountered some sort of problem. To be
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe * secure, we should return the error, rather than allow autoindex
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe * to create a (possibly unsafe) directory index.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * So we store the error, and if none of the listed files
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * exist, we return the last error response we got, instead
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * of a directory listing.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron if (rr->status && rr->status != HTTP_NOT_FOUND
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron && rr->status != HTTP_OK) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding error_notfound = rr->status;
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_destroy_sub_req(rr);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe if (error_notfound) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return error_notfound;
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
761cbc5db8f9f9ca10cd52957985d70503a2daaacovener /* record what we tried, mostly for the benefit of mod_autoindex */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim apr_table_set(r->notes, "dir-index-names",
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim d->index_names ?
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim apr_array_pstrcat(r->pool, d->index_names, ','):
761cbc5db8f9f9ca10cd52957985d70503a2daaacovener AP_DEFAULT_INDEX);
761cbc5db8f9f9ca10cd52957985d70503a2daaacovener
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* nothing for us to do, pass on through */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return DECLINED;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
d7d0366a6a8a3530c4d2ea722ba869171a81fd88trawick
1eda27e7224742a68c18c09a7f5ae233363465a4niqstatic int dir_fixups(request_rec *r)
1eda27e7224742a68c18c09a7f5ae233363465a4niq{
1eda27e7224742a68c18c09a7f5ae233363465a4niq if (r->finfo.filetype == APR_DIR) {
1eda27e7224742a68c18c09a7f5ae233363465a4niq /* serve up a directory */
1eda27e7224742a68c18c09a7f5ae233363465a4niq return fixup_dir(r);
1eda27e7224742a68c18c09a7f5ae233363465a4niq }
1eda27e7224742a68c18c09a7f5ae233363465a4niq else if ((r->finfo.filetype == APR_NOFILE) && (r->handler == NULL)) {
1eda27e7224742a68c18c09a7f5ae233363465a4niq /* No handler and nothing in the filesystem - use fallback */
1eda27e7224742a68c18c09a7f5ae233363465a4niq return fixup_dflt(r);
1eda27e7224742a68c18c09a7f5ae233363465a4niq }
1eda27e7224742a68c18c09a7f5ae233363465a4niq return DECLINED;
1eda27e7224742a68c18c09a7f5ae233363465a4niq}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
73e8b26287de5c06fa470d36162e103dbac9c7e5wrowestatic void register_hooks(apr_pool_t *p)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
1eda27e7224742a68c18c09a7f5ae233363465a4niq ap_hook_fixups(dir_fixups,NULL,NULL,APR_HOOK_LAST);
e95f5a6ebefb83d0e8a82cbc4db7d354957a817dben}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
36ef8f77bffe75d1aa327882be1b5bdbe2ff567asfAP_DECLARE_MODULE(dir) = {
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding STANDARD20_MODULE_STUFF,
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron create_dir_config, /* create per-directory config structure */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron merge_dir_configs, /* merge per-directory config structures */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron NULL, /* create per-server config structure */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron NULL, /* merge per-server config structures */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron dir_cmds, /* command apr_table_t */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron register_hooks /* register hooks */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding};