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
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 * mod_dir.c: handle default index files, and trailing-/ redirects
2d84861186d70e5396751ba308bb90c8a7db47acndtypedef enum {
4f9a74ad7e44b0464f7cf56525a205d788becacbtrawickstatic const char *add_index(cmd_parms *cmd, void *dummy, const char *arg)
b6d2c204c150843e48f6787c1090ae75b718896ecovener const char *t, *w;
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron d->index_names = apr_array_make(cmd->pool, 2, sizeof(char *));
7076b40ea4800c8f91c4c0948f9c98c1bacbe96crpluem while ((w = ap_getword_conf(cmd->pool, &t)) && w[0]) {
b6d2c204c150843e48f6787c1090ae75b718896ecovener /* peek to see if "disabled" is first in a series of arguments */
b6d2c204c150843e48f6787c1090ae75b718896ecovener /* "disabled" is first, and alone */
2d84861186d70e5396751ba308bb90c8a7db47acndstatic const char *configure_slash(cmd_parms *cmd, void *d_, int arg)
111436a32ba1254291e4883292fb116d15fe8f64covenerstatic const char *configure_checkhandler(cmd_parms *cmd, void *d_, int arg)
78b046ee9f769d9609ea1157177d5467e4700c89covenerstatic const char *configure_redirect(cmd_parms *cmd, void *d_, const char *arg1)
78b046ee9f769d9609ea1157177d5467e4700c89covener return "DirectoryIndexRedirect only accepts values between 300 and 399";
78b046ee9f769d9609ea1157177d5467e4700c89covener return "DirectoryIndexRedirect ON|OFF|permanent|temp|seeother|3xx";
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."),
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void *create_dir_config(apr_pool_t *p, char *dummy)
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron dir_config_rec *new = apr_pcalloc(p, sizeof(dir_config_rec));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return (void *) new;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void *merge_dir_configs(apr_pool_t *p, void *basev, void *addv)
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron dir_config_rec *new = apr_pcalloc(p, sizeof(dir_config_rec));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding new->index_names = add->index_names ? add->index_names : base->index_names;
128148f61cfed630b051d26e3e2018f774b21595covener (add->do_slash == MODDIR_UNSET) ? base->do_slash : add->do_slash;
111436a32ba1254291e4883292fb116d15fe8f64covener (add->checkhandler == MODDIR_UNSET) ? base->checkhandler : add->checkhandler;
78b046ee9f769d9609ea1157177d5467e4700c89covener (add->redirect_index == REDIRECT_UNSET) ? base->redirect_index : add->redirect_index;
e991c6fc032c59eb6cb751d9d382e933a53a2866niq dir_config_rec *d = ap_get_module_config(r->per_dir_config, &dir_module);
5695f522f64e4b842be9dc438666fd91a89cc10bgryzor if ((name_ptr == NULL) || !(strcasecmp(name_ptr,"disabled"))){
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 /* The logic of this function is basically cloned and simplified
a1efede5943e76f1fcdf10494de41704c9ba70f1niq * from fixup_dir below. See the comments there.
e991c6fc032c59eb6cb751d9d382e933a53a2866niq name_ptr = apr_pstrcat(r->pool, name_ptr, "?", r->args, NULL);
e991c6fc032c59eb6cb751d9d382e933a53a2866niq rr = ap_sub_req_lookup_uri(name_ptr, r, r->output_filters);
e991c6fc032c59eb6cb751d9d382e933a53a2866niq && ( (rr->handler && !strcmp(rr->handler, "proxy-server"))
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 r->err_headers_out = apr_table_overlay(r->pool, r->err_headers_out,
e991c6fc032c59eb6cb751d9d382e933a53a2866niq /* nothing for us to do, pass on through */
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe /* In case mod_mime wasn't present, and no handler was assigned. */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron /* Never tolerate path_info on dir requests */
2d84861186d70e5396751ba308bb90c8a7db47acnd d = (dir_config_rec *)ap_get_module_config(r->per_dir_config,
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe /* Redirect requests that are not '/' terminated */
e8f95a682820a599fe41b22977010636be5c2717jim if (r->uri[0] == '\0' || r->uri[strlen(r->uri) - 1] != '/')
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 && apr_table_get(r->subprocess_env, "redirect-carefully")) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ifile = apr_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri),
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ifile = apr_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri),
f06e7c4b1bce6b6491e5de0b7998d3f5696b293dchrisd if (r->method_number != M_GET && r->method_number != M_POST) {
111436a32ba1254291e4883292fb116d15fe8f64covener if (d->checkhandler == MODDIR_ON && strcmp(r->handler, DIR_MAGIC_TYPE)) {
cc06c8e7a7e785b46083984731b701d0c5447c72covener /* we're running between mod_rewrites fixup and its internal redirect handler, step aside */
179565be4043d7e5f9161aa75271fa0a001866d9covener if (!strcmp(r->handler, REWRITE_REDIRECT_HANDLER_NAME)) {
3f65070bf58882ab06bfa08cc4e04c7c90ac04f8wrowe /* XXX: Is this name_ptr considered escaped yet, or not??? */
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 name_ptr = apr_pstrcat(r->pool, name_ptr, "?", r->args, NULL);
433dcb1fbaae82d36634f5120bff71a04296904ddirkx rr = ap_sub_req_lookup_uri(name_ptr, r, r->output_filters);
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.
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.
eea521297270de3f9ae70d8822f8665c513de574nd && ( (rr->handler && !strcmp(rr->handler, "proxy-server"))
78b046ee9f769d9609ea1157177d5467e4700c89covener apr_table_setn(r->headers_out, "Location", ap_construct_url(r->pool, rr->uri, r));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* If the request returned a redirect, propagate it to the client */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron || (rr->status == HTTP_NOT_ACCEPTABLE && num_names == 1)
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron || (rr->status == HTTP_UNAUTHORIZED && num_names == 1)) {
066877f1a045103acfdd376d48cdd473c33f409bdougm r->notes = apr_table_overlay(r->pool, r->notes, rr->notes);
066877f1a045103acfdd376d48cdd473c33f409bdougm r->headers_out = apr_table_overlay(r->pool, r->headers_out,
066877f1a045103acfdd376d48cdd473c33f409bdougm r->err_headers_out = apr_table_overlay(r->pool, r->err_headers_out,
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 * 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.
761cbc5db8f9f9ca10cd52957985d70503a2daaacovener /* record what we tried, mostly for the benefit of mod_autoindex */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* nothing for us to do, pass on through */
1eda27e7224742a68c18c09a7f5ae233363465a4niq /* serve up a directory */
1eda27e7224742a68c18c09a7f5ae233363465a4niq else if ((r->finfo.filetype == APR_NOFILE) && (r->handler == NULL)) {
1eda27e7224742a68c18c09a7f5ae233363465a4niq /* No handler and nothing in the filesystem - use fallback */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron create_dir_config, /* create per-directory config structure */
06a537b50a7a5d4f8543231d2b6067b8f6805dd3aaron merge_dir_configs, /* merge per-directory config structures */