http_core.c revision a368d1ad6bc200b13dda026a14fa4ad8f82716cb
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * The Apache Software License, Version 1.1
842ae4bd224140319ae7feec1872b93dfd491143fielding *
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 2000 The Apache Software Foundation. All rights
842ae4bd224140319ae7feec1872b93dfd491143fielding * reserved.
842ae4bd224140319ae7feec1872b93dfd491143fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Redistribution and use in source and binary forms, with or without
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * modification, are permitted provided that the following conditions
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * are met:
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 1. Redistributions of source code must retain the above copyright
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * notice, this list of conditions and the following disclaimer.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 2. Redistributions in binary form must reproduce the above copyright
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * notice, this list of conditions and the following disclaimer in
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the documentation and/or other materials provided with the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * distribution.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh * 3. The end-user documentation included with the redistribution,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * if any, must include the following acknowledgment:
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh * "This product includes software developed by the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Apache Software Foundation (http://www.apache.org/)."
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Alternately, this acknowledgment may appear in the software itself,
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein * if and wherever such third-party acknowledgments normally appear.
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein *
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein * 4. The names "Apache" and "Apache Software Foundation" must
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein * not be used to endorse or promote products derived from this
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein * software without prior written permission. For written
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * permission, please contact apache@apache.org.
be3223a6a18d9a3a3cf7155d5430a5d92bcddceegstein *
573394373c777e1624a481160f3d02f8fb09f3ffrjung * 5. Products derived from this software may not be called "Apache",
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * nor may "Apache" appear in their name, without prior written
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * permission of the Apache Software Foundation.
1b21d7b3d97def358b2e923655edeb16613a1c31gstein *
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * SUCH DAMAGE.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * ====================================================================
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * This software consists of voluntary contributions made by many
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * individuals on behalf of the Apache Software Foundation. For more
cf8fe49d9d89cfa4b62cb2b1376ca6f25b81b362trawick * information on the Apache Software Foundation, please see
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick * <http://www.apache.org/>.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf * Portions of this software are based upon public domain software
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf * originally written at the National Center for Supercomputing Applications,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * University of Illinois, Urbana-Champaign.
963f8b44ac95132458ea3b6aaa8ebc135188e473takashi */
963f8b44ac95132458ea3b6aaa8ebc135188e473takashi
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define CORE_PRIVATE
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "ap_config.h"
a7318397b355119d990d1f311b951dea2aafc53arbb#include "apr_strings.h"
a7318397b355119d990d1f311b951dea2aafc53arbb#include "apr_lib.h"
ce4dc40a4e87991087488f70d96d3447d7557294sf#include "httpd.h"
a7318397b355119d990d1f311b951dea2aafc53arbb#include "http_config.h"
a7318397b355119d990d1f311b951dea2aafc53arbb#include "http_core.h"
cb9e6e5c78f5a1690214e9548250fc6af1fc73b5wrowe#include "http_protocol.h" /* For index_of_response(). Grump. */
cb9e6e5c78f5a1690214e9548250fc6af1fc73b5wrowe#include "http_request.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "http_vhost.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "http_main.h" /* For the default_handler below... */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "http_log.h"
8a3228198adb03e6996f7738c361a612777ecab6aaron#include "rfc1413.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "util_md5.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "apr_fnmatch.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "http_connection.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "ap_buckets.h"
8a3228198adb03e6996f7738c361a612777ecab6aaron#include "util_filter.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "util_ebcdic.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "mpm.h"
8a3228198adb03e6996f7738c361a612777ecab6aaron#ifdef HAVE_NETDB_H
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <netdb.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
8a3228198adb03e6996f7738c361a612777ecab6aaron#ifdef HAVE_SYS_SOCKET_H
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <sys/socket.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
8a3228198adb03e6996f7738c361a612777ecab6aaron#ifdef HAVE_ARPA_INET_H
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <arpa/inet.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
8a3228198adb03e6996f7738c361a612777ecab6aaron#ifdef HAVE_STRINGS_H
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <strings.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
8a3228198adb03e6996f7738c361a612777ecab6aaron
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Make sure we don't write less than 4096 bytes at any one time.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
8a3228198adb03e6996f7738c361a612777ecab6aaron#define MIN_SIZE_TO_WRITE 9000
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Allow Apache to use ap_mmap */
8a3228198adb03e6996f7738c361a612777ecab6aaron#ifdef USE_MMAP_FILES
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "apr_mmap.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
8a3228198adb03e6996f7738c361a612777ecab6aaron/* mmap support for static files based on ideas from John Heidemann's
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * patch against 1.0.5. See
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * <http://www.isi.edu/~johnh/SOFTWARE/APACHE/index.html>.
8a3228198adb03e6996f7738c361a612777ecab6aaron */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Files have to be at least this big before they're mmap()d. This is to deal
8a3228198adb03e6996f7738c361a612777ecab6aaron * with systems where the expense of doing an mmap() and an munmap() outweighs
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the benefit for small files. It shouldn't be set lower than 1.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
8a3228198adb03e6996f7738c361a612777ecab6aaron#ifndef MMAP_THRESHOLD
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding #ifdef SUNOS4
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding #define MMAP_THRESHOLD (8*1024)
8a3228198adb03e6996f7738c361a612777ecab6aaron #else
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding #define MMAP_THRESHOLD 1
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding #endif /* SUNOS4 */
8a3228198adb03e6996f7738c361a612777ecab6aaron#endif /* MMAP_THRESHOLD */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#ifndef MMAP_LIMIT
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define MMAP_LIMIT (4*1024*1024)
8a3228198adb03e6996f7738c361a612777ecab6aaron#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif /* USE_MMAP_FILES */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
8a3228198adb03e6996f7738c361a612777ecab6aaron/* LimitXMLRequestBody handling */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define AP_LIMIT_UNSET ((long) -1)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define AP_DEFAULT_LIMIT_XML_BODY ((size_t)1000000)
8a3228198adb03e6996f7738c361a612777ecab6aaron
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Server core module... This module provides support for really basic
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * server operations, including options and commands which control the
8a3228198adb03e6996f7738c361a612777ecab6aaron * operation of other modules. Consider this the bureaucracy module.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
8a3228198adb03e6996f7738c361a612777ecab6aaron * The core module also defines handlers, etc., do handle just enough
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * to allow a server with the core module ONLY to actually serve documents
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * (though it slaps DefaultType on all of 'em); this was useful in testing,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * but may not be worth preserving.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
8a3228198adb03e6996f7738c361a612777ecab6aaron * This file could almost be mod_core.c, except for the stuff which affects
8a3228198adb03e6996f7738c361a612777ecab6aaron * the http_conf_globals.
8a3228198adb03e6996f7738c361a612777ecab6aaron */
8a3228198adb03e6996f7738c361a612777ecab6aaron
8a3228198adb03e6996f7738c361a612777ecab6aaronstatic void *create_core_dir_config(apr_pool_t *a, char *dir)
8a3228198adb03e6996f7738c361a612777ecab6aaron{
8a3228198adb03e6996f7738c361a612777ecab6aaron core_dir_config *conf;
8a3228198adb03e6996f7738c361a612777ecab6aaron
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf conf = (core_dir_config *)apr_pcalloc(a, sizeof(core_dir_config));
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf if (!dir || dir[strlen(dir) - 1] == '/') {
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf conf->d = dir;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf }
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf else if (strncmp(dir, "proxy:", 6) == 0) {
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf conf->d = apr_pstrdup(a, dir);
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf }
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf else {
8a3228198adb03e6996f7738c361a612777ecab6aaron conf->d = apr_pstrcat(a, dir, "/", NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding conf->d_is_fnmatch = conf->d ? (apr_is_fnmatch(conf->d) != 0) : 0;
649c9dd342a580016d29c2866de88a4609eb6457wrowe conf->d_components = conf->d ? ap_count_dirs(conf->d) : 0;
649c9dd342a580016d29c2866de88a4609eb6457wrowe
0f57a69cc84c59eacda1179763ae42ca88f1a577wrowe conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL;
18b197c6ba1d5b8bb5b2fb372ef752f87e56912atrawick conf->opts_add = conf->opts_remove = OPT_NONE;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->content_md5 = 2;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->use_canonical_name = USE_CANONICAL_NAME_UNSET;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->do_rfc1413 = DEFAULT_RFC1413 | 2; /* set bit 1 to indicate default */
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->satisfy = SATISFY_NOSPEC;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton#ifdef RLIMIT_CPU
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->limit_cpu = NULL;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton#endif
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->limit_mem = NULL;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton#endif
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton#ifdef RLIMIT_NPROC
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->limit_nproc = NULL;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton#endif
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->limit_req_body = 0;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->limit_xml_body = AP_LIMIT_UNSET;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->sec = apr_make_array(a, 2, sizeof(void *));
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton#ifdef WIN32
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe conf->script_interpreter_source = INTERPRETER_SOURCE_UNSET;
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe#endif
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->server_signature = srv_sig_unset;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->add_default_charset = ADD_DEFAULT_CHARSET_UNSET;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->filters = apr_make_array(a, 2, sizeof(void *));
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton conf->input_filters = apr_make_array(a, 2, sizeof(void *));
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton return (void *)conf;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton}
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jortonstatic void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton{
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick core_dir_config *base = (core_dir_config *)basev;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick core_dir_config *new = (core_dir_config *)newv;
649c9dd342a580016d29c2866de88a4609eb6457wrowe core_dir_config *conf;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick int i;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf = (core_dir_config *)apr_palloc(a, sizeof(core_dir_config));
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick memcpy((char *)conf, (const char *)base, sizeof(core_dir_config));
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick if (base->response_code_strings) {
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->response_code_strings =
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick apr_palloc(a, sizeof(*conf->response_code_strings)
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe * RESPONSE_CODES);
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe memcpy(conf->response_code_strings, base->response_code_strings,
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe sizeof(*conf->response_code_strings) * RESPONSE_CODES);
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe }
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe conf->d = new->d;
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe conf->d_is_fnmatch = new->d_is_fnmatch;
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe conf->d_components = new->d_components;
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe conf->r = new->r;
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick if (new->opts & OPT_UNSET) {
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick /* there was no explicit setting of new->opts, so we merge
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe * preserve the invariant (opts_add & opts_remove) == 0
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick */
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->opts_add = (conf->opts_add & ~new->opts_remove) | new->opts_add;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->opts_remove = (conf->opts_remove & ~new->opts_add)
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick | new->opts_remove;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES)) {
d7b781abdcdc6fc4d4fcd513d5babd3c42dff43dwrowe conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick }
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick }
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick else {
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick /* otherwise we just copy, because an explicit opts setting
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick * overrides all earlier +/- modifiers
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick */
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->opts = new->opts;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->opts_add = new->opts_add;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick conf->opts_remove = new->opts_remove;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick }
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick if (!(new->override & OR_UNSET)) {
ebc18d48bea83ee5ed7a1b4e30007e5192539829wrowe conf->override = new->override;
18b197c6ba1d5b8bb5b2fb372ef752f87e56912atrawick }
066877f1a045103acfdd376d48cdd473c33f409bdougm if (new->ap_default_type) {
18b197c6ba1d5b8bb5b2fb372ef752f87e56912atrawick conf->ap_default_type = new->ap_default_type;
18b197c6ba1d5b8bb5b2fb372ef752f87e56912atrawick }
e8f95a682820a599fe41b22977010636be5c2717jim
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe if (new->ap_auth_type) {
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe conf->ap_auth_type = new->ap_auth_type;
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe }
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe if (new->ap_auth_name) {
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe conf->ap_auth_name = new->ap_auth_name;
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe }
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe if (new->ap_requires) {
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe conf->ap_requires = new->ap_requires;
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe }
85c435ceda98eab940615e4466d9c5955252e745wrowe
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe if (new->response_code_strings) {
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe if (conf->response_code_strings == NULL) {
92eed7d377d8be7cd8e48d1299412fc8c742b7f5jorton conf->response_code_strings = apr_palloc(a,
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe sizeof(*conf->response_code_strings) * RESPONSE_CODES);
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe memcpy(conf->response_code_strings, new->response_code_strings,
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe sizeof(*conf->response_code_strings) * RESPONSE_CODES);
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe }
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe else {
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe for (i = 0; i < RESPONSE_CODES; ++i) {
649c9dd342a580016d29c2866de88a4609eb6457wrowe if (new->response_code_strings[i] != NULL) {
649c9dd342a580016d29c2866de88a4609eb6457wrowe conf->response_code_strings[i]
649c9dd342a580016d29c2866de88a4609eb6457wrowe = new->response_code_strings[i];
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe if (new->hostname_lookups != HOSTNAME_LOOKUP_UNSET) {
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe conf->hostname_lookups = new->hostname_lookups;
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe if ((new->do_rfc1413 & 2) == 0) {
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe conf->do_rfc1413 = new->do_rfc1413;
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe if ((new->content_md5 & 2) == 0) {
649c9dd342a580016d29c2866de88a4609eb6457wrowe conf->content_md5 = new->content_md5;
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe if (new->use_canonical_name != USE_CANONICAL_NAME_UNSET) {
649c9dd342a580016d29c2866de88a4609eb6457wrowe conf->use_canonical_name = new->use_canonical_name;
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe
649c9dd342a580016d29c2866de88a4609eb6457wrowe#ifdef RLIMIT_CPU
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe if (new->limit_cpu) {
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe conf->limit_cpu = new->limit_cpu;
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe#endif
649c9dd342a580016d29c2866de88a4609eb6457wrowe#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
649c9dd342a580016d29c2866de88a4609eb6457wrowe if (new->limit_mem) {
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe conf->limit_mem = new->limit_mem;
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe }
760b90f5b0bb414646deb6a3a2a53c14bf49bf3dwrowe#endif
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe#ifdef RLIMIT_NPROC
15405e91bb3fad5a80f7abe828a00b44a3a65bf8jerenkrantz if (new->limit_nproc) {
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe conf->limit_nproc = new->limit_nproc;
b3edf21d591bfd0e64bbec0dda73c0e41d7ecdb6wrowe }
76185d819b745e953dd2cd636fbdd515c333e4a4trawick#endif
76185d819b745e953dd2cd636fbdd515c333e4a4trawick
76185d819b745e953dd2cd636fbdd515c333e4a4trawick if (new->limit_req_body) {
76185d819b745e953dd2cd636fbdd515c333e4a4trawick conf->limit_req_body = new->limit_req_body;
76185d819b745e953dd2cd636fbdd515c333e4a4trawick }
76185d819b745e953dd2cd636fbdd515c333e4a4trawick
76185d819b745e953dd2cd636fbdd515c333e4a4trawick if (new->limit_xml_body != AP_LIMIT_UNSET)
399cf0e5e061b49593817421b94305889fa6bc1fjorton conf->limit_xml_body = new->limit_xml_body;
399cf0e5e061b49593817421b94305889fa6bc1fjorton else
399cf0e5e061b49593817421b94305889fa6bc1fjorton conf->limit_xml_body = base->limit_xml_body;
399cf0e5e061b49593817421b94305889fa6bc1fjorton
399cf0e5e061b49593817421b94305889fa6bc1fjorton conf->sec = apr_append_arrays(a, base->sec, new->sec);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe if (new->satisfy != SATISFY_NOSPEC) {
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe conf->satisfy = new->satisfy;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#ifdef WIN32
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (new->script_interpreter_source != INTERPRETER_SOURCE_UNSET) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding conf->script_interpreter_source = new->script_interpreter_source;
f5fccb8eae1f1a5f212a5bda878479c281f36512trawick }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm#endif
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
399cf0e5e061b49593817421b94305889fa6bc1fjorton if (new->server_signature != srv_sig_unset) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding conf->server_signature = new->server_signature;
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh }
5a6a87d8920e385b1ed14177d74ab9786f3acddfwrowe
5a6a87d8920e385b1ed14177d74ab9786f3acddfwrowe if (new->add_default_charset != ADD_DEFAULT_CHARSET_UNSET) {
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe conf->add_default_charset = new->add_default_charset;
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh if (new->add_default_charset_name) {
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh conf->add_default_charset_name = new->add_default_charset_name;
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh }
76185d819b745e953dd2cd636fbdd515c333e4a4trawick }
76185d819b745e953dd2cd636fbdd515c333e4a4trawick conf->filters = apr_append_arrays(a, base->filters, new->filters);
ff0436077dc959b17a6f87825e4a106d211224c1wrowe conf->input_filters = apr_append_arrays(a, base->input_filters,
ff0436077dc959b17a6f87825e4a106d211224c1wrowe new->input_filters);
fa4e5ac791dd1c84df616b28d4ee9751efe9c64frbb
fa4e5ac791dd1c84df616b28d4ee9751efe9c64frbb return (void*)conf;
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh}
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void *create_core_server_config(apr_pool_t *a, server_rec *s)
8a3228198adb03e6996f7738c361a612777ecab6aaron{
ff0436077dc959b17a6f87825e4a106d211224c1wrowe core_server_config *conf;
ff0436077dc959b17a6f87825e4a106d211224c1wrowe int is_virtual = s->is_virtual;
ff0436077dc959b17a6f87825e4a106d211224c1wrowe
ff0436077dc959b17a6f87825e4a106d211224c1wrowe conf = (core_server_config *)apr_pcalloc(a, sizeof(core_server_config));
ff0436077dc959b17a6f87825e4a106d211224c1wrowe#ifdef GPROF
ff0436077dc959b17a6f87825e4a106d211224c1wrowe conf->gprof_dir = NULL;
066877f1a045103acfdd376d48cdd473c33f409bdougm#endif
8a3228198adb03e6996f7738c361a612777ecab6aaron conf->access_name = is_virtual ? NULL : DEFAULT_ACCESS_FNAME;
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh conf->ap_document_root = is_virtual ? NULL : DOCUMENT_LOCATION;
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb conf->sec = apr_make_array(a, 40, sizeof(void *));
d521bfef0e1a65993d5e302628ac68a2c91a195ftrawick conf->sec_url = apr_make_array(a, 40, sizeof(void *));
20c85ca0d404e29972fb94c3d6236a264d1c77abstoddard
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick return (void *)conf;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick}
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbbstatic void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb{
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb core_server_config *base = (core_server_config *)basev;
8a3228198adb03e6996f7738c361a612777ecab6aaron core_server_config *virt = (core_server_config *)virtv;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding core_server_config *conf;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
399cf0e5e061b49593817421b94305889fa6bc1fjorton conf = (core_server_config *)apr_pcalloc(p, sizeof(core_server_config));
399cf0e5e061b49593817421b94305889fa6bc1fjorton *conf = *virt;
399cf0e5e061b49593817421b94305889fa6bc1fjorton if (!conf->access_name) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding conf->access_name = base->access_name;
061c3874622b67beff724876b9bd1b1f291f2eaafielding }
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb if (!conf->ap_document_root) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding conf->ap_document_root = base->ap_document_root;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung conf->sec = apr_append_arrays(p, base->sec, virt->sec);
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe conf->sec_url = apr_append_arrays(p, base->sec_url, virt->sec_url);
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb return conf;
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe}
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe/* Add per-directory configuration entry (for <directory> section);
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe * these are part of the core server config.
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe */
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe
7117ace448072813fa6eb7180ef206fc2e8fcfc7wroweCORE_EXPORT(void) ap_add_per_dir_conf(server_rec *s, void *dir_config)
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe{
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe core_server_config *sconf = ap_get_module_config(s->module_config,
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe &core_module);
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe void **new_space = (void **)apr_push_array(sconf->sec);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
399cf0e5e061b49593817421b94305889fa6bc1fjorton *new_space = dir_config;
399cf0e5e061b49593817421b94305889fa6bc1fjorton}
399cf0e5e061b49593817421b94305889fa6bc1fjorton
399cf0e5e061b49593817421b94305889fa6bc1fjortonCORE_EXPORT(void) ap_add_per_url_conf(server_rec *s, void *url_config)
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe{
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung core_server_config *sconf = ap_get_module_config(s->module_config,
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung &core_module);
19702a9985f3b2f794d22be9102d9d4fbf6bebe7rjung void **new_space = (void **)apr_push_array(sconf->sec_url);
783e3e4bd40b8c276b72b49470bfabb8693fb5c2rjung
85c435ceda98eab940615e4466d9c5955252e745wrowe *new_space = url_config;
8a3228198adb03e6996f7738c361a612777ecab6aaron}
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung
053847fad1e0bfc79d75dd6aec040b78c4d9189erjungCORE_EXPORT(void) ap_add_file_conf(core_dir_config *conf, void *url_config)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding void **new_space = (void **)apr_push_array(conf->sec);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *new_space = url_config;
8a3228198adb03e6996f7738c361a612777ecab6aaron}
8a3228198adb03e6996f7738c361a612777ecab6aaron
8a3228198adb03e6996f7738c361a612777ecab6aaron/* core_reorder_directories reorders the directory sections such that the
8a3228198adb03e6996f7738c361a612777ecab6aaron * 1-component sections come first, then the 2-component, and so on, finally
8a3228198adb03e6996f7738c361a612777ecab6aaron * followed by the "special" sections. A section is "special" if it's a regex,
8a3228198adb03e6996f7738c361a612777ecab6aaron * or if it doesn't start with / -- consider proxy: matching. All movements
8a3228198adb03e6996f7738c361a612777ecab6aaron * are in-order to preserve the ordering of the sections from the config files.
8a3228198adb03e6996f7738c361a612777ecab6aaron * See directory_walk().
8a3228198adb03e6996f7738c361a612777ecab6aaron */
85c435ceda98eab940615e4466d9c5955252e745wrowe
8a3228198adb03e6996f7738c361a612777ecab6aaron#if defined(HAVE_DRIVE_LETTERS)
8a3228198adb03e6996f7738c361a612777ecab6aaron#define IS_SPECIAL(entry_core) \
8a3228198adb03e6996f7738c361a612777ecab6aaron ((entry_core)->r != NULL \
8a3228198adb03e6996f7738c361a612777ecab6aaron || ((entry_core)->d[0] != '/' && (entry_core)->d[1] != ':'))
8a3228198adb03e6996f7738c361a612777ecab6aaron#elif defined(NETWARE)
8a3228198adb03e6996f7738c361a612777ecab6aaron/* XXX: Fairly certain this is correct... '/' must prefix the path
8a3228198adb03e6996f7738c361a612777ecab6aaron * or else in the case xyz:/ or abc/xyz:/, '/' must follow the ':'.
8a3228198adb03e6996f7738c361a612777ecab6aaron * If there is no leading '/' or embedded ':/', then we are special.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define IS_SPECIAL(entry_core) \
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ((entry_core)->r != NULL \
8a3228198adb03e6996f7738c361a612777ecab6aaron || ((entry_core)->d[0] != '/' \
32c4bc04f89b16521718145dc731f750144d7b38wrowe && strchr((entry_core)->d, ':') \
32c4bc04f89b16521718145dc731f750144d7b38wrowe && *(strchr((entry_core)->d, ':') + 1) != '/'))
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung#else
32c4bc04f89b16521718145dc731f750144d7b38wrowe#define IS_SPECIAL(entry_core) \
85c435ceda98eab940615e4466d9c5955252e745wrowe ((entry_core)->r != NULL || (entry_core)->d[0] != '/')
32c4bc04f89b16521718145dc731f750144d7b38wrowe#endif
32c4bc04f89b16521718145dc731f750144d7b38wrowe
92eed7d377d8be7cd8e48d1299412fc8c742b7f5jorton/* We need to do a stable sort, qsort isn't stable. So to make it stable
32c4bc04f89b16521718145dc731f750144d7b38wrowe * we'll be maintaining the original index into the list, and using it
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh * as the minor key during sorting. The major key is the number of
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung * components (where a "special" section has infinite components).
c25e9633c29be3a5b74f0bf75079d54e5417115dwrowe */
85c435ceda98eab940615e4466d9c5955252e745wrowestruct reorder_sort_rec {
8a3228198adb03e6996f7738c361a612777ecab6aaron void *elt;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int orig_index;
85c435ceda98eab940615e4466d9c5955252e745wrowe};
85c435ceda98eab940615e4466d9c5955252e745wrowe
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic int reorder_sorter(const void *va, const void *vb)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
e8f95a682820a599fe41b22977010636be5c2717jim const struct reorder_sort_rec *a = va;
85c435ceda98eab940615e4466d9c5955252e745wrowe const struct reorder_sort_rec *b = vb;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding core_dir_config *core_a;
649c9dd342a580016d29c2866de88a4609eb6457wrowe core_dir_config *core_b;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding core_a = (core_dir_config *)ap_get_module_config(a->elt, &core_module);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding core_b = (core_dir_config *)ap_get_module_config(b->elt, &core_module);
649c9dd342a580016d29c2866de88a4609eb6457wrowe if (IS_SPECIAL(core_a)) {
649c9dd342a580016d29c2866de88a4609eb6457wrowe if (!IS_SPECIAL(core_b)) {
649c9dd342a580016d29c2866de88a4609eb6457wrowe return 1;
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe else if (IS_SPECIAL(core_b)) {
649c9dd342a580016d29c2866de88a4609eb6457wrowe return -1;
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe else {
649c9dd342a580016d29c2866de88a4609eb6457wrowe /* we know they're both not special */
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick if (core_a->d_components < core_b->d_components) {
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick return -1;
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe else if (core_a->d_components > core_b->d_components) {
649c9dd342a580016d29c2866de88a4609eb6457wrowe return 1;
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe }
649c9dd342a580016d29c2866de88a4609eb6457wrowe /* Either they're both special, or they're both not special and have the
649c9dd342a580016d29c2866de88a4609eb6457wrowe * same number of components. In any event, we now have to compare
649c9dd342a580016d29c2866de88a4609eb6457wrowe * the minor key. */
649c9dd342a580016d29c2866de88a4609eb6457wrowe return a->orig_index - b->orig_index;
aef88024529c64e3e634c6f3f255e4419ad9182drjung}
649c9dd342a580016d29c2866de88a4609eb6457wrowe
85c435ceda98eab940615e4466d9c5955252e745wrowevoid ap_core_reorder_directories(apr_pool_t *p, server_rec *s)
85c435ceda98eab940615e4466d9c5955252e745wrowe{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding core_server_config *sconf;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_array_header_t *sec;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding struct reorder_sort_rec *sortbin;
ab43b4a17b2ac31ccb1cf280be8c42a8a314cecbjorton int nelts;
aef88024529c64e3e634c6f3f255e4419ad9182drjung void **elts;
ab43b4a17b2ac31ccb1cf280be8c42a8a314cecbjorton int i;
066877f1a045103acfdd376d48cdd473c33f409bdougm apr_pool_t *tmp;
649c9dd342a580016d29c2866de88a4609eb6457wrowe
ab43b4a17b2ac31ccb1cf280be8c42a8a314cecbjorton sconf = ap_get_module_config(s->module_config, &core_module);
ab43b4a17b2ac31ccb1cf280be8c42a8a314cecbjorton sec = sconf->sec;
ec727afb817df0e5202135278c0d2902923cc980stoddard nelts = sec->nelts;
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh elts = (void **)sec->elts;
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh
649c9dd342a580016d29c2866de88a4609eb6457wrowe /* we have to allocate tmp space to do a stable sort */
649c9dd342a580016d29c2866de88a4609eb6457wrowe apr_create_pool(&tmp, p);
649c9dd342a580016d29c2866de88a4609eb6457wrowe sortbin = apr_palloc(tmp, sec->nelts * sizeof(*sortbin));
649c9dd342a580016d29c2866de88a4609eb6457wrowe for (i = 0; i < nelts; ++i) {
649c9dd342a580016d29c2866de88a4609eb6457wrowe sortbin[i].orig_index = i;
649c9dd342a580016d29c2866de88a4609eb6457wrowe sortbin[i].elt = elts[i];
ec727afb817df0e5202135278c0d2902923cc980stoddard }
188dff19ac1e71ffd25752d1a4f8d71f9f563305wrowe
188dff19ac1e71ffd25752d1a4f8d71f9f563305wrowe qsort(sortbin, nelts, sizeof(*sortbin), reorder_sorter);
188dff19ac1e71ffd25752d1a4f8d71f9f563305wrowe
188dff19ac1e71ffd25752d1a4f8d71f9f563305wrowe /* and now copy back to the original array */
188dff19ac1e71ffd25752d1a4f8d71f9f563305wrowe for (i = 0; i < nelts; ++i) {
188dff19ac1e71ffd25752d1a4f8d71f9f563305wrowe elts[i] = sortbin[i].elt;
188dff19ac1e71ffd25752d1a4f8d71f9f563305wrowe }
188dff19ac1e71ffd25752d1a4f8d71f9f563305wrowe
188dff19ac1e71ffd25752d1a4f8d71f9f563305wrowe apr_destroy_pool(tmp);
188dff19ac1e71ffd25752d1a4f8d71f9f563305wrowe}
ec727afb817df0e5202135278c0d2902923cc980stoddard
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*****************************************************************
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * There are some elements of the core config structures in which
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * other modules have a legitimate interest (this is ugly, but necessary
0f57a69cc84c59eacda1179763ae42ca88f1a577wrowe * to preserve NCSA back-compatibility). So, we have a bunch of accessors
6850c836b8c7c688ef8a8ec280e798e1d0bfbf01trawick * here...
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
8a3228198adb03e6996f7738c361a612777ecab6aaronAPI_EXPORT(int) ap_allow_options(request_rec *r)
8a3228198adb03e6996f7738c361a612777ecab6aaron{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding core_dir_config *conf =
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
8a3228198adb03e6996f7738c361a612777ecab6aaron return conf->opts;
8a3228198adb03e6996f7738c361a612777ecab6aaron}
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh
2261031aa94be82d7e6b1b8c367afc1b282317f5ianhAPI_EXPORT(int) ap_allow_overrides(request_rec *r)
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh{
8a3228198adb03e6996f7738c361a612777ecab6aaron core_dir_config *conf;
8a3228198adb03e6996f7738c361a612777ecab6aaron conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh &core_module);
8a3228198adb03e6996f7738c361a612777ecab6aaron
399cf0e5e061b49593817421b94305889fa6bc1fjorton return conf->override;
85c435ceda98eab940615e4466d9c5955252e745wrowe}
85c435ceda98eab940615e4466d9c5955252e745wrowe
8a3228198adb03e6996f7738c361a612777ecab6aaronAPI_EXPORT(const char *) ap_auth_type(request_rec *r)
8a3228198adb03e6996f7738c361a612777ecab6aaron{
8a3228198adb03e6996f7738c361a612777ecab6aaron core_dir_config *conf;
8a3228198adb03e6996f7738c361a612777ecab6aaron
8a3228198adb03e6996f7738c361a612777ecab6aaron conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
8a3228198adb03e6996f7738c361a612777ecab6aaron &core_module);
8a3228198adb03e6996f7738c361a612777ecab6aaron return conf->ap_auth_type;
8a3228198adb03e6996f7738c361a612777ecab6aaron}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
85c435ceda98eab940615e4466d9c5955252e745wroweAPI_EXPORT(const char *) ap_auth_name(request_rec *r)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding core_dir_config *conf;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
ab5581cc78e9d865b0a6ab1404c53347b3276968rbb &core_module);
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh return conf->ap_auth_name;
4e1e8abb2a6e588366a4680b039b460fc5fe1ccdstoddard}
bdf833c0329ee171eb99efe9c037b6ed653c5007aaron
40303323ae9960bd38a0f03d2c10e897a7badd88rbbAPI_EXPORT(const char *) ap_default_type(request_rec *r)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding core_dir_config *conf;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return conf->ap_default_type
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ? conf->ap_default_type
e302f38fd646764ce1a1e1c578d794aef514a9e5sf : DEFAULT_CONTENT_TYPE;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingAPI_EXPORT(const char *) ap_document_root(request_rec *r) /* Don't use this! */
e34223f72e630187c4d8ac7c22da5096c833eb20trawick{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf core_server_config *conf;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conf = (core_server_config *)ap_get_module_config(r->server->module_config,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return conf->ap_document_root;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sfAPI_EXPORT(const apr_array_header_t *) ap_requires(request_rec *r)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh core_dir_config *conf;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return conf->ap_requires;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sfAPI_EXPORT(int) ap_satisfies(request_rec *r)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf core_dir_config *conf;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return conf->satisfy;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf/* Should probably just get rid of this... the only code that cares is
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * part of the core anyway (and in fact, it isn't publicised to other
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * modules).
e302f38fd646764ce1a1e1c578d794aef514a9e5sf */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sfchar *ap_response_code_string(request_rec *r, int error_index)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf core_dir_config *conf;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (conf->response_code_strings == NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return conf->response_code_strings[error_index];
efd83d1dd1a25688a3093c5a542ae16bacef62ddsf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf/* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
e302f38fd646764ce1a1e1c578d794aef514a9e5sfstatic apr_inline void do_double_reverse (conn_rec *conn)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf struct hostent *hptr;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (conn->double_reverse) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* already done */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (conn->remote_host == NULL || conn->remote_host[0] == '\0') {
8a3228198adb03e6996f7738c361a612777ecab6aaron /* single reverse failed, so don't bother */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conn->double_reverse = -1;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf hptr = gethostbyname(conn->remote_host);
baf4649272f3dabd48b095a23b3180cc0105dce6rjung if (hptr) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf char **haddr;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf for (haddr = hptr->h_addr_list; *haddr; haddr++) {
573394373c777e1624a481160f3d02f8fb09f3ffrjung if (((struct in_addr *)(*haddr))->s_addr
e302f38fd646764ce1a1e1c578d794aef514a9e5sf == conn->remote_addr.sin_addr.s_addr) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conn->double_reverse = 1;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conn->double_reverse = -1;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
fcf27b53e98b61c652f3e832561193b21046dd2drjung
e302f38fd646764ce1a1e1c578d794aef514a9e5sfAPI_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf int type)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf struct in_addr *iaddr;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf struct hostent *hptr;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf int hostname_lookups;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* If we haven't checked the host name, and we want to */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (dir_config) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf hostname_lookups =
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ((core_dir_config *)ap_get_module_config(dir_config, &core_module))
573394373c777e1624a481160f3d02f8fb09f3ffrjung ->hostname_lookups;
2b484455736f4c30447aa852764f53282cbeb5ddrbb if (hostname_lookups == HOSTNAME_LOOKUP_UNSET) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf hostname_lookups = HOSTNAME_LOOKUP_OFF;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* the default */
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh hostname_lookups = HOSTNAME_LOOKUP_OFF;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (type != REMOTE_NOLOOKUP
e302f38fd646764ce1a1e1c578d794aef514a9e5sf && conn->remote_host == NULL
e302f38fd646764ce1a1e1c578d794aef514a9e5sf && (type == REMOTE_DOUBLE_REV
e302f38fd646764ce1a1e1c578d794aef514a9e5sf || hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf iaddr = &(conn->remote_addr.sin_addr);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (hptr != NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conn->remote_host = apr_pstrdup(conn->pool, (void *)hptr->h_name);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ap_str_tolower(conn->remote_host);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf do_double_reverse(conn);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (conn->double_reverse != 1) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conn->remote_host = NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* if failed, set it to the NULL string to indicate error */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (conn->remote_host == NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conn->remote_host = "";
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
0ef41d8e4b94d343e5b093c4dbd6ee61c1279401trawick }
8a3228198adb03e6996f7738c361a612777ecab6aaron if (type == REMOTE_DOUBLE_REV) {
8a3228198adb03e6996f7738c361a612777ecab6aaron do_double_reverse(conn);
6951b61f50b21aa93c224b8b0f4966377918ac34stoddard if (conn->double_reverse == -1) {
6951b61f50b21aa93c224b8b0f4966377918ac34stoddard return NULL;
6951b61f50b21aa93c224b8b0f4966377918ac34stoddard }
6951b61f50b21aa93c224b8b0f4966377918ac34stoddard }
6951b61f50b21aa93c224b8b0f4966377918ac34stoddard
8a3228198adb03e6996f7738c361a612777ecab6aaron/*
8a3228198adb03e6996f7738c361a612777ecab6aaron * Return the desired information; either the remote DNS name, if found,
8a3228198adb03e6996f7738c361a612777ecab6aaron * or either NULL (if the hostname was requested) or the IP address
8a3228198adb03e6996f7738c361a612777ecab6aaron * (if any identifier was requested).
8a3228198adb03e6996f7738c361a612777ecab6aaron */
8a3228198adb03e6996f7738c361a612777ecab6aaron if (conn->remote_host != NULL && conn->remote_host[0] != '\0') {
8a3228198adb03e6996f7738c361a612777ecab6aaron return conn->remote_host;
8a3228198adb03e6996f7738c361a612777ecab6aaron }
8a3228198adb03e6996f7738c361a612777ecab6aaron else {
8a3228198adb03e6996f7738c361a612777ecab6aaron if (type == REMOTE_HOST || type == REMOTE_DOUBLE_REV) {
8a3228198adb03e6996f7738c361a612777ecab6aaron return NULL;
8a3228198adb03e6996f7738c361a612777ecab6aaron }
8a3228198adb03e6996f7738c361a612777ecab6aaron else {
8a3228198adb03e6996f7738c361a612777ecab6aaron return conn->remote_ip;
8a3228198adb03e6996f7738c361a612777ecab6aaron }
50e421c0e069853bb724f3d816cef543e447c844jorton }
50e421c0e069853bb724f3d816cef543e447c844jorton}
50e421c0e069853bb724f3d816cef543e447c844jorton
50e421c0e069853bb724f3d816cef543e447c844jortonAPI_EXPORT(const char *) ap_get_remote_logname(request_rec *r)
50e421c0e069853bb724f3d816cef543e447c844jorton{
50e421c0e069853bb724f3d816cef543e447c844jorton core_dir_config *dir_conf;
50e421c0e069853bb724f3d816cef543e447c844jorton
50e421c0e069853bb724f3d816cef543e447c844jorton if (r->connection->remote_logname != NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return r->connection->remote_logname;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf/* If we haven't checked the identity, and we want to */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf dir_conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (dir_conf->do_rfc1413 & 1) {
b32d756dae79045a9bc90e0d0b85582f6f28eaf3sf return ap_rfc1413(r->connection, r->server);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
b32d756dae79045a9bc90e0d0b85582f6f28eaf3sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf/* There are two options regarding what the "name" of a server is. The
b32d756dae79045a9bc90e0d0b85582f6f28eaf3sf * "canonical" name as defined by ServerName and Port, or the "client's
b32d756dae79045a9bc90e0d0b85582f6f28eaf3sf * name" as supplied by a possible Host: header or full URI. We never
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * trust the port passed in the client's headers, we always use the
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * port of the actual socket.
b32d756dae79045a9bc90e0d0b85582f6f28eaf3sf *
b32d756dae79045a9bc90e0d0b85582f6f28eaf3sf * The DNS option to UseCanonicalName causes this routine to do a
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * reverse lookup on the local IP address of the connectiona and use
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * that for the ServerName. This makes its value more reliable while
b32d756dae79045a9bc90e0d0b85582f6f28eaf3sf * at the same time allowing Demon's magic virtual hosting to work.
b32d756dae79045a9bc90e0d0b85582f6f28eaf3sf * The assumption is that DNS lookups are sufficiently quick...
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * -- fanf 1998-10-03
e302f38fd646764ce1a1e1c578d794aef514a9e5sf */
e302f38fd646764ce1a1e1c578d794aef514a9e5sfAPI_EXPORT(const char *) ap_get_server_name(request_rec *r)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conn_rec *conn = r->connection;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf core_dir_config *d;
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf &core_module);
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf if (d->use_canonical_name == USE_CANONICAL_NAME_OFF) {
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf return r->hostname ? r->hostname : r->server->server_hostname;
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf }
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf if (d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf if (conn->local_host == NULL) {
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf struct in_addr *iaddr;
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf struct hostent *hptr;
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf iaddr = &(conn->local_addr.sin_addr);
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr),
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf AF_INET);
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf if (hptr != NULL) {
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf conn->local_host = apr_pstrdup(conn->pool,
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf (void *)hptr->h_name);
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf ap_str_tolower(conn->local_host);
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf }
4497075b5e08b0c8ee89425a1758258ae80550fcsf else {
4497075b5e08b0c8ee89425a1758258ae80550fcsf conn->local_host = apr_pstrdup(conn->pool,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf r->server->server_hostname);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
4497075b5e08b0c8ee89425a1758258ae80550fcsf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return conn->local_host;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
4497075b5e08b0c8ee89425a1758258ae80550fcsf /* default */
4497075b5e08b0c8ee89425a1758258ae80550fcsf return r->server->server_hostname;
4497075b5e08b0c8ee89425a1758258ae80550fcsf}
4497075b5e08b0c8ee89425a1758258ae80550fcsf
4497075b5e08b0c8ee89425a1758258ae80550fcsfAPI_EXPORT(unsigned) ap_get_server_port(const request_rec *r)
4497075b5e08b0c8ee89425a1758258ae80550fcsf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf unsigned port;
4497075b5e08b0c8ee89425a1758258ae80550fcsf core_dir_config *d =
e302f38fd646764ce1a1e1c578d794aef514a9e5sf (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf port = r->server->port ? r->server->port : ap_default_port(r);
4497075b5e08b0c8ee89425a1758258ae80550fcsf
4497075b5e08b0c8ee89425a1758258ae80550fcsf if (d->use_canonical_name == USE_CANONICAL_NAME_OFF
4497075b5e08b0c8ee89425a1758258ae80550fcsf || d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
4497075b5e08b0c8ee89425a1758258ae80550fcsf return r->hostname ? ntohs(r->connection->local_addr.sin_port)
4497075b5e08b0c8ee89425a1758258ae80550fcsf : port;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
4497075b5e08b0c8ee89425a1758258ae80550fcsf /* default */
4497075b5e08b0c8ee89425a1758258ae80550fcsf return port;
4497075b5e08b0c8ee89425a1758258ae80550fcsf}
4497075b5e08b0c8ee89425a1758258ae80550fcsf
4497075b5e08b0c8ee89425a1758258ae80550fcsfAPI_EXPORT(char *) ap_construct_url(apr_pool_t *p, const char *uri,
4497075b5e08b0c8ee89425a1758258ae80550fcsf request_rec *r)
4497075b5e08b0c8ee89425a1758258ae80550fcsf{
4497075b5e08b0c8ee89425a1758258ae80550fcsf unsigned port = ap_get_server_port(r);
4497075b5e08b0c8ee89425a1758258ae80550fcsf const char *host = ap_get_server_name(r);
4497075b5e08b0c8ee89425a1758258ae80550fcsf
4497075b5e08b0c8ee89425a1758258ae80550fcsf if (ap_is_default_port(port, r)) {
4497075b5e08b0c8ee89425a1758258ae80550fcsf return apr_pstrcat(p, ap_http_method(r), "://", host, uri, NULL);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
4497075b5e08b0c8ee89425a1758258ae80550fcsf return apr_psprintf(p, "%s://%s:%u%s", ap_http_method(r), host, port, uri);
4497075b5e08b0c8ee89425a1758258ae80550fcsf}
4497075b5e08b0c8ee89425a1758258ae80550fcsf
4497075b5e08b0c8ee89425a1758258ae80550fcsfAPI_EXPORT(unsigned long) ap_get_limit_req_body(const request_rec *r)
4497075b5e08b0c8ee89425a1758258ae80550fcsf{
4497075b5e08b0c8ee89425a1758258ae80550fcsf core_dir_config *d =
4497075b5e08b0c8ee89425a1758258ae80550fcsf (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
4497075b5e08b0c8ee89425a1758258ae80550fcsf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return d->limit_req_body;
ce4dc40a4e87991087488f70d96d3447d7557294sf}
ce4dc40a4e87991087488f70d96d3447d7557294sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf#ifdef WIN32
e302f38fd646764ce1a1e1c578d794aef514a9e5sfstatic apr_status_t get_win32_registry_default_value(apr_pool_t *p, HKEY hkey,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf char* relativepath,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf char **value)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf HKEY hkeyOpen;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf DWORD type;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf DWORD size = 0;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf DWORD result = RegOpenKeyEx(hkey, relativepath, 0,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf KEY_QUERY_VALUE, &hkeyOpen);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (result != ERROR_SUCCESS)
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh return APR_FROM_OS_ERROR(result);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* Read to NULL buffer to determine value size */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf result = RegQueryValueEx(hkeyOpen, "", 0, &type, NULL, &size);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (result == ERROR_SUCCESS) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if ((size < 2) || (type != REG_SZ && type != REG_EXPAND_SZ)) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf result = ERROR_INVALID_PARAMETER;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf *value = apr_palloc(p, size);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* Read value based on size query above */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf result = RegQueryValueEx(hkeyOpen, "", 0, &type, *value, &size);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* TODO: This might look fine, but we need to provide some warning
b32d756dae79045a9bc90e0d0b85582f6f28eaf3sf * somewhere that some environment variables may -not- be translated,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * seeing as we may have chopped the environment table down somewhat.
e302f38fd646764ce1a1e1c578d794aef514a9e5sf */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if ((result == ERROR_SUCCESS) && (type == REG_EXPAND_SZ))
e302f38fd646764ce1a1e1c578d794aef514a9e5sf {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf char *tmp = *value;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf size = ExpandEnvironmentStrings(tmp, *value, 0);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (size) {
06bc0ed097a567a63ec01ce7b8044221478cb5cdsf *value = apr_palloc(p, size);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf size = ExpandEnvironmentStrings(tmp, *value, size);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
b32d756dae79045a9bc90e0d0b85582f6f28eaf3sf }
06bc0ed097a567a63ec01ce7b8044221478cb5cdsf
ce4dc40a4e87991087488f70d96d3447d7557294sf RegCloseKey(hkeyOpen);
ce4dc40a4e87991087488f70d96d3447d7557294sf return APR_FROM_OS_ERROR(result);
ce4dc40a4e87991087488f70d96d3447d7557294sf}
ce4dc40a4e87991087488f70d96d3447d7557294sf
ce4dc40a4e87991087488f70d96d3447d7557294sfstatic char* get_interpreter_from_win32_registry(apr_pool_t *p, const char* ext,
ce4dc40a4e87991087488f70d96d3447d7557294sf char** arguments, int strict)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
ce4dc40a4e87991087488f70d96d3447d7557294sf char execcgi_path[] = "SHELL\\EXECCGI\\COMMAND";
ce4dc40a4e87991087488f70d96d3447d7557294sf char execopen_path[] = "SHELL\\OPEN\\COMMAND";
ce4dc40a4e87991087488f70d96d3447d7557294sf char typeName[MAX_PATH];
e302f38fd646764ce1a1e1c578d794aef514a9e5sf int cmdOfName = FALSE;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf HKEY hkeyName;
ce4dc40a4e87991087488f70d96d3447d7557294sf HKEY hkeyType;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf DWORD type;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf int size;
ce4dc40a4e87991087488f70d96d3447d7557294sf int result;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf char *buffer;
ce4dc40a4e87991087488f70d96d3447d7557294sf char *s;
ce4dc40a4e87991087488f70d96d3447d7557294sf
ce4dc40a4e87991087488f70d96d3447d7557294sf if (!ext)
ce4dc40a4e87991087488f70d96d3447d7557294sf return NULL;
ce4dc40a4e87991087488f70d96d3447d7557294sf /*
ce4dc40a4e87991087488f70d96d3447d7557294sf * Future optimization:
ce4dc40a4e87991087488f70d96d3447d7557294sf * When the registry is successfully searched, store the strings for
ce4dc40a4e87991087488f70d96d3447d7557294sf * interpreter and arguments in an ext hash to speed up subsequent look-ups
ce4dc40a4e87991087488f70d96d3447d7557294sf */
ce4dc40a4e87991087488f70d96d3447d7557294sf
ce4dc40a4e87991087488f70d96d3447d7557294sf /* Open the key associated with the script filetype extension */
ce4dc40a4e87991087488f70d96d3447d7557294sf result = RegOpenKeyEx(HKEY_CLASSES_ROOT, ext, 0, KEY_QUERY_VALUE,
ce4dc40a4e87991087488f70d96d3447d7557294sf &hkeyType);
ce4dc40a4e87991087488f70d96d3447d7557294sf
ce4dc40a4e87991087488f70d96d3447d7557294sf if (result != ERROR_SUCCESS)
ce4dc40a4e87991087488f70d96d3447d7557294sf return NULL;
ce4dc40a4e87991087488f70d96d3447d7557294sf
ce4dc40a4e87991087488f70d96d3447d7557294sf /* Retrieve the name of the script filetype extension */
ce4dc40a4e87991087488f70d96d3447d7557294sf size = sizeof(typeName);
ce4dc40a4e87991087488f70d96d3447d7557294sf result = RegQueryValueEx(hkeyType, "", NULL, &type, typeName, &size);
ce4dc40a4e87991087488f70d96d3447d7557294sf
ce4dc40a4e87991087488f70d96d3447d7557294sf if (result == ERROR_SUCCESS && type == REG_SZ && typeName[0]) {
ce4dc40a4e87991087488f70d96d3447d7557294sf /* Open the key associated with the script filetype extension */
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf result = RegOpenKeyEx(HKEY_CLASSES_ROOT, typeName, 0,
9228509ac5da8374df4a5d50b7da139e7b31f8a3sf KEY_QUERY_VALUE, &hkeyName);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (result == ERROR_SUCCESS)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf cmdOfName = TRUE;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* Open the key for the script command path by:
e302f38fd646764ce1a1e1c578d794aef514a9e5sf *
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * 1) the 'named' filetype key for ExecCGI/Command
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * 2) the extension's type key for ExecCGI/Command
e302f38fd646764ce1a1e1c578d794aef514a9e5sf *
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * and if the strict arg is false, then continue trying:
e302f38fd646764ce1a1e1c578d794aef514a9e5sf *
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * 3) the 'named' filetype key for Open/Command
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * 4) the extension's type key for Open/Command
e302f38fd646764ce1a1e1c578d794aef514a9e5sf */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (cmdOfName) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf result = get_win32_registry_default_value(p, hkeyName,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf execcgi_path, &buffer);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (!cmdOfName || (result != ERROR_SUCCESS)) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf result = get_win32_registry_default_value(p, hkeyType,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf execcgi_path, &buffer);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (!strict && cmdOfName && (result != ERROR_SUCCESS)) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf result = get_win32_registry_default_value(p, hkeyName,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf execopen_path, &buffer);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (!strict && (result != ERROR_SUCCESS)) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf result = get_win32_registry_default_value(p, hkeyType,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf execopen_path, &buffer);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (cmdOfName)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf RegCloseKey(hkeyName);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf RegCloseKey(hkeyType);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (result != ERROR_SUCCESS)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /*
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * The canonical way shell command entries are entered in the Win32
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * registry is as follows:
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * shell [options] "%1" [args]
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * where
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * shell - full path name to interpreter or shell to run.
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * E.g., c:\usr\local\ntreskit\perl\bin\perl.exe
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * options - optional switches
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * E.g., \C
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * "%1" - Place holder for file to run the shell against.
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * Typically quoted.
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * options - additional arguments
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * E.g., /silent
e302f38fd646764ce1a1e1c578d794aef514a9e5sf *
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * If we find a %1 or a quoted %1, lop off the remainder to arguments.
e302f38fd646764ce1a1e1c578d794aef514a9e5sf */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (buffer && *buffer) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if ((s = strstr(buffer, "\"%1")))
1939c6929d01cf9be05ed767714c6012edc5c035sf {
1939c6929d01cf9be05ed767714c6012edc5c035sf *s = '\0';
1939c6929d01cf9be05ed767714c6012edc5c035sf *arguments = s + 4;
1939c6929d01cf9be05ed767714c6012edc5c035sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else if ((s = strstr(buffer, "%1")))
e302f38fd646764ce1a1e1c578d794aef514a9e5sf {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf *s = '\0';
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *arguments = buffer + 2;
82acfa3f57607ae78326104c420a317260554a47nd }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else
e302f38fd646764ce1a1e1c578d794aef514a9e5sf *arguments = strchr(buffer, '\0');
9fe315e66ef597a158db81bcbd230d7a5d65785dnd while (**arguments && isspace(**arguments))
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ++*arguments;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return buffer;
82acfa3f57607ae78326104c420a317260554a47nd}
e698258fd17a7f9d51cb2b35e96f8f0b48ec23c8nd
e302f38fd646764ce1a1e1c578d794aef514a9e5sfAPI_EXPORT (file_type_e) ap_get_win32_interpreter(const request_rec *r,
e698258fd17a7f9d51cb2b35e96f8f0b48ec23c8nd char** interpreter,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf char** arguments)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf HANDLE hFile;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf DWORD nBytesRead;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf BOOLEAN bResult;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf char buffer[1024];
e302f38fd646764ce1a1e1c578d794aef514a9e5sf core_dir_config *d;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf int i;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf file_type_e fileType = eFileTypeUNKNOWN;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf char *ext = NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf char *exename = NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* Find the file extension */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf exename = strrchr(r->filename, '/');
9fe315e66ef597a158db81bcbd230d7a5d65785dnd if (!exename) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf exename = strrchr(r->filename, '\\');
e698258fd17a7f9d51cb2b35e96f8f0b48ec23c8nd }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (!exename) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf exename = r->filename;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf exename++;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ext = strrchr(exename, '.');
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (ext && (!strcasecmp(ext,".bat") || !strcasecmp(ext,".cmd")))
e302f38fd646764ce1a1e1c578d794aef514a9e5sf {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf char *comspec = getenv("COMSPEC");
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (comspec) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf *interpreter = apr_pstrcat(r->pool, "\"", comspec, "\" /c ", NULL);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return eFileTypeSCRIPT;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r->server,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf "Failed to start a '%s' file as a script." APR_EOL_STR
e302f38fd646764ce1a1e1c578d794aef514a9e5sf "\tCOMSPEC variable is missing from the environment.", ext);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return eFileTypeUNKNOWN;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
9fe315e66ef597a158db81bcbd230d7a5d65785dnd
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* If the file has an extension and it is not .com and not .exe and
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * we've been instructed to search the registry, then do it!
e302f38fd646764ce1a1e1c578d794aef514a9e5sf */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (ext && strcasecmp(ext,".exe") && strcasecmp(ext,".com") &&
e302f38fd646764ce1a1e1c578d794aef514a9e5sf (d->script_interpreter_source == INTERPRETER_SOURCE_REGISTRY ||
e698258fd17a7f9d51cb2b35e96f8f0b48ec23c8nd d->script_interpreter_source == INTERPRETER_SOURCE_REGISTRY_STRICT)) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* Check the registry */
e698258fd17a7f9d51cb2b35e96f8f0b48ec23c8nd int strict = (d->script_interpreter_source
e302f38fd646764ce1a1e1c578d794aef514a9e5sf == INTERPRETER_SOURCE_REGISTRY_STRICT);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf *interpreter = get_interpreter_from_win32_registry(r->pool, ext,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf arguments, strict);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (*interpreter)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return eFileTypeSCRIPT;
b5c4b00201fdc3ed11c6cc05cf3f9a7912ac0cfbsf else if (d->script_interpreter_source == INTERPRETER_SOURCE_REGISTRY_STRICT) {
b5c4b00201fdc3ed11c6cc05cf3f9a7912ac0cfbsf ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r->server,
b5c4b00201fdc3ed11c6cc05cf3f9a7912ac0cfbsf "ScriptInterpreterSource config directive set to \"registry-strict\"." APR_EOL_STR
b5c4b00201fdc3ed11c6cc05cf3f9a7912ac0cfbsf "\tInterpreter not found for files of type '%s'.", ext);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return eFileTypeUNKNOWN;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else
e302f38fd646764ce1a1e1c578d794aef514a9e5sf {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r->server,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf "ScriptInterpreterSource config directive set to \"registry\"." APR_EOL_STR
e302f38fd646764ce1a1e1c578d794aef514a9e5sf "\tInterpreter not found for files of type '%s', "
e302f38fd646764ce1a1e1c578d794aef514a9e5sf "trying \"script\" method...", ext);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* Need to peek into the file figure out what it really is... */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf hFile = CreateFile(r->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (hFile == INVALID_HANDLE_VALUE) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return eFileTypeUNKNOWN;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf bResult = ReadFile(hFile, (void*) &buffer, sizeof(buffer) - 1,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf &nBytesRead, NULL);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (!bResult || (nBytesRead == 0)) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ap_log_rerror(APLOG_MARK, APLOG_ERR, GetLastError(), r,
d2e443764d6855a4a06c8eb2b7708ab9b465ddeerbb "ReadFile(%s) failed", r->filename);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf CloseHandle(hFile);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return eFileTypeUNKNOWN;
d2e443764d6855a4a06c8eb2b7708ab9b465ddeerbb }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf CloseHandle(hFile);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf buffer[nBytesRead] = '\0';
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Script or executable, that is the question... */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((buffer[0] == '#') && (buffer[1] == '!')) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* Assuming file is a script since it starts with a shebang */
8a3228198adb03e6996f7738c361a612777ecab6aaron fileType = eFileTypeSCRIPT;
e7daae8d2ef0165e83627188bf33655c0b8266e8wrowe for (i = 2; i < sizeof(buffer); i++) {
8a3228198adb03e6996f7738c361a612777ecab6aaron if ((buffer[i] == '\r')
a1de70bda57b72d8cc6b47ea744e0973ed424f56wrowe || (buffer[i] == '\n')) {
066877f1a045103acfdd376d48cdd473c33f409bdougm break;
8a3228198adb03e6996f7738c361a612777ecab6aaron }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding buffer[i] = '\0';
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 2; buffer[i] == ' ' ; ++i)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *interpreter = apr_pstrdup(r->pool, buffer + i );
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* Not a script, is it an executable? */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf IMAGE_DOS_HEADER *hdr = (IMAGE_DOS_HEADER*)buffer;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if ((nBytesRead >= sizeof(IMAGE_DOS_HEADER)) && (hdr->e_magic == IMAGE_DOS_SIGNATURE)) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (hdr->e_lfarlc < 0x40)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf fileType = eFileTypeEXE16;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else
e302f38fd646764ce1a1e1c578d794aef514a9e5sf fileType = eFileTypeEXE32;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else
e302f38fd646764ce1a1e1c578d794aef514a9e5sf fileType = eFileTypeUNKNOWN;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return fileType;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf#endif
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf/*****************************************************************
e302f38fd646764ce1a1e1c578d794aef514a9e5sf *
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * Commands... this module handles almost all of the NCSA httpd.conf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf * commands, but most of the old srm.conf is in the the modules.
e302f38fd646764ce1a1e1c578d794aef514a9e5sf */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf/* returns a parent if it matches the given directive */
e302f38fd646764ce1a1e1c578d794aef514a9e5sfstatic const ap_directive_t * find_parent(const ap_directive_t *dirp,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf const char *what)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf while (dirp->parent != NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf dirp = dirp->parent;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf /* ### it would be nice to have atom-ized directives */
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (strcasecmp(dirp->directive, what) == 0)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return dirp;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sfAPI_EXPORT(const char *) ap_check_cmd_context(cmd_parms *cmd,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf unsigned forbidden)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf const char *gt = (cmd->cmd->name[0] == '<'
e302f38fd646764ce1a1e1c578d794aef514a9e5sf && cmd->cmd->name[strlen(cmd->cmd->name)-1] != '>')
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ? ">" : "";
e302f38fd646764ce1a1e1c578d794aef514a9e5sf const ap_directive_t *found;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if ((forbidden & NOT_IN_VIRTUALHOST) && cmd->server->is_virtual) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf " cannot occur within <VirtualHost> section", NULL);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if ((forbidden & NOT_IN_LIMIT) && cmd->limited != -1) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf " cannot occur within <Limit> section", NULL);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if ((forbidden & NOT_IN_DIR_LOC_FILE) == NOT_IN_DIR_LOC_FILE
e302f38fd646764ce1a1e1c578d794aef514a9e5sf && cmd->path != NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf " cannot occur within <Directory/Location/Files> "
e302f38fd646764ce1a1e1c578d794aef514a9e5sf "section", NULL);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (((forbidden & NOT_IN_DIRECTORY)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf && ((found = find_parent(cmd->directive, "<Directory"))
e302f38fd646764ce1a1e1c578d794aef514a9e5sf || (found = find_parent(cmd->directive, "<DirectoryMatch"))))
e302f38fd646764ce1a1e1c578d794aef514a9e5sf || ((forbidden & NOT_IN_LOCATION)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf && ((found = find_parent(cmd->directive, "<Location"))
e302f38fd646764ce1a1e1c578d794aef514a9e5sf || (found = find_parent(cmd->directive, "<LocationMatch"))))
e302f38fd646764ce1a1e1c578d794aef514a9e5sf || ((forbidden & NOT_IN_FILES)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf && ((found = find_parent(cmd->directive, "<Files"))
e302f38fd646764ce1a1e1c578d794aef514a9e5sf || (found = find_parent(cmd->directive, "<FilesMatch"))))) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf " cannot occur within ", found->directive,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf "> section", NULL);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sfstatic const char *set_access_name(cmd_parms *cmd, void *dummy,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf const char *arg)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf void *sconf = cmd->server->module_config;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf core_server_config *conf = ap_get_module_config(sconf, &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf const char *err = ap_check_cmd_context(cmd,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (err != NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return err;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conf->access_name = apr_pstrdup(cmd->pool, arg);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf#ifdef GPROF
e302f38fd646764ce1a1e1c578d794aef514a9e5sfstatic const char *set_gprof_dir(cmd_parms *cmd, void *dummy, char *arg)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf void *sconf = cmd->server->module_config;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf core_server_config *conf = ap_get_module_config(sconf, &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf const char *err = ap_check_cmd_context(cmd,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (err != NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return err;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conf->gprof_dir = apr_pstrdup(cmd->pool, arg);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf#endif /*GPROF*/
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sfstatic const char *set_add_default_charset(cmd_parms *cmd,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf void *d_, const char *arg)
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf core_dir_config *d=d_;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (err != NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return err;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (!strcasecmp(arg, "Off")) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf d->add_default_charset = ADD_DEFAULT_CHARSET_OFF;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else if (!strcasecmp(arg, "On")) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf d->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf d->add_default_charset_name = arg;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sfstatic const char *set_document_root(cmd_parms *cmd, void *dummy,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf const char *arg)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf void *sconf = cmd->server->module_config;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf core_server_config *conf = ap_get_module_config(sconf, &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf const char *err = ap_check_cmd_context(cmd,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (err != NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return err;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf arg = ap_os_canonical_filename(cmd->pool, arg);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (/* TODO: ap_configtestonly && ap_docrootcheck && */ !ap_is_directory(arg)) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (cmd->server->is_virtual) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf "Warning: DocumentRoot [%s] does not exist",
e302f38fd646764ce1a1e1c578d794aef514a9e5sf arg);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf else {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return "DocumentRoot must be a directory";
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conf->ap_document_root = arg;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return NULL;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sfAPI_EXPORT(void) ap_custom_response(request_rec *r, int status, char *string)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf core_dir_config *conf =
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ap_get_module_config(r->per_dir_config, &core_module);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf int idx;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if(conf->response_code_strings == NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conf->response_code_strings =
e302f38fd646764ce1a1e1c578d794aef514a9e5sf apr_pcalloc(r->pool,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf sizeof(*conf->response_code_strings) *
e302f38fd646764ce1a1e1c578d794aef514a9e5sf RESPONSE_CODES);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf idx = ap_index_of_response(status);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf conf->response_code_strings[idx] =
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ((ap_is_url(string) || (*string == '/')) && (*string != '"')) ?
e302f38fd646764ce1a1e1c578d794aef514a9e5sf apr_pstrdup(r->pool, string) : apr_pstrcat(r->pool, "\"", string, NULL);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf}
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sfstatic const char *set_error_document(cmd_parms *cmd, void *conf_,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *errno_str, const char *msg)
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh{
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf core_dir_config *conf=conf_;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf int error_number, index_number, idx500;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf enum { MSG, LOCAL_PATH, REMOTE_PATH } what = MSG;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (err != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return err;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf }
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf
3597d6b10c88c252f156fe8061b659a38dea38c2rbb /* 1st parameter should be a 3 digit number, which we recognize;
3597d6b10c88c252f156fe8061b659a38dea38c2rbb * convert it into an array index
3597d6b10c88c252f156fe8061b659a38dea38c2rbb */
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf error_number = atoi(errno_str);
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf idx500 = ap_index_of_response(HTTP_INTERNAL_SERVER_ERROR);
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf
3597d6b10c88c252f156fe8061b659a38dea38c2rbb if (error_number == HTTP_INTERNAL_SERVER_ERROR) {
3597d6b10c88c252f156fe8061b659a38dea38c2rbb index_number = idx500;
3597d6b10c88c252f156fe8061b659a38dea38c2rbb }
3597d6b10c88c252f156fe8061b659a38dea38c2rbb else if ((index_number = ap_index_of_response(error_number)) == idx500) {
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf return apr_pstrcat(cmd->pool, "Unsupported HTTP response code ",
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf errno_str, NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Heuristic to determine second argument. */
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf if (ap_strchr_c(msg,' '))
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf what = MSG;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf else if (msg[0] == '/')
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding what = LOCAL_PATH;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ap_is_url(msg))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding what = REMOTE_PATH;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf what = MSG;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh /* The entry should be ignored if it is a full URL for a 401 error */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
2b13bc45632d72cdf50ac42149e4fc8bc0d05bf2stoddard if (error_number == 401 && what == REMOTE_PATH) {
2b13bc45632d72cdf50ac42149e4fc8bc0d05bf2stoddard ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, cmd->server,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "cannot use a full URL in a 401 ErrorDocument "
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "directive --- ignoring!");
2b13bc45632d72cdf50ac42149e4fc8bc0d05bf2stoddard }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else { /* Store it... */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (conf->response_code_strings == NULL) {
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh conf->response_code_strings =
2b13bc45632d72cdf50ac42149e4fc8bc0d05bf2stoddard apr_pcalloc(cmd->pool,
2b13bc45632d72cdf50ac42149e4fc8bc0d05bf2stoddard sizeof(*conf->response_code_strings) * RESPONSE_CODES);
8a3228198adb03e6996f7738c361a612777ecab6aaron }
8a3228198adb03e6996f7738c361a612777ecab6aaron /* hack. Prefix a " if it is a msg; as that is what
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh * http_protocol.c relies on to distinguish between
8a3228198adb03e6996f7738c361a612777ecab6aaron * a msg and a (local) path.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding conf->response_code_strings[index_number] = (what == MSG) ?
e34223f72e630187c4d8ac7c22da5096c833eb20trawick apr_pstrcat(cmd->pool, "\"",msg,NULL) :
e34223f72e630187c4d8ac7c22da5096c833eb20trawick apr_pstrdup(cmd->pool, msg);
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf }
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf return NULL;
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf}
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf
7538cfc9bcb1132e87011484b826c0d8bff9cc73sfstatic const char *set_override(cmd_parms *cmd, void *d_, const char *l)
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf{
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf core_dir_config *d=d_;
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf char *w;
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf if (err != NULL) {
7538cfc9bcb1132e87011484b826c0d8bff9cc73sf return err;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf }
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf d->override = OR_NONE;
e34223f72e630187c4d8ac7c22da5096c833eb20trawick while (l[0]) {
e34223f72e630187c4d8ac7c22da5096c833eb20trawick w = ap_getword_conf(cmd->pool, &l);
e34223f72e630187c4d8ac7c22da5096c833eb20trawick if (!strcasecmp(w, "Limit")) {
e34223f72e630187c4d8ac7c22da5096c833eb20trawick d->override |= OR_LIMIT;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf }
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf else if (!strcasecmp(w, "Options")) {
e34223f72e630187c4d8ac7c22da5096c833eb20trawick d->override |= OR_OPTIONS;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (!strcasecmp(w, "FileInfo")) {
bd27541a0c96caa881f17a490e23cdd220d480c8poirier d->override |= OR_FILEINFO;
bd27541a0c96caa881f17a490e23cdd220d480c8poirier }
bd27541a0c96caa881f17a490e23cdd220d480c8poirier else if (!strcasecmp(w, "AuthConfig")) {
bd27541a0c96caa881f17a490e23cdd220d480c8poirier d->override |= OR_AUTHCFG;
bd27541a0c96caa881f17a490e23cdd220d480c8poirier }
bd27541a0c96caa881f17a490e23cdd220d480c8poirier else if (!strcasecmp(w, "Indexes")) {
bd27541a0c96caa881f17a490e23cdd220d480c8poirier d->override |= OR_INDEXES;
bd27541a0c96caa881f17a490e23cdd220d480c8poirier }
bd27541a0c96caa881f17a490e23cdd220d480c8poirier else if (!strcasecmp(w, "None")) {
bd27541a0c96caa881f17a490e23cdd220d480c8poirier d->override = OR_NONE;
bd27541a0c96caa881f17a490e23cdd220d480c8poirier }
bd27541a0c96caa881f17a490e23cdd220d480c8poirier else if (!strcasecmp(w, "All")) {
bd27541a0c96caa881f17a490e23cdd220d480c8poirier d->override = OR_ALL;
bd27541a0c96caa881f17a490e23cdd220d480c8poirier }
bd27541a0c96caa881f17a490e23cdd220d480c8poirier else {
bd27541a0c96caa881f17a490e23cdd220d480c8poirier return apr_pstrcat(cmd->pool, "Illegal override option ", w, NULL);
bd27541a0c96caa881f17a490e23cdd220d480c8poirier }
bd27541a0c96caa881f17a490e23cdd220d480c8poirier d->override &= ~OR_UNSET;
bd27541a0c96caa881f17a490e23cdd220d480c8poirier }
bd27541a0c96caa881f17a490e23cdd220d480c8poirier
bd27541a0c96caa881f17a490e23cdd220d480c8poirier return NULL;
bd27541a0c96caa881f17a490e23cdd220d480c8poirier}
bd27541a0c96caa881f17a490e23cdd220d480c8poirier
bd27541a0c96caa881f17a490e23cdd220d480c8poirierstatic const char *set_options(cmd_parms *cmd, void *d_, const char *l)
bd27541a0c96caa881f17a490e23cdd220d480c8poirier{
bd27541a0c96caa881f17a490e23cdd220d480c8poirier core_dir_config *d=d_;
bd27541a0c96caa881f17a490e23cdd220d480c8poirier allow_options_t opt;
32c4bc04f89b16521718145dc731f750144d7b38wrowe int first = 1;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char action;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm while (l[0]) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *w = ap_getword_conf(cmd->pool, &l);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding action = '\0';
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
32c4bc04f89b16521718145dc731f750144d7b38wrowe if (*w == '+' || *w == '-') {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding action = *(w++);
32c4bc04f89b16521718145dc731f750144d7b38wrowe }
32c4bc04f89b16521718145dc731f750144d7b38wrowe else if (first) {
32c4bc04f89b16521718145dc731f750144d7b38wrowe d->opts = OPT_NONE;
32c4bc04f89b16521718145dc731f750144d7b38wrowe first = 0;
32c4bc04f89b16521718145dc731f750144d7b38wrowe }
32c4bc04f89b16521718145dc731f750144d7b38wrowe
e8f95a682820a599fe41b22977010636be5c2717jim if (!strcasecmp(w, "Indexes")) {
32c4bc04f89b16521718145dc731f750144d7b38wrowe opt = OPT_INDEXES;
32c4bc04f89b16521718145dc731f750144d7b38wrowe }
32c4bc04f89b16521718145dc731f750144d7b38wrowe else if (!strcasecmp(w, "Includes")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding opt = OPT_INCLUDES;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh else if (!strcasecmp(w, "IncludesNOEXEC")) {
8a3228198adb03e6996f7738c361a612777ecab6aaron opt = (OPT_INCLUDES | OPT_INCNOEXEC);
8a3228198adb03e6996f7738c361a612777ecab6aaron }
8a3228198adb03e6996f7738c361a612777ecab6aaron else if (!strcasecmp(w, "FollowSymLinks")) {
8a3228198adb03e6996f7738c361a612777ecab6aaron opt = OPT_SYM_LINKS;
8a3228198adb03e6996f7738c361a612777ecab6aaron }
8a3228198adb03e6996f7738c361a612777ecab6aaron else if (!strcasecmp(w, "SymLinksIfOwnerMatch")) {
8a3228198adb03e6996f7738c361a612777ecab6aaron opt = OPT_SYM_OWNER;
8a3228198adb03e6996f7738c361a612777ecab6aaron }
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick else if (!strcasecmp(w, "execCGI")) {
4bb7ba7c1f9972b443562faf99151ccec854446fjorton opt = OPT_EXECCGI;
4bb7ba7c1f9972b443562faf99151ccec854446fjorton }
4bb7ba7c1f9972b443562faf99151ccec854446fjorton else if (!strcasecmp(w, "MultiViews")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding opt = OPT_MULTI;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
8a3228198adb03e6996f7738c361a612777ecab6aaron else if (!strcasecmp(w, "RunScripts")) { /* AI backcompat. Yuck */
8a3228198adb03e6996f7738c361a612777ecab6aaron opt = OPT_MULTI|OPT_EXECCGI;
8a3228198adb03e6996f7738c361a612777ecab6aaron }
8a3228198adb03e6996f7738c361a612777ecab6aaron else if (!strcasecmp(w, "None")) {
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh opt = OPT_NONE;
cf5ace98ead10d803fda70674cb4dda30fddb832trawick }
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick else if (!strcasecmp(w, "All")) {
2b484455736f4c30447aa852764f53282cbeb5ddrbb opt = OPT_ALL;
8a3228198adb03e6996f7738c361a612777ecab6aaron }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_pstrcat(cmd->pool, "Illegal option ", w, NULL);
95dc871e605e3b1b347adbbbdd9a9caede71c38eminfrin }
066877f1a045103acfdd376d48cdd473c33f409bdougm
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* we ensure the invariant (d->opts_add & d->opts_remove) == 0 */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (action == '-') {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding d->opts_remove |= opt;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick d->opts_add &= ~opt;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick d->opts &= ~opt;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick }
dc64949d88a97fef0bfcb2eed2115dddafc41666wrowe else if (action == '+') {
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick d->opts_add |= opt;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick d->opts_remove &= ~opt;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick d->opts |= opt;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick }
2de7ee14d4925c754a2d3a52d91350b895257df9jerenkrantz else {
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick d->opts |= opt;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick }
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick }
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick return NULL;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick}
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick
e8f95a682820a599fe41b22977010636be5c2717jimstatic const char *satisfy(cmd_parms *cmd, void *c_, const char *arg)
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick{
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick core_dir_config *c=c_;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick if (!strcasecmp(arg, "all")) {
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick c->satisfy = SATISFY_ALL;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick }
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick else if (!strcasecmp(arg, "any")) {
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick c->satisfy = SATISFY_ANY;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick }
2de7ee14d4925c754a2d3a52d91350b895257df9jerenkrantz else {
2de7ee14d4925c754a2d3a52d91350b895257df9jerenkrantz return "Satisfy either 'any' or 'all'.";
2de7ee14d4925c754a2d3a52d91350b895257df9jerenkrantz }
2de7ee14d4925c754a2d3a52d91350b895257df9jerenkrantz return NULL;
2de7ee14d4925c754a2d3a52d91350b895257df9jerenkrantz}
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawickstatic const char *require(cmd_parms *cmd, void *c_, const char *arg)
2de7ee14d4925c754a2d3a52d91350b895257df9jerenkrantz{
2de7ee14d4925c754a2d3a52d91350b895257df9jerenkrantz require_line *r;
f2b43354f9ac8496ab7003ae01211af739efba1atrawick core_dir_config *c=c_;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick if (!c->ap_requires) {
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick c->ap_requires = apr_make_array(cmd->pool, 2, sizeof(require_line));
f2b43354f9ac8496ab7003ae01211af739efba1atrawick }
2de7ee14d4925c754a2d3a52d91350b895257df9jerenkrantz r = (require_line *)apr_push_array(c->ap_requires);
2de7ee14d4925c754a2d3a52d91350b895257df9jerenkrantz r->requirement = apr_pstrdup(cmd->pool, arg);
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick r->method_mask = cmd->limited;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick return NULL;
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick}
e3754dae9df2783c2cd88fa8d46bd0a0765e9820trawick
8a3228198adb03e6996f7738c361a612777ecab6aaronCORE_EXPORT_NONSTD(const char *) ap_limit_section(cmd_parms *cmd, void *dummy,
8a3228198adb03e6996f7738c361a612777ecab6aaron const char *arg) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *limited_methods = ap_getword(cmd->pool, &arg, '>');
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe void *tog = cmd->cmd->cmd_data;
6db54801798f6021bb464de7b3fdcc9dc3150f7bdgaudet int limited = 0;
066877f1a045103acfdd376d48cdd473c33f409bdougm const char *errmsg;
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick
2b484455736f4c30447aa852764f53282cbeb5ddrbb const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
8a3228198adb03e6996f7738c361a612777ecab6aaron if (err != NULL) {
8f0d7adca1c0719b3b1863fb2b9d333d7822567awrowe return err;
8f0d7adca1c0719b3b1863fb2b9d333d7822567awrowe }
8f0d7adca1c0719b3b1863fb2b9d333d7822567awrowe
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (limited_methods[0]) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *method = ap_getword_conf(cmd->pool, &limited_methods);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int methnum = ap_method_number_of(method);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (methnum == M_TRACE && !tog) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return "TRACE cannot be controlled by <Limit>";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
7646be5b9ab5b098bc81d3a08a47e1931dc87597rbb else if (methnum == M_INVALID) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char **xmethod;
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe register int i, j, k;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
f5308a6d396448120986bed14412954788af3e5cjorton /*
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung * Deal with <Limit> by adding the method to the list.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if (!tog) {
db2ef76dc744b13b9a9929ebb9e6f94712a81717rbb if (cmd->limited_xmethods == NULL) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm cmd->limited_xmethods = apr_make_array(cmd->pool, 2,
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb sizeof(char *));
066877f1a045103acfdd376d48cdd473c33f409bdougm }
5a6a87d8920e385b1ed14177d74ab9786f3acddfwrowe xmethod = (char **) apr_push_array(cmd->limited_xmethods);
5a6a87d8920e385b1ed14177d74ab9786f3acddfwrowe *xmethod = apr_pstrdup(cmd->pool, method);
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe }
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe /*
8a3228198adb03e6996f7738c361a612777ecab6aaron * <LimitExcept>, so remove any/all occurrences of the method
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton * in the extension array.
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton */
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe else if ((cmd->limited_xmethods != NULL)
76185d819b745e953dd2cd636fbdd515c333e4a4trawick && (cmd->limited_xmethods->nelts != 0)) {
76185d819b745e953dd2cd636fbdd515c333e4a4trawick xmethod = (char **) cmd->limited_xmethods->elts;
76185d819b745e953dd2cd636fbdd515c333e4a4trawick for (i = 0; i < cmd->limited_xmethods->nelts; ) {
e4c4fcc82268e0192db234c74a6db784b879fffdrbb if (strcmp(xmethod[i], method) == 0) {
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb for (j = i, k = i + 1;
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick k < cmd->limited_xmethods->nelts;
8a3228198adb03e6996f7738c361a612777ecab6aaron ++j, ++k) {
8a3228198adb03e6996f7738c361a612777ecab6aaron xmethod[j] = xmethod[k];
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb cmd->limited_xmethods->nelts--;
7f1290cbf118bf3d34aecc68cff2e5bd0a23e126rbb }
7f1290cbf118bf3d34aecc68cff2e5bd0a23e126rbb }
7f1290cbf118bf3d34aecc68cff2e5bd0a23e126rbb }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm limited |= (1 << methnum);
db2ef76dc744b13b9a9929ebb9e6f94712a81717rbb }
76185d819b745e953dd2cd636fbdd515c333e4a4trawick
76185d819b745e953dd2cd636fbdd515c333e4a4trawick /* Killing two features with one function,
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh * if (tog == NULL) <Limit>, else <LimitExcept>
76185d819b745e953dd2cd636fbdd515c333e4a4trawick */
20c85ca0d404e29972fb94c3d6236a264d1c77abstoddard cmd->limited = tog ? ~limited : limited;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
38cf7a307a8067b5b476403b9fec0bc6d7849cd2jorton errmsg = ap_walk_config(cmd->directive->first_child, cmd, cmd->context);
38cf7a307a8067b5b476403b9fec0bc6d7849cd2jorton
38cf7a307a8067b5b476403b9fec0bc6d7849cd2jorton cmd->limited = -1;
38cf7a307a8067b5b476403b9fec0bc6d7849cd2jorton
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung return errmsg;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton}
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb/* We use this in <DirectoryMatch> and <FilesMatch>, to ensure that
76185d819b745e953dd2cd636fbdd515c333e4a4trawick * people don't get bitten by wrong-cased regex matches
76185d819b745e953dd2cd636fbdd515c333e4a4trawick */
76185d819b745e953dd2cd636fbdd515c333e4a4trawick
76185d819b745e953dd2cd636fbdd515c333e4a4trawick#ifdef WIN32
76185d819b745e953dd2cd636fbdd515c333e4a4trawick#define USE_ICASE REG_ICASE
76185d819b745e953dd2cd636fbdd515c333e4a4trawick#else
76185d819b745e953dd2cd636fbdd515c333e4a4trawick#define USE_ICASE 0
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh
f5308a6d396448120986bed14412954788af3e5cjorton/*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Report a missing-'>' syntax error.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *unclosed_directive(cmd_parms *cmd)
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_pstrcat(cmd->pool, cmd->cmd->name,
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung "> directive missing closing '>'", NULL);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm}
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *dirsection(cmd_parms *cmd, void *mconfig, const char *arg)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
7f1290cbf118bf3d34aecc68cff2e5bd0a23e126rbb const char *errmsg;
7f1290cbf118bf3d34aecc68cff2e5bd0a23e126rbb const char *endp = ap_strrchr_c(arg, '>');
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick int old_overrides = cmd->override;
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick char *old_path = cmd->path;
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick core_dir_config *conf;
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung void *new_dir_conf = ap_create_per_dir_config(cmd->pool);
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick regex_t *r = NULL;
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick const command_rec *thiscmd = cmd->cmd;
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick const char *err = ap_check_cmd_context(cmd,
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick if (err != NULL) {
8a3228198adb03e6996f7738c361a612777ecab6aaron return err;
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick }
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick if (endp == NULL) {
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick return unclosed_directive(cmd);
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung }
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick arg=apr_pstrndup(cmd->pool, arg, endp-arg);
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick cmd->path = ap_getword_conf(cmd->pool, &arg);
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick cmd->override = OR_ALL|ACCESS_CONF;
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick if (thiscmd->cmd_data) { /* <DirectoryMatch> */
8a3228198adb03e6996f7738c361a612777ecab6aaron r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
8a3228198adb03e6996f7738c361a612777ecab6aaron }
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh else if (!strcmp(cmd->path, "~")) {
7f1290cbf118bf3d34aecc68cff2e5bd0a23e126rbb cmd->path = ap_getword_conf(cmd->pool, &arg);
ffb048955d9939c0ab6ff99c2efc412d8e7a191dwrowe r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
ffb048955d9939c0ab6ff99c2efc412d8e7a191dwrowe }
8a3228198adb03e6996f7738c361a612777ecab6aaron#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh else if (strcmp(cmd->path, "/") == 0) {
7f1290cbf118bf3d34aecc68cff2e5bd0a23e126rbb /* Treat 'default' path / as an inalienable root */
8a3228198adb03e6996f7738c361a612777ecab6aaron cmd->path = apr_pstrdup(cmd->pool, cmd->path);
8a3228198adb03e6996f7738c361a612777ecab6aaron }
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick#endif
8a3228198adb03e6996f7738c361a612777ecab6aaron#if defined(HAVE_UNC_PATHS)
8a3228198adb03e6996f7738c361a612777ecab6aaron else if (strcmp(cmd->path, "//") == 0) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Treat UNC path // as an inalienable root */
7f1290cbf118bf3d34aecc68cff2e5bd0a23e126rbb cmd->path = apr_pstrdup(cmd->pool, cmd->path);
8a3228198adb03e6996f7738c361a612777ecab6aaron }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Ensure that the pathname is canonical */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cmd->path = ap_os_canonical_filename(cmd->pool, cmd->path);
c54189c4d2d06d8b374940b32acf20287effff07wrowe }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* initialize our config and fetch it */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding conf = (core_dir_config *)ap_set_config_vectors(cmd, new_dir_conf,
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton &core_module);
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
2a7d0035b5594ddc0907a9cc545e14ae5140c541manoj errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_dir_conf);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (errmsg != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return errmsg;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
c54189c4d2d06d8b374940b32acf20287effff07wrowe conf->r = r;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_add_per_dir_conf(cmd->server, new_dir_conf);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
c54189c4d2d06d8b374940b32acf20287effff07wrowe if (*arg != '\0') {
c54189c4d2d06d8b374940b32acf20287effff07wrowe return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
c54189c4d2d06d8b374940b32acf20287effff07wrowe "> arguments not (yet) supported.", NULL);
c54189c4d2d06d8b374940b32acf20287effff07wrowe }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cmd->path = old_path;
c54189c4d2d06d8b374940b32acf20287effff07wrowe cmd->override = old_overrides;
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe return NULL;
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *urlsection(cmd_parms *cmd, void *mconfig, const char *arg)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm const char *errmsg;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *endp = ap_strrchr_c(arg, '>');
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm int old_overrides = cmd->override;
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb char *old_path = cmd->path;
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe core_dir_config *conf;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton regex_t *r = NULL;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton const command_rec *thiscmd = cmd->cmd;
52bdaf788c70b03fe6f68a5a489cdbe11fb184efwrowe
8a3228198adb03e6996f7738c361a612777ecab6aaron void *new_url_conf = ap_create_per_dir_config(cmd->pool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
8a3228198adb03e6996f7738c361a612777ecab6aaron const char *err = ap_check_cmd_context(cmd,
8a3228198adb03e6996f7738c361a612777ecab6aaron NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
053847fad1e0bfc79d75dd6aec040b78c4d9189erjung if (err != NULL) {
8a3228198adb03e6996f7738c361a612777ecab6aaron return err;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton }
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
8a3228198adb03e6996f7738c361a612777ecab6aaron if (endp == NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return unclosed_directive(cmd);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding arg=apr_pstrndup(cmd->pool, arg, endp-arg);
cddad5fd27fd3b9f4375d76d04bbbeaebec00548wrowe
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb cmd->path = ap_getword_conf(cmd->pool, &arg);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm cmd->override = OR_ALL|ACCESS_CONF;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb if (thiscmd->cmd_data) { /* <LocationMatch> */
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED);
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton }
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb else if (!strcmp(cmd->path, "~")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cmd->path = ap_getword_conf(cmd->pool, &arg);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED);
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe }
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe /* initialize our config and fetch it */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding conf = (core_dir_config *)ap_set_config_vectors(cmd, new_url_conf,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding &core_module);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_url_conf);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (errmsg != NULL)
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe return errmsg;
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh conf->d = apr_pstrdup(cmd->pool, cmd->path); /* No mangling, please */
19702a9985f3b2f794d22be9102d9d4fbf6bebe7rjung conf->d_is_fnmatch = apr_is_fnmatch(conf->d) != 0;
19702a9985f3b2f794d22be9102d9d4fbf6bebe7rjung conf->r = r;
85c435ceda98eab940615e4466d9c5955252e745wrowe
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_add_per_url_conf(cmd->server, new_url_conf);
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if (*arg != '\0') {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton "> arguments not (yet) supported.", NULL);
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton }
066877f1a045103acfdd376d48cdd473c33f409bdougm
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cmd->path = old_path;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cmd->override = old_overrides;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return NULL;
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowestatic const char *filesection(cmd_parms *cmd, void *mconfig, const char *arg)
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe{
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe const char *errmsg;
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe const char *endp = ap_strrchr_c(arg, '>');
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe int old_overrides = cmd->override;
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe char *old_path = cmd->path;
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe core_dir_config *conf;
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe regex_t *r = NULL;
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe const command_rec *thiscmd = cmd->cmd;
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe core_dir_config *c=mconfig;
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe void *new_file_conf = ap_create_per_dir_config(cmd->pool);
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT|NOT_IN_LOCATION);
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe if (err != NULL) {
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe return err;
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe }
44c44a736f11c7785e87b8c4744b3867ad7d8f0bwrowe
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe if (endp == NULL) {
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe return unclosed_directive(cmd);
3d96ee83babeec32482c9082c9426340cee8c44dwrowe }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
066877f1a045103acfdd376d48cdd473c33f409bdougm arg=apr_pstrndup(cmd->pool, arg, endp-arg);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb cmd->path = ap_getword_conf(cmd->pool, &arg);
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf /* Only if not an .htaccess file */
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf if (!old_path) {
1119f286db67c139106e274e0814430cd600b901sf cmd->override = OR_ALL|ACCESS_CONF;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf }
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf if (thiscmd->cmd_data) { /* <FilesMatch> */
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf }
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf else if (!strcmp(cmd->path, "~")) {
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf cmd->path = ap_getword_conf(cmd->pool, &arg);
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf }
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf else {
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf /* Ensure that the pathname is canonical */
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf cmd->path = ap_os_canonical_filename(cmd->pool, cmd->path);
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf }
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf /* initialize our config and fetch it */
aa51f4b9e1f954f9c04d2728a0d7be01719fe0a1sf conf = (core_dir_config *)ap_set_config_vectors(cmd, new_file_conf,
a7318397b355119d990d1f311b951dea2aafc53arbb &core_module);
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_file_conf);
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh if (errmsg != NULL)
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf return errmsg;
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh
ce4dc40a4e87991087488f70d96d3447d7557294sf conf->d = cmd->path;
ce4dc40a4e87991087488f70d96d3447d7557294sf conf->d_is_fnmatch = apr_is_fnmatch(conf->d) != 0;
ce4dc40a4e87991087488f70d96d3447d7557294sf conf->r = r;
ce4dc40a4e87991087488f70d96d3447d7557294sf
ce4dc40a4e87991087488f70d96d3447d7557294sf ap_add_file_conf(c, new_file_conf);
if (*arg != '\0') {
return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
"> arguments not (yet) supported.", NULL);
}
cmd->path = old_path;
cmd->override = old_overrides;
return NULL;
}
static const char *start_ifmod(cmd_parms *cmd, void *mconfig, const char *arg)
{
const char *endp = ap_strrchr_c(arg, '>');
int not = (arg[0] == '!');
module *found;
if (endp == NULL) {
return unclosed_directive(cmd);
}
arg=apr_pstrndup(cmd->pool, arg, endp-arg);
if (not) {
arg++;
}
found = ap_find_linked_module(arg);
if ((!not && found) || (not && !found)) {
ap_directive_t *parent = NULL;
ap_directive_t *current = NULL;
const char *retval;
retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
&current, &parent, "<IfModule");
*(ap_directive_t **)mconfig = current;
return retval;
}
else {
*(ap_directive_t **)mconfig = NULL;
return ap_soak_end_container(cmd, "<IfModule");
}
}
API_EXPORT(int) ap_exists_config_define(const char *name)
{
char **defines;
int i;
defines = (char **)ap_server_config_defines->elts;
for (i = 0; i < ap_server_config_defines->nelts; i++) {
if (strcmp(defines[i], name) == 0) {
return 1;
}
}
return 0;
}
static const char *start_ifdefine(cmd_parms *cmd, void *dummy, const char *arg)
{
const char *endp;
int defined;
int not = 0;
endp = ap_strrchr_c(arg, '>');
if (endp == NULL) {
return unclosed_directive(cmd);
}
arg=apr_pstrndup(cmd->pool, arg, endp-arg);
if (arg[0] == '!') {
not = 1;
arg++;
}
defined = ap_exists_config_define(arg);
if ((!not && defined) || (not && !defined)) {
ap_directive_t *parent = NULL;
ap_directive_t *current = NULL;
const char *retval;
retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
&current, &parent, "<IfDefine");
*(ap_directive_t **)dummy = current;
return retval;
}
else {
*(ap_directive_t **)dummy = NULL;
return ap_soak_end_container(cmd, "<IfDefine");
}
}
/* httpd.conf commands... beginning with the <VirtualHost> business */
static const char *virtualhost_section(cmd_parms *cmd, void *dummy,
const char *arg)
{
server_rec *main_server = cmd->server, *s;
const char *errmsg;
const char *endp = ap_strrchr_c(arg, '>');
apr_pool_t *p = cmd->pool;
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
if (endp == NULL) {
return unclosed_directive(cmd);
}
arg=apr_pstrndup(cmd->pool, arg, endp-arg);
/* FIXME: There's another feature waiting to happen here -- since you
can now put multiple addresses/names on a single <VirtualHost>
you might want to use it to group common definitions and then
define other "subhosts" with their individual differences. But
personally I'd rather just do it with a macro preprocessor. -djg */
if (main_server->is_virtual) {
return "<VirtualHost> doesn't nest!";
}
errmsg = ap_init_virtual_host(p, arg, main_server, &s);
if (errmsg) {
return errmsg;
}
s->next = main_server->next;
main_server->next = s;
s->defn_name = cmd->directive->filename;
s->defn_line_number = cmd->directive->line_num;
cmd->server = s;
errmsg = ap_walk_config(cmd->directive->first_child, cmd,
s->lookup_defaults);
cmd->server = main_server;
return errmsg;
}
static const char *set_server_alias(cmd_parms *cmd, void *dummy,
const char *arg)
{
if (!cmd->server->names) {
return "ServerAlias only used in <VirtualHost>";
}
while (*arg) {
char **item, *name = ap_getword_conf(cmd->pool, &arg);
if (ap_is_matchexp(name)) {
item = (char **)apr_push_array(cmd->server->wild_names);
}
else {
item = (char **)apr_push_array(cmd->server->names);
}
*item = name;
}
return NULL;
}
static const char *add_filter(cmd_parms *cmd, void *dummy, const char *arg)
{
core_dir_config *conf = dummy;
char **newfilter;
newfilter = (char **)apr_push_array(conf->filters);
*newfilter = apr_pstrdup(cmd->pool, arg);
return NULL;
}
static const char *add_input_filter(cmd_parms *cmd, void *dummy, const char *arg)
{
core_dir_config *conf = dummy;
char **newfilter;
newfilter = (char **)apr_push_array(conf->input_filters);
*newfilter = apr_pstrdup(cmd->pool, arg);
return NULL;
}
static const char *add_module_command(cmd_parms *cmd, void *dummy,
const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
if (!ap_add_named_module(arg)) {
return apr_pstrcat(cmd->pool, "Cannot add module via name '", arg,
"': not in list of loaded modules", NULL);
}
*(ap_directive_t **)dummy = NULL;
return NULL;
}
static const char *clear_module_list_command(cmd_parms *cmd, void *dummy)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_clear_module_list();
*(ap_directive_t **)dummy = NULL;
return NULL;
}
static const char *set_server_string_slot(cmd_parms *cmd, void *dummy,
const char *arg)
{
/* This one's pretty generic... */
int offset = (int)(long)cmd->info;
char *struct_ptr = (char *)cmd->server;
const char *err = ap_check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
*(const char **)(struct_ptr + offset) = arg;
return NULL;
}
static const char *server_port(cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
int port;
if (err != NULL) {
return err;
}
port = atoi(arg);
if (port <= 0 || port >= 65536) { /* 65536 == 1<<16 */
return apr_pstrcat(cmd->temp_pool, "The port number \"", arg,
"\" is outside the appropriate range "
"(i.e., 1..65535).", NULL);
}
cmd->server->port = port;
return NULL;
}
static const char *set_signature_flag(cmd_parms *cmd, void *d_,
const char *arg)
{
core_dir_config *d=d_;
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
if (strcasecmp(arg, "On") == 0) {
d->server_signature = srv_sig_on;
}
else if (strcasecmp(arg, "Off") == 0) {
d->server_signature = srv_sig_off;
}
else if (strcasecmp(arg, "EMail") == 0) {
d->server_signature = srv_sig_withmail;
}
else {
return "ServerSignature: use one of: off | on | email";
}
return NULL;
}
static const char *set_server_root(cmd_parms *cmd, void *dummy,
const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
arg = ap_os_canonical_filename(cmd->pool, arg);
if (!ap_is_directory(arg)) {
return "ServerRoot must be a valid directory";
}
ap_server_root = arg;
return NULL;
}
static const char *set_timeout(cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
cmd->server->timeout = atoi(arg);
return NULL;
}
static const char *set_keep_alive_timeout(cmd_parms *cmd, void *dummy,
const char *arg)
{
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
cmd->server->keep_alive_timeout = atoi(arg);
return NULL;
}
static const char *set_keep_alive(cmd_parms *cmd, void *dummy,
const char *arg)
{
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
/* We've changed it to On/Off, but used to use numbers
* so we accept anything but "Off" or "0" as "On"
*/
if (!strcasecmp(arg, "off") || !strcmp(arg, "0")) {
cmd->server->keep_alive = 0;
}
else {
cmd->server->keep_alive = 1;
}
return NULL;
}
static const char *set_keep_alive_max(cmd_parms *cmd, void *dummy,
const char *arg)
{
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
cmd->server->keep_alive_max = atoi(arg);
return NULL;
}
static const char *set_idcheck(cmd_parms *cmd, void *d_, int arg)
{
core_dir_config *d=d_;
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
d->do_rfc1413 = arg != 0;
return NULL;
}
static const char *set_hostname_lookups(cmd_parms *cmd, void *d_,
const char *arg)
{
core_dir_config *d=d_;
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
if (!strcasecmp(arg, "on")) {
d->hostname_lookups = HOSTNAME_LOOKUP_ON;
}
else if (!strcasecmp(arg, "off")) {
d->hostname_lookups = HOSTNAME_LOOKUP_OFF;
}
else if (!strcasecmp(arg, "double")) {
d->hostname_lookups = HOSTNAME_LOOKUP_DOUBLE;
}
else {
return "parameter must be 'on', 'off', or 'double'";
}
return NULL;
}
static const char *set_serverpath(cmd_parms *cmd, void *dummy,
const char *arg)
{
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
cmd->server->path = arg;
cmd->server->pathlen = strlen(arg);
return NULL;
}
static const char *set_content_md5(cmd_parms *cmd, void *d_, int arg)
{
core_dir_config *d=d_;
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
d->content_md5 = arg != 0;
return NULL;
}
static const char *set_use_canonical_name(cmd_parms *cmd, void *d_,
const char *arg)
{
core_dir_config *d=d_;
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
if (strcasecmp(arg, "on") == 0) {
d->use_canonical_name = USE_CANONICAL_NAME_ON;
}
else if (strcasecmp(arg, "off") == 0) {
d->use_canonical_name = USE_CANONICAL_NAME_OFF;
}
else if (strcasecmp(arg, "dns") == 0) {
d->use_canonical_name = USE_CANONICAL_NAME_DNS;
}
else {
return "parameter must be 'on', 'off', or 'dns'";
}
return NULL;
}
static const char *include_config (cmd_parms *cmd, void *dummy,
const char *name)
{
ap_directive_t *conftree = NULL;
ap_process_resource_config(cmd->server,
ap_server_root_relative(cmd->pool, name),
&conftree, cmd->pool, cmd->temp_pool);
*(ap_directive_t **)dummy = conftree;
return NULL;
}
static const char *set_loglevel(cmd_parms *cmd, void *dummy, const char *arg)
{
char *str;
const char *err = ap_check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
if ((str = ap_getword_conf(cmd->pool, &arg))) {
if (!strcasecmp(str, "emerg")) {
cmd->server->loglevel = APLOG_EMERG;
}
else if (!strcasecmp(str, "alert")) {
cmd->server->loglevel = APLOG_ALERT;
}
else if (!strcasecmp(str, "crit")) {
cmd->server->loglevel = APLOG_CRIT;
}
else if (!strcasecmp(str, "error")) {
cmd->server->loglevel = APLOG_ERR;
}
else if (!strcasecmp(str, "warn")) {
cmd->server->loglevel = APLOG_WARNING;
}
else if (!strcasecmp(str, "notice")) {
cmd->server->loglevel = APLOG_NOTICE;
}
else if (!strcasecmp(str, "info")) {
cmd->server->loglevel = APLOG_INFO;
}
else if (!strcasecmp(str, "debug")) {
cmd->server->loglevel = APLOG_DEBUG;
}
else {
return "LogLevel requires level keyword: one of "
"emerg/alert/crit/error/warn/notice/info/debug";
}
}
else {
return "LogLevel requires level keyword";
}
return NULL;
}
API_EXPORT(const char *) ap_psignature(const char *prefix, request_rec *r)
{
char sport[20];
core_dir_config *conf;
conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
&core_module);
if ((conf->server_signature == srv_sig_off)
|| (conf->server_signature == srv_sig_unset)) {
return "";
}
apr_snprintf(sport, sizeof sport, "%u", (unsigned) ap_get_server_port(r));
if (conf->server_signature == srv_sig_withmail) {
return apr_pstrcat(r->pool, prefix, "<ADDRESS>" AP_SERVER_BASEVERSION
" Server at <A HREF=\"mailto:",
r->server->server_admin, "\">",
ap_get_server_name(r), "</A> Port ", sport,
"</ADDRESS>\n", NULL);
}
return apr_pstrcat(r->pool, prefix, "<ADDRESS>" AP_SERVER_BASEVERSION
" Server at ", ap_get_server_name(r), " Port ", sport,
"</ADDRESS>\n", NULL);
}
/*
* Load an authorisation realm into our location configuration, applying the
* usual rules that apply to realms.
*/
static const char *set_authname(cmd_parms *cmd, void *mconfig,
const char *word1)
{
core_dir_config *aconfig = (core_dir_config *)mconfig;
aconfig->ap_auth_name = ap_escape_quotes(cmd->pool, word1);
return NULL;
}
#ifdef _OSD_POSIX /* BS2000 Logon Passwd file */
static const char *set_bs2000_account(cmd_parms *cmd, void *dummy, char *name)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
return os_set_account(cmd->pool, name);
}
#endif /*_OSD_POSIX*/
/*
* Handle a request to include the server's OS platform in the Server
* response header field (the ServerTokens directive). Unfortunately
* this requires a new global in order to communicate the setting back to
* http_main so it can insert the information in the right place in the
* string.
*/
static char *server_version = NULL;
static int version_locked = 0;
enum server_token_type {
SrvTk_MIN, /* eg: Apache/1.3.0 */
SrvTk_OS, /* eg: Apache/1.3.0 (UNIX) */
SrvTk_FULL, /* eg: Apache/1.3.0 (UNIX) PHP/3.0 FooBar/1.2b */
SrvTk_PRODUCT_ONLY /* eg: Apache */
};
static enum server_token_type ap_server_tokens = SrvTk_FULL;
static apr_status_t reset_version(void *dummy)
{
version_locked = 0;
ap_server_tokens = SrvTk_FULL;
server_version = NULL;
return APR_SUCCESS;
}
API_EXPORT(const char *) ap_get_server_version(void)
{
return (server_version ? server_version : AP_SERVER_BASEVERSION);
}
API_EXPORT(void) ap_add_version_component(apr_pool_t *pconf, const char *component)
{
if (! version_locked) {
/*
* If the version string is null, register our cleanup to reset the
* pointer on pool destruction. We also know that, if NULL,
* we are adding the original SERVER_BASEVERSION string.
*/
if (server_version == NULL) {
apr_register_cleanup(pconf, NULL, reset_version,
apr_null_cleanup);
server_version = apr_pstrdup(pconf, component);
}
else {
/*
* Tack the given component identifier to the end of
* the existing string.
*/
server_version = apr_pstrcat(pconf, server_version, " ",
component, NULL);
}
}
}
/*
* This routine adds the real server base identity to the version string,
* and then locks out changes until the next reconfig.
*/
static void ap_set_version(apr_pool_t *pconf)
{
if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT);
}
else if (ap_server_tokens == SrvTk_MIN) {
ap_add_version_component(pconf, AP_SERVER_BASEVERSION);
}
else {
ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
}
/*
* Lock the server_version string if we're not displaying
* the full set of tokens
*/
if (ap_server_tokens != SrvTk_FULL) {
version_locked++;
}
}
static const char *set_serv_tokens(cmd_parms *cmd, void *dummy,
const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
if (!strcasecmp(arg, "OS")) {
ap_server_tokens = SrvTk_OS;
}
else if (!strcasecmp(arg, "Min") || !strcasecmp(arg, "Minimal")) {
ap_server_tokens = SrvTk_MIN;
}
else if (!strcasecmp(arg, "Prod") || !strcasecmp(arg, "ProductOnly")) {
ap_server_tokens = SrvTk_PRODUCT_ONLY;
}
else {
ap_server_tokens = SrvTk_FULL;
}
return NULL;
}
static const char *set_limit_req_line(cmd_parms *cmd, void *dummy,
const char *arg)
{
const char *err = ap_check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
int lim;
if (err != NULL) {
return err;
}
lim = atoi(arg);
if (lim < 0) {
return apr_pstrcat(cmd->temp_pool, "LimitRequestLine \"", arg,
"\" must be a non-negative integer", NULL);
}
if (lim > DEFAULT_LIMIT_REQUEST_LINE) {
return apr_psprintf(cmd->temp_pool, "LimitRequestLine \"%s\" "
"must not exceed the precompiled maximum of %d",
arg, DEFAULT_LIMIT_REQUEST_LINE);
}
cmd->server->limit_req_line = lim;
return NULL;
}
static const char *set_limit_req_fieldsize(cmd_parms *cmd, void *dummy,
const char *arg)
{
const char *err = ap_check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
int lim;
if (err != NULL) {
return err;
}
lim = atoi(arg);
if (lim < 0) {
return apr_pstrcat(cmd->temp_pool, "LimitRequestFieldsize \"", arg,
"\" must be a non-negative integer (0 = no limit)",
NULL);
}
if (lim > DEFAULT_LIMIT_REQUEST_FIELDSIZE) {
return apr_psprintf(cmd->temp_pool, "LimitRequestFieldsize \"%s\" "
"must not exceed the precompiled maximum of %d",
arg, DEFAULT_LIMIT_REQUEST_FIELDSIZE);
}
cmd->server->limit_req_fieldsize = lim;
return NULL;
}
static const char *set_limit_req_fields(cmd_parms *cmd, void *dummy,
const char *arg)
{
const char *err = ap_check_cmd_context(cmd,
NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
int lim;
if (err != NULL) {
return err;
}
lim = atoi(arg);
if (lim < 0) {
return apr_pstrcat(cmd->temp_pool, "LimitRequestFields \"", arg,
"\" must be a non-negative integer (0 = no limit)",
NULL);
}
cmd->server->limit_req_fields = lim;
return NULL;
}
static const char *set_limit_req_body(cmd_parms *cmd, void *conf_,
const char *arg)
{
core_dir_config *conf=conf_;
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
/* WTF: If strtoul is not portable, then write a replacement.
* Instead we have an idiotic define in httpd.h that prevents
* it from being used even when it is available. Sheesh.
*/
conf->limit_req_body = (unsigned long)strtol(arg, (char **)NULL, 10);
return NULL;
}
static const char *set_limit_xml_req_body(cmd_parms *cmd, void *conf_,
const char *arg)
{
core_dir_config *conf = conf_;
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
conf->limit_xml_body = atol(arg);
if (conf->limit_xml_body < 0)
return "LimitXMLRequestBody requires a non-negative integer.";
return NULL;
}
API_EXPORT(size_t) ap_get_limit_xml_body(const request_rec *r)
{
core_dir_config *conf;
conf = ap_get_module_config(r->per_dir_config, &core_module);
if (conf->limit_xml_body == AP_LIMIT_UNSET)
return AP_DEFAULT_LIMIT_XML_BODY;
return (size_t)conf->limit_xml_body;
}
#ifdef WIN32
static const char *set_interpreter_source(cmd_parms *cmd, core_dir_config *d,
char *arg)
{
if (!strcasecmp(arg, "registry")) {
d->script_interpreter_source = INTERPRETER_SOURCE_REGISTRY;
} else if (!strcasecmp(arg, "registry-strict")) {
d->script_interpreter_source = INTERPRETER_SOURCE_REGISTRY_STRICT;
} else if (!strcasecmp(arg, "script")) {
d->script_interpreter_source = INTERPRETER_SOURCE_SHEBANG;
} else {
return apr_pstrcat(cmd->temp_pool, "ScriptInterpreterSource \"", arg,
"\" must be \"registry\", \"registry-strict\" or "
"\"script\"", NULL);
}
return NULL;
}
#endif
#if !defined (RLIMIT_CPU) || !(defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)) || !defined (RLIMIT_NPROC)
static const char *no_set_limit(cmd_parms *cmd, core_dir_config *conf,
const char *arg, const char *arg2)
{
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, cmd->server,
"%s not supported on this platform", cmd->cmd->name);
return NULL;
}
#endif
#ifdef RLIMIT_CPU
static const char *set_limit_cpu(cmd_parms *cmd, void *conf_,
const char *arg, const char *arg2)
{
core_dir_config *conf=conf_;
unixd_set_rlimit(cmd, &conf->limit_cpu, arg, arg2, RLIMIT_CPU);
return NULL;
}
#endif
#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
static const char *set_limit_mem(cmd_parms *cmd, void *conf_,
const char *arg, const char * arg2)
{
core_dir_config *conf=conf_;
#if defined(RLIMIT_AS)
unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2 ,RLIMIT_AS);
#elif defined(RLIMIT_DATA)
unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_DATA);
#elif defined(RLIMIT_VMEM)
unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_VMEM);
#endif
return NULL;
}
#endif
#ifdef RLIMIT_NPROC
static const char *set_limit_nproc(cmd_parms *cmd, void *conf_,
const char *arg, const char * arg2)
{
core_dir_config *conf=conf_;
unixd_set_rlimit(cmd, &conf->limit_nproc, arg, arg2, RLIMIT_NPROC);
return NULL;
}
#endif
static apr_status_t writev_it_all(apr_socket_t *s, struct iovec *vec, int nvec,
apr_size_t len, apr_size_t *nbytes)
{
apr_size_t bytes_written = 0;
apr_status_t rv;
apr_ssize_t n = len;
apr_ssize_t i = 0;
*nbytes = 0;
/* XXX handle checking for non-blocking socket */
while (bytes_written != len) {
rv = apr_sendv(s, vec + i, nvec - i, &n);
bytes_written += n;
if (rv != APR_SUCCESS)
return rv;
/* If the write did not complete, adjust the iovecs and issue
* apr_sendv again
*/
if (bytes_written < len) {
/* Skip over the vectors that have already been written */
apr_size_t cnt = vec[i].iov_len;
while (n >= cnt && i + 1 < nvec) {
i++;
cnt += vec[i].iov_len;
}
if (n < cnt) {
/* Handle partial write of vec i */
vec[i].iov_base = (char *) vec[i].iov_base +
(vec[i].iov_len - (cnt - n));
vec[i].iov_len = cnt -n;
}
}
n = len - bytes_written;
}
return APR_SUCCESS;
}
/*
* send_the_file()
* Sends the contents of file fd along with header/trailer bytes, if any,
* to the network. send_the_file will return only when all the bytes have been
* sent (i.e., it handles partial writes) or on a network error condition.
*/
static apr_status_t send_the_file(conn_rec *c, apr_file_t *fd,
apr_hdtr_t *hdtr, apr_off_t offset,
apr_size_t length, apr_size_t *nbytes)
{
apr_status_t rv = APR_SUCCESS;
apr_int32_t togo; /* Remaining number of bytes in the file to send */
apr_int32_t sendlen;
apr_int32_t bytes_sent;
apr_int32_t i;
apr_off_t o; /* Track the file offset for partial writes */
char buffer[8192];
*nbytes = 0;
/* Send the headers
* writev_it_all handles partial writes.
* XXX: optimization... if headers are less than MIN_WRITE_SIZE, copy
* them into buffer
*/
sendlen = 0;
if ( hdtr && hdtr->numheaders > 0 ) {
for (i = 0; i < hdtr->numheaders; i++) {
sendlen += hdtr->headers[i].iov_len;
}
rv = writev_it_all(c->client->bsock, hdtr->headers, hdtr->numheaders,
sendlen, &bytes_sent);
if (rv == APR_SUCCESS)
*nbytes += bytes_sent; /* track total bytes sent */
}
/* Seek the file to 'offset' */
if (offset != 0 && rv == APR_SUCCESS) {
rv = apr_seek(fd, APR_SET, &offset);
}
/* Send the file, making sure to handle partial writes */
togo = length;
while (rv == APR_SUCCESS && togo) {
sendlen = togo > sizeof(buffer) ? sizeof(buffer) : togo;
o = 0;
rv = apr_read(fd, buffer, &sendlen);
while (rv == APR_SUCCESS && sendlen) {
bytes_sent = sendlen;
rv = apr_send(c->client->bsock, &buffer[o], &bytes_sent);
if (rv == APR_SUCCESS) {
sendlen -= bytes_sent; /* sendlen != bytes_sent ==> partial write */
o += bytes_sent; /* o is where we are in the buffer */
*nbytes += bytes_sent;
togo -= bytes_sent; /* track how much of the file we've sent */
}
}
}
/* Send the trailers
* XXX: optimization... if it will fit, send this on the last send in the
* loop above
*/
sendlen = 0;
if ( rv == APR_SUCCESS && hdtr && hdtr->numtrailers > 0 ) {
for (i = 0; i < hdtr->numtrailers; i++) {
sendlen += hdtr->trailers[i].iov_len;
}
rv = writev_it_all(c->client->bsock, hdtr->trailers, hdtr->numtrailers,
sendlen, &bytes_sent);
if (rv == APR_SUCCESS)
*nbytes += bytes_sent;
}
return rv;
}
/* Note --- ErrorDocument will now work from .htaccess files.
* The AllowOverride of Fileinfo allows webmasters to turn it off
*/
static const command_rec core_cmds[] = {
/* Old access config file commands */
AP_INIT_RAW_ARGS("<Directory", dirsection, NULL, RSRC_CONF,
"Container for directives affecting resources located in the specified "
"directories"),
AP_INIT_RAW_ARGS("<Location", urlsection, NULL, RSRC_CONF,
"Container for directives affecting resources accessed through the "
"specified URL paths"),
AP_INIT_RAW_ARGS("<VirtualHost", virtualhost_section, NULL, RSRC_CONF,
"Container to map directives to a particular virtual host, takes one or "
"more host addresses"),
AP_INIT_RAW_ARGS("<Files", filesection, NULL, OR_ALL,
"Container for directives affecting files matching specified patterns"),
AP_INIT_RAW_ARGS("<Limit", ap_limit_section, NULL, OR_ALL,
"Container for authentication directives when accessed using specified HTTP "
"methods"),
AP_INIT_RAW_ARGS("<LimitExcept", ap_limit_section, (void*)1, OR_ALL,
"Container for authentication directives to be applied when any HTTP "
"method other than those specified is used to access the resource"),
AP_INIT_TAKE1("<IfModule", start_ifmod, NULL, EXEC_ON_READ | OR_ALL,
"Container for directives based on existance of specified modules"),
AP_INIT_TAKE1("<IfDefine", start_ifdefine, NULL, EXEC_ON_READ | OR_ALL,
"Container for directives based on existance of command line defines"),
AP_INIT_RAW_ARGS("<DirectoryMatch", dirsection, (void*)1, RSRC_CONF,
"Container for directives affecting resources located in the "
"specified directories"),
AP_INIT_RAW_ARGS("<LocationMatch", urlsection, (void*)1, RSRC_CONF,
"Container for directives affecting resources accessed through the "
"specified URL paths"),
AP_INIT_RAW_ARGS("<FilesMatch", filesection, (void*)1, OR_ALL,
"Container for directives affecting files matching specified patterns"),
AP_INIT_TAKE1("AuthType", ap_set_string_slot,
(void*)XtOffsetOf(core_dir_config, ap_auth_type), OR_AUTHCFG,
"An HTTP authorization type (e.g., \"Basic\")"),
AP_INIT_TAKE1("AuthName", set_authname, NULL, OR_AUTHCFG,
"The authentication realm (e.g. \"Members Only\")"),
AP_INIT_RAW_ARGS("Require", require, NULL, OR_AUTHCFG,
"Selects which authenticated users or groups may access a protected space"),
AP_INIT_TAKE1("Satisfy", satisfy, NULL, OR_AUTHCFG,
"access policy if both allow and require used ('all' or 'any')"),
#ifdef GPROF
AP_INIT_TAKE1("GprofDir", set_gprof_dir, NULL, RSRC_CONF,
"Directory to plop gmon.out files"),
#endif
AP_INIT_TAKE1("AddDefaultCharset", set_add_default_charset, NULL, OR_FILEINFO,
"The name of the default charset to add to any Content-Type without one or 'Off' to disable"),
/* Old resource config file commands */
AP_INIT_RAW_ARGS("AccessFileName", set_access_name, NULL, RSRC_CONF,
"Name(s) of per-directory config files (default: .htaccess)"),
AP_INIT_TAKE1("DocumentRoot", set_document_root, NULL, RSRC_CONF,
"Root directory of the document tree"),
AP_INIT_TAKE2("ErrorDocument", set_error_document, NULL, OR_FILEINFO,
"Change responses for HTTP errors"),
AP_INIT_RAW_ARGS("AllowOverride", set_override, NULL, ACCESS_CONF,
"Controls what groups of directives can be configured by per-directory "
"config files"),
AP_INIT_RAW_ARGS("Options", set_options, NULL, OR_OPTIONS,
"Set a number of attributes for a given directory"),
AP_INIT_TAKE1("DefaultType", ap_set_string_slot,
(void*)XtOffsetOf (core_dir_config, ap_default_type),
OR_FILEINFO, "the default MIME type for untypable files"),
/* Old server config file commands */
AP_INIT_TAKE1("Port", server_port, NULL, RSRC_CONF, "A TCP port number"),
AP_INIT_TAKE1("HostnameLookups", set_hostname_lookups, NULL,
ACCESS_CONF|RSRC_CONF,
"\"on\" to enable, \"off\" to disable reverse DNS lookups, or \"double\" to "
"enable double-reverse DNS lookups"),
AP_INIT_TAKE1("ServerAdmin", set_server_string_slot,
(void *)XtOffsetOf (server_rec, server_admin), RSRC_CONF,
"The email address of the server administrator"),
AP_INIT_TAKE1("ServerName", set_server_string_slot,
(void *)XtOffsetOf (server_rec, server_hostname), RSRC_CONF,
"The hostname of the server"),
AP_INIT_TAKE1("ServerSignature", set_signature_flag, NULL, OR_ALL,
"En-/disable server signature (on|off|email)"),
AP_INIT_TAKE1("ServerRoot", set_server_root, NULL, RSRC_CONF,
"Common directory of server-related files (logs, confs, etc.)"),
AP_INIT_TAKE1("ErrorLog", set_server_string_slot,
(void *)XtOffsetOf (server_rec, error_fname), RSRC_CONF,
"The filename of the error log"),
AP_INIT_RAW_ARGS("ServerAlias", set_server_alias, NULL, RSRC_CONF,
"A name or names alternately used to access the server"),
AP_INIT_TAKE1("ServerPath", set_serverpath, NULL, RSRC_CONF,
"The pathname the server can be reached at"),
AP_INIT_TAKE1("Timeout", set_timeout, NULL, RSRC_CONF,
"Timeout duration (sec)"),
AP_INIT_TAKE1("KeepAliveTimeout", set_keep_alive_timeout, NULL, RSRC_CONF,
"Keep-Alive timeout duration (sec)"),
AP_INIT_TAKE1("MaxKeepAliveRequests", set_keep_alive_max, NULL, RSRC_CONF,
"Maximum number of Keep-Alive requests per connection, or 0 for infinite"),
AP_INIT_TAKE1("KeepAlive", set_keep_alive, NULL, RSRC_CONF,
"Whether persistent connections should be On or Off"),
AP_INIT_FLAG("IdentityCheck", set_idcheck, NULL, RSRC_CONF|ACCESS_CONF,
"Enable identd (RFC 1413) user lookups - SLOW"),
AP_INIT_FLAG("ContentDigest", set_content_md5, NULL, OR_OPTIONS,
"whether or not to send a Content-MD5 header with each request"),
AP_INIT_TAKE1("UseCanonicalName", set_use_canonical_name, NULL,
RSRC_CONF|ACCESS_CONF,
"How to work out the ServerName : Port when constructing URLs"),
/* TODO: RlimitFoo should all be part of mod_cgi, not in the core */
AP_INIT_ITERATE("AddModule", add_module_command, NULL,
RSRC_CONF, "The name of a module"),
AP_INIT_NO_ARGS("ClearModuleList", clear_module_list_command, NULL,
RSRC_CONF, NULL),
/* TODO: ListenBacklog in MPM */
AP_INIT_TAKE1("Include", include_config, NULL,
(RSRC_CONF | ACCESS_CONF | EXEC_ON_READ),
"Name of the config file to be included"),
AP_INIT_TAKE1("LogLevel", set_loglevel, NULL, RSRC_CONF,
"Level of verbosity in error logging"),
AP_INIT_TAKE1("NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF,
"A numeric IP address:port, or the name of a host"),
#ifdef _OSD_POSIX
AP_INIT_TAKE1("BS2000Account", set_bs2000_account, NULL, RSRC_CONF,
"Name of server User's bs2000 logon account name"),
#endif
#ifdef WIN32
AP_INIT_TAKE1("ScriptInterpreterSource", set_interpreter_source, NULL,
OR_FILEINFO,
"Where to find interpreter to run Win32 scripts (Registry or script shebang line)"),
#endif
AP_INIT_TAKE1("ServerTokens", set_serv_tokens, NULL, RSRC_CONF,
"Determine tokens displayed in the Server: header - Min(imal), OS or Full"),
AP_INIT_TAKE1("LimitRequestLine", set_limit_req_line, NULL, RSRC_CONF,
"Limit on maximum size of an HTTP request line"),
AP_INIT_TAKE1("LimitRequestFieldsize", set_limit_req_fieldsize, NULL,
RSRC_CONF,
"Limit on maximum size of an HTTP request header field"),
AP_INIT_TAKE1("LimitRequestFields", set_limit_req_fields, NULL, RSRC_CONF,
"Limit (0 = unlimited) on max number of header fields in a request message"),
AP_INIT_TAKE1("LimitRequestBody", set_limit_req_body,
(void*)XtOffsetOf(core_dir_config, limit_req_body), OR_ALL,
"Limit (in bytes) on maximum size of request message body"),
AP_INIT_TAKE1("LimitXMLRequestBody", set_limit_xml_req_body, NULL, OR_ALL,
"Limit (in bytes) on maximum size of an XML-based request "
"body"),
/* System Resource Controls */
#ifdef RLIMIT_CPU
AP_INIT_TAKE12("RLimitCPU", set_limit_cpu,
(void*)XtOffsetOf(core_dir_config, limit_cpu),
OR_ALL, "Soft/hard limits for max CPU usage in seconds"),
#else
AP_INIT_TAKE12("RLimitCPU", no_set_limit, NULL,
OR_ALL, "Soft/hard limits for max CPU usage in seconds"),
#endif
#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined (RLIMIT_AS)
AP_INIT_TAKE12("RLimitMEM", set_limit_mem,
(void*)XtOffsetOf(core_dir_config, limit_mem),
OR_ALL, "Soft/hard limits for max memory usage per process"),
#else
AP_INIT_TAKE12("RLimitMEM", no_set_limit, NULL,
OR_ALL, "Soft/hard limits for max memory usage per process"),
#endif
#ifdef RLIMIT_NPROC
AP_INIT_TAKE12("RLimitNPROC", set_limit_nproc,
(void*)XtOffsetOf(core_dir_config, limit_nproc),
OR_ALL, "soft/hard limits for max number of processes per uid"),
#else
AP_INIT_TAKE12("RLimitNPROC", no_set_limit, NULL,
OR_ALL, "soft/hard limits for max number of processes per uid"),
#endif
/* XXX These should be allowable in .htaccess files, but currently it won't
* play well with the Options stuff. Until that is fixed, I would prefer
* to leave it just in the conf file. Other should feel free to disagree
* with me. Rbb.
*/
AP_INIT_ITERATE("AddOutputFilter", add_filter, NULL, ACCESS_CONF,
"filters to be run"),
AP_INIT_ITERATE("AddInputFilter", add_input_filter, NULL, ACCESS_CONF,
"filters to be run on the request body"),
{ NULL }
};
/*****************************************************************
*
* Core handlers for various phases of server operation...
*/
API_EXPORT_NONSTD(int) ap_core_translate(request_rec *r)
{
void *sconf = r->server->module_config;
core_server_config *conf = ap_get_module_config(sconf, &core_module);
if (r->proxyreq) {
return HTTP_FORBIDDEN;
}
if ((r->uri[0] != '/') && strcmp(r->uri, "*")) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
"Invalid URI in request %s", r->the_request);
return HTTP_BAD_REQUEST;
}
if (r->server->path
&& !strncmp(r->uri, r->server->path, r->server->pathlen)
&& (r->server->path[r->server->pathlen - 1] == '/'
|| r->uri[r->server->pathlen] == '/'
|| r->uri[r->server->pathlen] == '\0')) {
r->filename = apr_pstrcat(r->pool, conf->ap_document_root,
(r->uri + r->server->pathlen), NULL);
}
else {
/*
* Make sure that we do not mess up the translation by adding two
* /'s in a row. This happens under windows when the document
* root ends with a /
*/
if ((conf->ap_document_root[strlen(conf->ap_document_root)-1] == '/')
&& (*(r->uri) == '/')) {
r->filename = apr_pstrcat(r->pool, conf->ap_document_root, r->uri+1,
NULL);
}
else {
r->filename = apr_pstrcat(r->pool, conf->ap_document_root, r->uri,
NULL);
}
}
return OK;
}
static int do_nothing(request_rec *r) { return OK; }
/*
* Default handler for MIME types without other handlers. Only GET
* and OPTIONS at this point... anyone who wants to write a generic
* handler for PUT or POST is free to do so, but it seems unwise to provide
* any defaults yet... So, for now, we assume that this will always be
* the last handler called and return 405 or 501.
*/
static int default_handler(request_rec *r)
{
core_dir_config *d =
(core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
int rangestatus, errstatus;
apr_file_t *fd = NULL;
apr_status_t status;
#ifdef USE_MMAP_FILES
apr_mmap_t *mm = NULL;
#endif
/* XXX if/when somebody writes a content-md5 filter we either need to
* remove this support or coordinate when to use the filter vs.
* when to use this code
* The current choice of when to compute the md5 here matches the 1.3
* support fairly closely (unlike 1.3, we don't handle computing md5
* when the charset is translated).
*/
int bld_content_md5 =
(d->content_md5 & 1) && r->output_filters->frec->ftype != AP_FTYPE_CONTENT;
/* This handler has no use for a request body (yet), but we still
* need to read and discard it if the client sent one.
*/
if ((errstatus = ap_discard_request_body(r)) != OK) {
return errstatus;
}
ap_allow_methods(r, MERGE_ALLOW, "GET", "OPTIONS", NULL);
if (r->method_number == M_INVALID) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
"Invalid method in request %s", r->the_request);
return HTTP_NOT_IMPLEMENTED;
}
if (r->method_number == M_OPTIONS) {
return ap_send_http_options(r);
}
if (r->method_number == M_PUT) {
return HTTP_METHOD_NOT_ALLOWED;
}
if (r->finfo.protection == 0 || (r->path_info && *r->path_info)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
"File does not exist: %s",r->path_info ?
apr_pstrcat(r->pool, r->filename, r->path_info, NULL)
: r->filename);
return HTTP_NOT_FOUND;
}
if (r->method_number != M_GET) {
return HTTP_METHOD_NOT_ALLOWED;
}
if ((status = apr_open(&fd, r->filename, APR_READ | APR_BINARY, 0, r->pool)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
"file permissions deny server access: %s", r->filename);
return HTTP_FORBIDDEN;
}
ap_update_mtime(r, r->finfo.mtime);
ap_set_last_modified(r);
ap_set_etag(r);
apr_table_setn(r->headers_out, "Accept-Ranges", "bytes");
if (((errstatus = ap_meets_conditions(r)) != OK)
|| (errstatus = ap_set_content_length(r, r->finfo.size))) {
apr_close(fd);
return errstatus;
}
#ifdef USE_MMAP_FILES
if ((r->finfo.size >= MMAP_THRESHOLD)
&& (r->finfo.size < MMAP_LIMIT)
&& (!r->header_only || bld_content_md5)) {
/* we need to protect ourselves in case we die while we've got the
* file mmapped */
apr_status_t status;
if ((status = apr_mmap_create(&mm, fd, 0, r->finfo.size, r->pool)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_CRIT, status, r,
"default_handler: mmap failed: %s", r->filename);
mm = NULL;
}
}
else {
mm = NULL;
}
if (mm == NULL) {
#endif
if (bld_content_md5) {
#ifdef APACHE_XLATE
apr_table_setn(r->headers_out, "Content-MD5",
ap_md5digest(r->pool, fd, NULL));
#else
apr_table_setn(r->headers_out, "Content-MD5",
ap_md5digest(r->pool, fd));
#endif /* APACHE_XLATE */
}
rangestatus = ap_set_byterange(r);
ap_send_http_header(r);
if (!r->header_only) {
apr_size_t length = r->finfo.size;
apr_off_t offset = 0;
apr_size_t nbytes = 0;
if (!rangestatus) {
ap_send_fd(fd, r, offset, length, &nbytes);
}
else {
while (ap_each_byterange(r, &offset, &length)) {
if ((status = ap_send_fd(fd, r, offset, length, &nbytes)) != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
"error byteserving file: %s", r->filename);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
}
}
#ifdef USE_MMAP_FILES
}
else {
unsigned char *addr;
apr_mmap_offset((void**)&addr, mm ,0);
if (bld_content_md5) {
apr_md5_ctx_t context;
apr_MD5Init(&context);
apr_MD5Update(&context, addr, (unsigned int)r->finfo.size);
apr_table_setn(r->headers_out, "Content-MD5",
ap_md5contextTo64(r->pool, &context));
}
rangestatus = ap_set_byterange(r);
ap_send_http_header(r);
if (!r->header_only) {
if (!rangestatus) {
ap_send_mmap(mm, r, 0, r->finfo.size);
}
else {
apr_off_t offset;
apr_size_t length;
while (ap_each_byterange(r, &offset, &length)) {
ap_send_mmap(mm, r, offset, length);
}
}
}
}
#endif
apr_close(fd);
return OK;
}
/* Buffer filter
* This is a relatively simple filter to coalesce many small buckets into
* one large bucket. This implementation of buffer_filter will only coalesce
* a single contiguous string of coalesable buckets. It will not coalesce
* multiple non-contiguous buckets.
*
* For example, if a brigade contains 10 small buckets followed by a
* large bucket (or a pipe or file bucket) followed by more small buckets,
* only the first 10 buckets will be coalesced.
*/
typedef struct BUFFER_FILTER_CTX {
char *buf; /* Start of buffer */
char *cur; /* Pointer to next location to write */
apr_ssize_t cnt; /* Number of bytes put in buf */
apr_ssize_t avail; /* Number of bytes available in the buf */
} buffer_filter_ctx_t;
#define FILTER_BUFF_SIZE 8192
#define MIN_BUCKET_SIZE 200
static apr_status_t buffer_filter(ap_filter_t *f, ap_bucket_brigade *b)
{
apr_status_t rv;
apr_pool_t *p = f->r->pool;
ap_bucket *e, *insert_before = NULL, *destroy_me = NULL;
buffer_filter_ctx_t *ctx = f->ctx;
int pass_the_brigade = 0, insert_first = 0;
if (ctx == NULL) {
f->ctx = ctx = apr_pcalloc(p, sizeof(buffer_filter_ctx_t));
ctx->avail = FILTER_BUFF_SIZE;
}
if (ctx->cnt) {
insert_first = 1;
}
/* Iterate across the buckets, coalescing the small buckets into a
* single buffer
*/
AP_BRIGADE_FOREACH(e, b) {
if (destroy_me) {
ap_bucket_destroy(destroy_me);
destroy_me = NULL;
}
if (AP_BUCKET_IS_EOS(e) || AP_BUCKET_IS_FILE(e) ||
AP_BUCKET_IS_PIPE(e)) {
pass_the_brigade = 1;
}
else {
const char *str;
apr_ssize_t n;
rv = ap_bucket_read(e, &str, &n, 0);
if (rv != APR_SUCCESS) {
/* XXX: log error */
return rv;
}
if ((n < MIN_BUCKET_SIZE) && (n < ctx->avail)) {
/* Coalesce this bucket into the buffer */
if (ctx->buf == NULL) {
ctx->buf = apr_palloc(p, FILTER_BUFF_SIZE);
ctx->cur = ctx->buf;
ctx->cnt = 0;
}
memcpy(ctx->cur, str, n);
ctx->cnt += n;
ctx->cur += n;
ctx->avail -= n;
/* If this is the first bucket to be coalesced, don't remove it
* from the brigade. Save it as a marker for where to insert
* ctx->buf into the brigade when we're done.
*/
if (insert_before || insert_first){
AP_BUCKET_REMOVE(e);
destroy_me = e;
}
else {
insert_before = e;
}
}
else if (insert_before || insert_first) {
/* This bucket was not able to be coalesced because it either
* exceeds MIN_BUCKET_SIZE or its contents will not fit into
* buf. We're done...
*/
pass_the_brigade = 1;
break;
}
else {
/* If there is even a single bucket that cannot be coalesced,
* then we must pass the brigade down to the next filter.
*/
pass_the_brigade = 1;
}
}
}
if (destroy_me) {
ap_bucket_destroy(destroy_me);
destroy_me = NULL;
}
if (pass_the_brigade) {
/* Insert ctx->buf into the correct spotin the brigade */
if (insert_first) {
e = ap_bucket_create_transient(ctx->buf, ctx->cnt);
AP_BRIGADE_INSERT_HEAD(b, e);
}
else if (insert_before) {
e = ap_bucket_create_transient(ctx->buf, ctx->cnt);
AP_BUCKET_INSERT_BEFORE(e, insert_before);
AP_BUCKET_REMOVE(insert_before);
ap_bucket_destroy(insert_before);
insert_before = NULL;
}
rv = ap_pass_brigade(f->next, b);
if (rv != APR_SUCCESS) {
/* XXX: Log the error */
return rv;
}
/* Get ctx->buf ready for the next brigade */
if (ctx) {
ctx->cur = ctx->buf;
ctx->cnt = 0;
ctx->avail = FILTER_BUFF_SIZE;
}
}
else {
if (insert_before) {
AP_BUCKET_REMOVE(insert_before);
ap_bucket_destroy(insert_before);
}
/* The brigade should be empty now because all the buckets
* were coalesced into the buffer_filter buf
*/
}
return APR_SUCCESS;
}
/*
* HTTP/1.1 chunked transfer encoding filter.
*/
static apr_status_t chunk_filter(ap_filter_t *f, ap_bucket_brigade *b)
{
ap_bucket_brigade *more = NULL;
ap_bucket *e;
apr_status_t rv;
for (more = NULL; b; b = more, more = NULL) {
apr_off_t bytes = 0;
ap_bucket *eos = NULL;
char chunk_hdr[20]; /* enough space for the snprintf below */
AP_BRIGADE_FOREACH(e, b) {
if (AP_BUCKET_IS_EOS(e)) {
/* there shouldn't be anything after the eos */
eos = e;
break;
}
else if (e->length == -1) {
/* unknown amount of data (e.g. a pipe) */
const char *data;
apr_ssize_t len;
rv = ap_bucket_read(e, &data, &len, 1);
if (rv != APR_SUCCESS) {
return rv;
}
if (len > 0) {
/*
* There may be a new next bucket representing the
* rest of the data stream on which a read() may
* block so we pass down what we have so far.
*/
bytes += len;
more = ap_brigade_split(b, AP_BUCKET_NEXT(e));
break;
}
else {
/* If there was nothing in this bucket then we can
* safely move on to the next one without pausing
* to pass down what we have counted up so far.
*/
continue;
}
}
else {
bytes += e->length;
}
}
/*
* XXX: if there aren't very many bytes at this point it may
* be a good idea to set them aside and return for more,
* unless we haven't finished counting this brigade yet.
*/
/* if there are content bytes, then wrap them in a chunk */
if (bytes > 0) {
apr_size_t hdr_len;
/*
* Insert the chunk header, specifying the number of bytes in
* the chunk.
*/
/* XXX might be nice to have APR_OFF_T_FMT_HEX */
hdr_len = apr_snprintf(chunk_hdr, sizeof(chunk_hdr),
"%qx" CRLF, (apr_uint64_t)bytes);
e = ap_bucket_create_transient(chunk_hdr, hdr_len);
AP_BRIGADE_INSERT_HEAD(b, e);
/*
* Insert the end-of-chunk CRLF before the EOS bucket, or
* appended to the brigade
*/
e = ap_bucket_create_immortal(CRLF, 2);
if (eos != NULL) {
AP_BUCKET_INSERT_BEFORE(eos, e);
}
else {
AP_BRIGADE_INSERT_TAIL(b, e);
}
}
/* RFC 2616, Section 3.6.1
*
* If there is an EOS bucket, then prefix it with:
* 1) the last-chunk marker ("0" CRLF)
* 2) the trailer
* 3) the end-of-chunked body CRLF
*
* If there is no EOS bucket, then do nothing.
*
* XXX: it would be nice to combine this with the end-of-chunk
* marker above, but this is a bit more straight-forward for
* now.
*/
if (eos != NULL) {
/* XXX: (2) trailers ... does not yet exist */
e = ap_bucket_create_immortal("0" CRLF /* <trailers> */ CRLF, 5);
AP_BUCKET_INSERT_BEFORE(eos, e);
}
/* pass the brigade to the next filter. */
rv = ap_pass_brigade(f->next, b);
if (rv != APR_SUCCESS || eos != NULL) {
return rv;
}
}
return APR_SUCCESS;
}
/* This function only understands a length of AP_GET_ANY_AMOUNT. It will
* ignore length values and always return the entire brigade. This is
* pretty safe to do, because we know there always needs to be an intervening
* filter just above this that will only make requests for AP_GET_ANY_AMOUNT
*/
static int core_input_filter(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t length)
{
apr_socket_t *csock = NULL;
ap_bucket *e;
if (!f->ctx) { /* If we haven't passed up the socket yet... */
f->ctx = (void *)1;
ap_bpop_socket(&csock, f->c->client);
e = ap_bucket_create_socket(csock);
AP_BRIGADE_INSERT_TAIL(b, e);
return APR_SUCCESS;
}
else {
/* Either some code lost track of the socket
* bucket or we already found out that the
* client closed.
*/
return APR_EOF;
}
}
/* Default filter. This filter should almost always be used. Its only job
* is to send the headers if they haven't already been sent, and then send
* the actual data.
*/
typedef struct CORE_OUTPUT_FILTER_CTX {
ap_bucket_brigade *b;
} core_output_filter_ctx_t;
#define MAX_IOVEC_TO_WRITE 16
static int core_output_filter(ap_filter_t *f, ap_bucket_brigade *b)
{
apr_status_t rv;
ap_bucket_brigade *more = NULL;
apr_ssize_t bytes_sent = 0, nbytes;
ap_bucket *e;
conn_rec *c = f->c;
core_output_filter_ctx_t *ctx = f->ctx;
apr_ssize_t nvec = 0;
apr_ssize_t nvec_trailers= 0;
struct iovec vec[MAX_IOVEC_TO_WRITE];
struct iovec vec_trailers[MAX_IOVEC_TO_WRITE];
apr_file_t *fd = NULL;
apr_ssize_t flen = 0;
apr_off_t foffset = 0;
if (ctx == NULL) {
f->ctx = ctx = apr_pcalloc(c->pool, sizeof(core_output_filter_ctx_t));
}
/* If we have a saved brigade, concatenate the new brigade to it */
if (ctx->b) {
AP_BRIGADE_CONCAT(ctx->b, b);
b = ctx->b;
ctx->b = NULL;
}
/* Hijack any bytes in BUFF and prepend it to the brigade. */
if (c->client->outcnt) {
e = ap_bucket_create_heap(c->client->outbase,
c->client->outcnt, 1, NULL);
c->client->outcnt = 0;
AP_BRIGADE_INSERT_HEAD(b, e);
}
/* Iterate over the brigade collecting iovecs */
while (b) {
nbytes = 0; /* in case more points to another brigade */
more = NULL;
AP_BRIGADE_FOREACH(e, b) {
if (AP_BUCKET_IS_EOS(e)) {
break;
}
else if (AP_BUCKET_IS_FILE(e)) {
ap_bucket_file *a = e->data;
/* Assume there is at most one AP_BUCKET_FILE in the brigade */
fd = a->fd;
flen = e->length;
foffset = a->offset;
}
else {
const char *str;
apr_ssize_t n;
rv = ap_bucket_read(e, &str, &n, 0);
if (n) {
nbytes += n;
if (!fd) {
vec[nvec].iov_base = (char*) str;
vec[nvec].iov_len = n;
nvec++;
}
else {
/* The bucket is a trailer to a file bucket */
vec_trailers[nvec_trailers].iov_base = (char*) str;
vec_trailers[nvec_trailers].iov_len = n;
nvec_trailers++;
}
}
}
if ((nvec == MAX_IOVEC_TO_WRITE) || (nvec_trailers == MAX_IOVEC_TO_WRITE)) {
/* Split the brigade and break */
if (AP_BUCKET_NEXT(e) != AP_BRIGADE_SENTINEL(b)) {
more = ap_brigade_split(b, AP_BUCKET_NEXT(e));
}
break;
}
}
/* Completed iterating over the brigades, now determine if we want to
* buffer the brigade or send the brigade out on the network
*/
if (!fd && (!more) && (nbytes < MIN_SIZE_TO_WRITE) && !AP_BUCKET_IS_EOS(e)) {
ap_save_brigade(f, &ctx->b, &b);
return APR_SUCCESS;
}
if (fd) {
apr_hdtr_t hdtr;
#if APR_HAS_SENDFILE
apr_int32_t flags = 0;
#endif
memset(&hdtr, '\0', sizeof(hdtr));
if (nvec) {
hdtr.numheaders = nvec;
hdtr.headers = vec;
}
if (nvec_trailers) {
hdtr.numtrailers = nvec_trailers;
hdtr.trailers = vec_trailers;
}
#if APR_HAS_SENDFILE
if (!c->keepalive) {
/* Prepare the socket to be reused */
flags |= APR_SENDFILE_DISCONNECT_SOCKET;
}
nbytes = flen;
rv = apr_sendfile(c->client->bsock,
fd, /* The file to send */
&hdtr, /* Header and trailer iovecs */
&foffset, /* Offset in file to begin sending from */
&nbytes,
flags);
bytes_sent = nbytes;
/* If apr_sendfile() returns APR_ENOTIMPL, call send_the_file() to
* loop on apr_read/apr_send to send the file. Our Windows binary
* distributions (which work on Windows 9x/NT) are compiled on
* Windows NT. TransmitFile is not available on Windows 95/98 and
* we discover this at runtime when apr_sendfile() returns
* APR_ENOTIMPL. Having apr_sendfile() return APR_ENOTIMPL seems
* the cleanest way to handle this case.
*/
if (rv == APR_ENOTIMPL) {
#endif
rv = send_the_file(c, fd, &hdtr, foffset, flen, &bytes_sent);
#if APR_HAS_SENDFILE
}
#endif
}
else {
rv = writev_it_all(c->client->bsock,
vec, nvec,
nbytes, &bytes_sent);
}
ap_brigade_destroy(b);
if (rv != APR_SUCCESS) {
/* XXX: log the error */
if (more)
ap_brigade_destroy(more);
return rv;
}
nvec = 0;
nvec_trailers = 0;
b = more;
} /* end while () */
return APR_SUCCESS;
}
static const handler_rec core_handlers[] = {
{ "*/*", default_handler },
{ "default-handler", default_handler },
{ NULL, NULL }
};
static void core_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
{
ap_init_bucket_types(pconf);
}
static void core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{
ap_set_version(pconf);
}
static void core_open_logs(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{
ap_open_logs(s, pconf);
}
static const char *core_method(const request_rec *r)
{ return "http"; }
static unsigned short core_port(const request_rec *r)
{ return DEFAULT_HTTP_PORT; }
static void core_insert_filter(request_rec *r)
{
int i;
core_dir_config *conf = (core_dir_config *)
ap_get_module_config(r->per_dir_config,
&core_module);
char **items = (char **)conf->filters->elts;
for (i = 0; i < conf->filters->nelts; i++) {
char *foobar = items[i];
ap_add_output_filter(foobar, NULL, r, r->connection);
}
items = (char **)conf->input_filters->elts;
for (i = 0; i < conf->input_filters->nelts; i++) {
char *foobar = items[i];
ap_add_input_filter(foobar, NULL, r, r->connection);
}
}
static void register_hooks(void)
{
ap_hook_pre_config(core_pre_config, NULL, NULL, AP_HOOK_REALLY_FIRST);
ap_hook_post_config(core_post_config,NULL,NULL,AP_HOOK_REALLY_FIRST);
ap_hook_translate_name(ap_core_translate,NULL,NULL,AP_HOOK_REALLY_LAST);
ap_hook_pre_connection(ap_pre_http_connection,NULL,NULL,
AP_HOOK_REALLY_LAST);
ap_hook_process_connection(ap_process_http_connection,NULL,NULL,
AP_HOOK_REALLY_LAST);
ap_hook_http_method(core_method,NULL,NULL,AP_HOOK_REALLY_LAST);
ap_hook_default_port(core_port,NULL,NULL,AP_HOOK_REALLY_LAST);
ap_hook_open_logs(core_open_logs,NULL,NULL,AP_HOOK_MIDDLE);
/* FIXME: I suspect we can eliminate the need for these - Ben */
ap_hook_type_checker(do_nothing,NULL,NULL,AP_HOOK_REALLY_LAST);
ap_hook_access_checker(do_nothing,NULL,NULL,AP_HOOK_REALLY_LAST);
/* register the core's insert_filter hook and register core-provided
* filters
*/
ap_hook_insert_filter(core_insert_filter, NULL, NULL, AP_HOOK_MIDDLE);
ap_register_input_filter("HTTP_IN", http_filter, AP_FTYPE_CONNECTION);
ap_register_input_filter("CORE_IN", core_input_filter, AP_FTYPE_CONNECTION);
ap_register_output_filter("CORE", core_output_filter, AP_FTYPE_CONNECTION + 1);
ap_register_output_filter("CHUNK", chunk_filter, AP_FTYPE_CONNECTION);
ap_register_output_filter("BUFFER", buffer_filter, AP_FTYPE_CONNECTION);
}
API_VAR_EXPORT module core_module = {
STANDARD20_MODULE_STUFF,
create_core_dir_config, /* create per-directory config structure */
merge_core_dir_configs, /* merge per-directory config structures */
create_core_server_config, /* create per-server config structure */
merge_core_server_configs, /* merge per-server config structures */
core_cmds, /* command apr_table_t */
core_handlers, /* handlers */
register_hooks /* register hooks */
};