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