http_core.c revision 10a4cdd68ef1ca0e54af296fe1d08ac00150c90b
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
*
* Portions of this software are based upon public domain software
* originally written at the National Center for Supercomputing Applications,
* University of Illinois, Urbana-Champaign.
*/
#define CORE_PRIVATE
#include "ap_config.h"
#include "apr_strings.h"
#include "apr_lib.h"
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_protocol.h" /* For index_of_response(). Grump. */
#include "http_request.h"
#include "http_vhost.h"
#include "http_main.h" /* For the default_handler below... */
#include "http_log.h"
#include "rfc1413.h"
#include "util_md5.h"
#include "apr_fnmatch.h"
#include "http_connection.h"
#include "util_ebcdic.h"
#include "mpm.h"
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#endif
#ifdef HAVE_ARPA_INET_H
#endif
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
/* Allow Apache to use ap_mmap */
#ifdef USE_MMAP_FILES
#include "apr_mmap.h"
/* mmap support for static files based on ideas from John Heidemann's
* patch against 1.0.5. See
*/
/* Files have to be at least this big before they're mmap()d. This is to deal
* with systems where the expense of doing an mmap() and an munmap() outweighs
* the benefit for small files. It shouldn't be set lower than 1.
*/
#ifndef MMAP_THRESHOLD
#ifdef SUNOS4
#else
#define MMAP_THRESHOLD 1
#endif /* SUNOS4 */
#endif /* MMAP_THRESHOLD */
#ifndef MMAP_LIMIT
#endif
#endif /* USE_MMAP_FILES */
/* LimitXMLRequestBody handling */
#define AP_LIMIT_UNSET ((long) -1)
/* Server core module... This module provides support for really basic
* server operations, including options and commands which control the
* operation of other modules. Consider this the bureaucracy module.
*
* The core module also defines handlers, etc., do handle just enough
* to allow a server with the core module ONLY to actually serve documents
* (though it slaps DefaultType on all of 'em); this was useful in testing,
* but may not be worth preserving.
*
* This file could almost be mod_core.c, except for the stuff which affects
* the http_conf_globals.
*/
{
}
}
else {
}
#ifdef RLIMIT_CPU
#endif
#endif
#ifdef RLIMIT_NPROC
#endif
conf->limit_req_body = 0;
#ifdef WIN32
#endif
return (void *)conf;
}
{
int i;
if (base->response_code_strings) {
* RESPONSE_CODES);
}
/* there was no explicit setting of new->opts, so we merge
* preserve the invariant (opts_add & opts_remove) == 0
*/
| new->opts_remove;
}
}
else {
/* otherwise we just copy, because an explicit opts setting
* overrides all earlier +/- modifiers
*/
}
}
if (new->ap_default_type) {
}
if (new->ap_auth_type) {
}
if (new->ap_auth_name) {
}
if (new->ap_requires) {
}
if (new->response_code_strings) {
}
else {
for (i = 0; i < RESPONSE_CODES; ++i) {
= new->response_code_strings[i];
}
}
}
}
}
}
}
}
#ifdef RLIMIT_CPU
}
#endif
}
#endif
#ifdef RLIMIT_NPROC
if (new->limit_nproc) {
}
#endif
if (new->limit_req_body) {
}
else
}
#ifdef WIN32
}
#endif
}
}
if (new->add_default_charset_name) {
}
return (void*)conf;
}
{
int is_virtual = s->is_virtual;
#ifdef GPROF
#endif
return (void *)conf;
}
{
if (!conf->access_name) {
}
if (!conf->ap_document_root) {
}
return conf;
}
/* Add per-directory configuration entry (for <directory> section);
* these are part of the core server config.
*/
{
&core_module);
*new_space = dir_config;
}
{
&core_module);
*new_space = url_config;
}
{
*new_space = url_config;
}
/* core_reorder_directories reorders the directory sections such that the
* 1-component sections come first, then the 2-component, and so on, finally
* followed by the "special" sections. A section is "special" if it's a regex,
* or if it doesn't start with / -- consider proxy: matching. All movements
* are in-order to preserve the ordering of the sections from the config files.
* See directory_walk().
*/
#ifdef HAVE_DRIVE_LETTERS
#define IS_SPECIAL(entry_core) \
((entry_core)->r != NULL \
#else
#define IS_SPECIAL(entry_core) \
#endif
/* We need to do a stable sort, qsort isn't stable. So to make it stable
* we'll be maintaining the original index into the list, and using it
* as the minor key during sorting. The major key is the number of
* components (where a "special" section has infinite components).
*/
struct reorder_sort_rec {
void *elt;
int orig_index;
};
{
const struct reorder_sort_rec *a = va;
const struct reorder_sort_rec *b = vb;
if (IS_SPECIAL(core_a)) {
if (!IS_SPECIAL(core_b)) {
return 1;
}
}
else if (IS_SPECIAL(core_b)) {
return -1;
}
else {
/* we know they're both not special */
return -1;
}
return 1;
}
}
/* Either they're both special, or they're both not special and have the
* same number of components. In any event, we now have to compare
* the minor key. */
return a->orig_index - b->orig_index;
}
{
struct reorder_sort_rec *sortbin;
int nelts;
void **elts;
int i;
/* we have to allocate tmp space to do a stable sort */
apr_create_pool(&tmp, p);
for (i = 0; i < nelts; ++i) {
sortbin[i].orig_index = i;
}
/* and now copy back to the original array */
for (i = 0; i < nelts; ++i) {
}
}
/*****************************************************************
*
* There are some elements of the core config structures in which
* other modules have a legitimate interest (this is ugly, but necessary
* to preserve NCSA back-compatibility). So, we have a bunch of accessors
* here...
*/
{
}
{
&core_module);
}
{
&core_module);
return conf->ap_auth_type;
}
{
&core_module);
return conf->ap_auth_name;
}
{
&core_module);
return conf->ap_default_type
}
{
&core_module);
return conf->ap_document_root;
}
{
&core_module);
return conf->ap_requires;
}
{
&core_module);
}
/* Should probably just get rid of this... the only code that cares is
* part of the core anyway (and in fact, it isn't publicised to other
* modules).
*/
{
&core_module);
return NULL;
}
}
/* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
{
if (conn->double_reverse) {
/* already done */
return;
}
/* single reverse failed, so don't bother */
return;
}
if (hptr) {
char **haddr;
return;
}
}
}
}
int type)
{
int hostname_lookups;
/* If we haven't checked the host name, and we want to */
if (dir_config) {
if (hostname_lookups == HOSTNAME_LOOKUP_UNSET) {
}
}
else {
/* the default */
}
if (type != REMOTE_NOLOOKUP
&& (type == REMOTE_DOUBLE_REV
|| hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
}
}
}
/* if failed, set it to the NULL string to indicate error */
}
}
if (type == REMOTE_DOUBLE_REV) {
return NULL;
}
}
/*
* Return the desired information; either the remote DNS name, if found,
* or either NULL (if the hostname was requested) or the IP address
* (if any identifier was requested).
*/
return conn->remote_host;
}
else {
return NULL;
}
else {
}
}
}
{
return r->connection->remote_logname;
}
/* If we haven't checked the identity, and we want to */
&core_module);
}
else {
return NULL;
}
}
/* There are two options regarding what the "name" of a server is. The
* "canonical" name as defined by ServerName and Port, or the "client's
* name" as supplied by a possible Host: header or full URI. We never
* trust the port passed in the client's headers, we always use the
* port of the actual socket.
*
* The DNS option to UseCanonicalName causes this routine to do a
* reverse lookup on the local IP address of the connectiona and use
* that for the ServerName. This makes its value more reliable while
* at the same time allowing Demon's magic virtual hosting to work.
* The assumption is that DNS lookups are sufficiently quick...
* -- fanf 1998-10-03
*/
{
core_dir_config *d;
&core_module);
if (d->use_canonical_name == USE_CANONICAL_NAME_OFF) {
}
if (d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
AF_INET);
}
else {
r->server->server_hostname);
}
}
return conn->local_host;
}
/* default */
return r->server->server_hostname;
}
{
unsigned port;
core_dir_config *d =
if (d->use_canonical_name == USE_CANONICAL_NAME_OFF
|| d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
: port;
}
/* default */
return port;
}
request_rec *r)
{
unsigned port = ap_get_server_port(r);
const char *host = ap_get_server_name(r);
if (ap_is_default_port(port, r)) {
}
}
{
core_dir_config *d =
return d->limit_req_body;
}
#ifdef WIN32
char* relativepath, char **value)
{
if (result != ERROR_SUCCESS)
return result;
/* Read to NULL buffer to determine value size */
if (result == ERROR_SUCCESS) {
}
else {
/* Read value based on size query above */
}
}
/* TODO: This might look fine, but we need to provide some warning
* somewhere that some environment variables may -not- be translated,
* seeing as we may have chopped the environment table down somewhat.
*/
{
if (size) {
}
}
return result;
}
{
char execcgi_path[] = "SHELL\\EXECCGI\\COMMAND";
char execopen_path[] = "SHELL\\OPEN\\COMMAND";
int size;
int result;
char *buffer;
char *s;
if (!ext)
return NULL;
/*
* Future optimization:
* When the registry is successfully searched, store the strings for
* interpreter and arguments in an ext hash to speed up subsequent look-ups
*/
/* Open the key associated with the script filetype extension */
&hkeyType);
if (result != ERROR_SUCCESS)
return NULL;
/* Retrieve the name of the script filetype extension */
/* Open the key associated with the script filetype extension */
if (result == ERROR_SUCCESS)
}
/* Open the key for the script command path by:
*
*
* and if the strict arg is false, then continue trying:
*
*/
if (cmdOfName) {
execcgi_path, &buffer);
}
execcgi_path, &buffer);
}
execopen_path, &buffer);
}
execopen_path, &buffer);
}
if (cmdOfName)
if (result != ERROR_SUCCESS)
return NULL;
/*
* The canonical way shell command entries are entered in the Win32
* registry is as follows:
* shell [options] "%1" [args]
* where
* shell - full path name to interpreter or shell to run.
* E.g., c:\usr\local\ntreskit\perl\bin\perl.exe
* options - optional switches
* E.g., \C
* "%1" - Place holder for file to run the shell against.
* Typically quoted.
* options - additional arguments
* E.g., /silent
*
* If we find a %1 or a quoted %1, lop off the remainder to arguments.
*/
{
*s = '\0';
*arguments = s + 4;
}
{
*s = '\0';
}
else
++*arguments;
}
return buffer;
}
char** interpreter,
char** arguments)
{
char buffer[1024];
core_dir_config *d;
int i;
&core_module);
/* Find the file extension */
if (!exename) {
}
if (!exename) {
}
else {
exename++;
}
{
if (comspec) {
return eFileTypeSCRIPT;
}
"Failed to start a '%s' file as a script." APR_EOL_STR
"\tCOMSPEC variable is missing from the environment.", ext);
return eFileTypeUNKNOWN;
}
/* If the file has an extension and it is not .com and not .exe and
* we've been instructed to search the registry, then do it!
*/
/* Check the registry */
int strict = (d->script_interpreter_source
if (*interpreter)
return eFileTypeSCRIPT;
else if (d->script_interpreter_source == INTERPRETER_SOURCE_REGISTRY_STRICT) {
"ScriptInterpreterSource config directive set to \"registry-strict\"." APR_EOL_STR
"\tInterpreter not found for files of type '%s'.", ext);
return eFileTypeUNKNOWN;
}
else
{
"ScriptInterpreterSource config directive set to \"registry\"." APR_EOL_STR
"\tInterpreter not found for files of type '%s', "
"trying \"script\" method...", ext);
}
}
/* Need to peek into the file figure out what it really is... */
if (hFile == INVALID_HANDLE_VALUE) {
return eFileTypeUNKNOWN;
}
&nBytesRead, NULL);
if (!bResult || (nBytesRead == 0)) {
"ReadFile(%s) failed", r->filename);
return eFileTypeUNKNOWN;
}
/* Script or executable, that is the question... */
/* Assuming file is a script since it starts with a shebang */
for (i = 2; i < sizeof(buffer); i++) {
if ((buffer[i] == '\r')
|| (buffer[i] == '\n')) {
break;
}
}
buffer[i] = '\0';
;
}
else {
/* Not a script, is it an executable? */
else
}
else
}
return fileType;
}
#endif
/*****************************************************************
*
* Commands... this module handles almost all of the NCSA httpd.conf
* commands, but most of the old srm.conf is in the the modules.
*/
/* returns a parent if it matches the given directive */
const char *what)
{
/* ### it would be nice to have atom-ized directives */
return dirp;
}
return NULL;
}
unsigned forbidden)
{
? ">" : "";
const ap_directive_t *found;
" cannot occur within <VirtualHost> section", NULL);
}
" cannot occur within <Limit> section", NULL);
}
"section", NULL);
}
if (((forbidden & NOT_IN_DIRECTORY)
|| ((forbidden & NOT_IN_LOCATION)
|| ((forbidden & NOT_IN_FILES)
"> section", NULL);
}
return NULL;
}
const char *arg)
{
return err;
}
return NULL;
}
#ifdef GPROF
{
return err;
}
return NULL;
}
#endif /*GPROF*/
{
core_dir_config *d=d_;
return err;
}
}
}
else {
d->add_default_charset_name = arg;
}
return NULL;
}
const char *arg)
{
return err;
}
"Warning: DocumentRoot [%s] does not exist",
arg);
}
else {
return "DocumentRoot must be a directory";
}
}
return NULL;
}
{
int idx;
apr_pcalloc(r->pool,
sizeof(*conf->response_code_strings) *
}
}
{
return err;
}
/* 1st parameter should be a 3 digit number, which we recognize;
* convert it into an array index
*/
if (error_number == HTTP_INTERNAL_SERVER_ERROR) {
}
}
/* Heuristic to determine second argument. */
else if (msg[0] == '/')
what = LOCAL_PATH;
what = REMOTE_PATH;
else
/* The entry should be ignored if it is a full URL for a 401 error */
"cannot use a full URL in a 401 ErrorDocument "
"directive --- ignoring!");
}
else { /* Store it... */
}
/* hack. Prefix a " if it is a msg; as that is what
* http_protocol.c relies on to distinguish between
* a msg and a (local) path.
*/
}
return NULL;
}
{
core_dir_config *d=d_;
char *w;
return err;
}
while (l[0]) {
if (!strcasecmp(w, "Limit")) {
}
else if (!strcasecmp(w, "Options")) {
d->override |= OR_OPTIONS;
}
else if (!strcasecmp(w, "FileInfo")) {
d->override |= OR_FILEINFO;
}
else if (!strcasecmp(w, "AuthConfig")) {
d->override |= OR_AUTHCFG;
}
else if (!strcasecmp(w, "Indexes")) {
d->override |= OR_INDEXES;
}
else if (!strcasecmp(w, "None")) {
}
else if (!strcasecmp(w, "All")) {
}
else {
}
}
return NULL;
}
{
core_dir_config *d=d_;
int first = 1;
char action;
while (l[0]) {
action = '\0';
if (*w == '+' || *w == '-') {
action = *(w++);
}
else if (first) {
first = 0;
}
if (!strcasecmp(w, "Indexes")) {
opt = OPT_INDEXES;
}
else if (!strcasecmp(w, "Includes")) {
opt = OPT_INCLUDES;
}
else if (!strcasecmp(w, "IncludesNOEXEC")) {
}
else if (!strcasecmp(w, "FollowSymLinks")) {
opt = OPT_SYM_LINKS;
}
else if (!strcasecmp(w, "SymLinksIfOwnerMatch")) {
opt = OPT_SYM_OWNER;
}
else if (!strcasecmp(w, "execCGI")) {
opt = OPT_EXECCGI;
}
else if (!strcasecmp(w, "MultiViews")) {
}
}
else if (!strcasecmp(w, "None")) {
}
else if (!strcasecmp(w, "All")) {
}
else {
}
/* we ensure the invariant (d->opts_add & d->opts_remove) == 0 */
if (action == '-') {
d->opts_remove |= opt;
}
else if (action == '+') {
d->opts_remove &= ~opt;
}
else {
}
}
return NULL;
}
{
core_dir_config *c=c_;
c->satisfy = SATISFY_ALL;
}
c->satisfy = SATISFY_ANY;
}
else {
return "Satisfy either 'any' or 'all'.";
}
return NULL;
}
{
require_line *r;
core_dir_config *c=c_;
if (!c->ap_requires) {
}
return NULL;
}
const char *arg)
{
int limited = 0;
const char *errmsg;
return err;
}
while (limited_methods[0]) {
return "TRACE cannot be controlled by <Limit>";
}
}
else {
}
}
/* Killing two features with one function,
* if (tog == NULL) <Limit>, else <LimitExcept>
*/
return errmsg;
}
/* We use this in <DirectoryMatch> and <FilesMatch>, to ensure that
* people don't get bitten by wrong-cased regex matches
*/
#ifdef WIN32
#else
#define USE_ICASE 0
#endif
/*
* Report a missing-'>' syntax error.
*/
{
"> directive missing closing '>'", NULL);
}
{
const char *errmsg;
return err;
}
return unclosed_directive(cmd);
}
}
}
else {
/* Ensure that the pathname is canonical */
}
/* initialize our config and fetch it */
&core_module);
return errmsg;
conf->r = r;
if (*arg != '\0') {
"> arguments not (yet) supported.", NULL);
}
return NULL;
}
{
const char *errmsg;
return err;
}
return unclosed_directive(cmd);
}
}
}
/* initialize our config and fetch it */
&core_module);
return errmsg;
conf->r = r;
if (*arg != '\0') {
"> arguments not (yet) supported.", NULL);
}
return NULL;
}
{
const char *errmsg;
return err;
}
return unclosed_directive(cmd);
}
/* Only if not an .htaccess file */
if (!old_path) {
}
}
}
else {
/* Ensure that the pathname is canonical */
}
/* initialize our config and fetch it */
&core_module);
return errmsg;
conf->r = r;
if (*arg != '\0') {
"> arguments not (yet) supported.", NULL);
}
return NULL;
}
{
return unclosed_directive(cmd);
}
if (not) {
arg++;
}
const char *retval;
return retval;
}
else {
}
}
{
char **defines;
int i;
for (i = 0; i < ap_server_config_defines->nelts; i++) {
return 1;
}
}
return 0;
}
{
const char *endp;
int defined;
int not = 0;
return unclosed_directive(cmd);
}
if (arg[0] == '!') {
not = 1;
arg++;
}
defined = ap_exists_config_define(arg);
const char *retval;
return retval;
}
else {
}
}
/* httpd.conf commands... beginning with the <VirtualHost> business */
const char *arg)
{
const char *errmsg;
return err;
}
return unclosed_directive(cmd);
}
/* FIXME: There's another feature waiting to happen here -- since you
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!";
}
if (errmsg) {
return errmsg;
}
main_server->next = s;
s->lookup_defaults);
return errmsg;
}
const char *arg)
{
return "ServerAlias only used in <VirtualHost>";
}
while (*arg) {
if (ap_is_matchexp(name)) {
}
else {
}
}
return NULL;
}
const char *arg)
{
return err;
}
if (!ap_add_named_module(arg)) {
"': not in list of loaded modules", NULL);
}
return NULL;
}
{
return err;
}
return NULL;
}
const char *arg)
{
/* This one's pretty generic... */
return err;
}
return NULL;
}
{
int port;
return err;
}
"\" is outside the appropriate range "
"(i.e., 1..65535).", NULL);
}
return NULL;
}
const char *arg)
{
core_dir_config *d=d_;
return err;
}
d->server_signature = srv_sig_on;
}
d->server_signature = srv_sig_off;
}
}
else {
return "ServerSignature: use one of: off | on | email";
}
return NULL;
}
const char *arg)
{
return err;
}
if (!ap_is_directory(arg)) {
return "ServerRoot must be a valid directory";
}
return NULL;
}
{
return err;
}
return NULL;
}
const char *arg)
{
return err;
}
return NULL;
}
const char *arg)
{
return err;
}
* so we accept anything but "Off" or "0" as "On"
*/
}
else {
}
return NULL;
}
const char *arg)
{
return err;
}
return NULL;
}
{
core_dir_config *d=d_;
return err;
}
d->do_rfc1413 = arg != 0;
return NULL;
}
const char *arg)
{
core_dir_config *d=d_;
return err;
}
}
}
}
else {
return "parameter must be 'on', 'off', or 'double'";
}
return NULL;
}
const char *arg)
{
return err;
}
return NULL;
}
{
core_dir_config *d=d_;
return err;
}
d->content_md5 = arg != 0;
return NULL;
}
const char *arg)
{
core_dir_config *d=d_;
return err;
}
}
}
}
else {
return "parameter must be 'on', 'off', or 'dns'";
}
return NULL;
}
const char *name)
{
return NULL;
}
{
char *str;
return err;
}
}
}
}
}
}
}
}
}
else {
return "LogLevel requires level keyword: one of "
}
}
else {
return "LogLevel requires level keyword";
}
return NULL;
}
{
char sport[20];
&core_module);
return "";
}
" Server at <A HREF=\"mailto:",
"</ADDRESS>\n", NULL);
}
"</ADDRESS>\n", NULL);
}
/*
* Load an authorisation realm into our location configuration, applying the
* usual rules that apply to realms.
*/
const char *word1)
{
return NULL;
}
#ifdef _OSD_POSIX /* BS2000 Logon Passwd file */
{
return err;
}
}
#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 */
};
{
version_locked = 0;
return APR_SUCCESS;
}
API_EXPORT(const char *) ap_get_server_version(void)
{
}
{
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) {
}
else {
/*
* Tack the given component identifier to the end of
* the existing string.
*/
}
}
}
/*
* This routine adds the real server base identity to the version string,
* and then locks out changes until the next reconfig.
*/
{
if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
}
else if (ap_server_tokens == SrvTk_MIN) {
}
else {
}
/*
* Lock the server_version string if we're not displaying
* the full set of tokens
*/
if (ap_server_tokens != SrvTk_FULL) {
}
}
const char *arg)
{
return err;
}
}
}
}
else {
}
return NULL;
}
const char *arg)
{
int lim;
return err;
}
if (lim < 0) {
"\" must be a non-negative integer", NULL);
}
if (lim > DEFAULT_LIMIT_REQUEST_LINE) {
"must not exceed the precompiled maximum of %d",
}
return NULL;
}
const char *arg)
{
int lim;
return err;
}
if (lim < 0) {
"\" must be a non-negative integer (0 = no limit)",
NULL);
}
if (lim > DEFAULT_LIMIT_REQUEST_FIELDSIZE) {
"must not exceed the precompiled maximum of %d",
}
return NULL;
}
const char *arg)
{
int lim;
return err;
}
if (lim < 0) {
"\" must be a non-negative integer (0 = no limit)",
NULL);
}
return NULL;
}
const char *arg)
{
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.
*/
return NULL;
}
const char *arg)
{
return err;
}
if (conf->limit_xml_body < 0)
return "LimitXMLRequestBody requires a non-negative integer.";
return NULL;
}
{
return AP_DEFAULT_LIMIT_XML_BODY;
}
#ifdef WIN32
char *arg)
{
} else {
}
return NULL;
}
#endif
#if !defined (RLIMIT_CPU) || !(defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)) || !defined (RLIMIT_NPROC)
{
return NULL;
}
#endif
#ifdef RLIMIT_CPU
{
return NULL;
}
#endif
{
#if defined(RLIMIT_AS)
#elif defined(RLIMIT_DATA)
#elif defined(RLIMIT_VMEM)
#endif
return NULL;
}
#endif
#ifdef RLIMIT_NPROC
{
return NULL;
}
#endif
/* 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 */
"Container for directives affecting resources located in the specified "
"directories"),
"Container for directives affecting resources accessed through the "
"specified URL paths"),
"Container to map directives to a particular virtual host, takes one or "
"more host addresses"),
"Container for directives affecting files matching specified patterns"),
"Container for authentication directives when accessed using specified HTTP "
"methods"),
"Container for authentication directives to be applied when any HTTP "
"method other than those specified is used to access the resource"),
"Container for directives based on existance of specified modules"),
"Container for directives based on existance of command line defines"),
"Container for directives affecting resources located in the "
"specified directories"),
"Container for directives affecting resources accessed through the "
"specified URL paths"),
"Container for directives affecting files matching specified patterns"),
"An HTTP authorization type (e.g., \"Basic\")"),
"The authentication realm (e.g. \"Members Only\")"),
"Selects which authenticated users or groups may access a protected space"),
"access policy if both allow and require used ('all' or 'any')"),
#ifdef GPROF
"Directory to plop gmon.out files"),
#endif
"The name of the default charset to add to any Content-Type without one or 'Off' to disable"),
/* Old resource config file commands */
"Name(s) of per-directory config files (default: .htaccess)"),
"Root directory of the document tree"),
"Change responses for HTTP errors"),
"Controls what groups of directives can be configured by per-directory "
"config files"),
"Set a number of attributes for a given directory"),
OR_FILEINFO, "the default MIME type for untypable files"),
/* Old server config file commands */
"\"on\" to enable, \"off\" to disable reverse DNS lookups, or \"double\" to "
"enable double-reverse DNS lookups"),
"The email address of the server administrator"),
"The hostname of the server"),
"Common directory of server-related files (logs, confs, etc.)"),
"The filename of the error log"),
"A name or names alternately used to access the server"),
"The pathname the server can be reached at"),
"Timeout duration (sec)"),
"Keep-Alive timeout duration (sec)"),
"Maximum number of Keep-Alive requests per connection, or 0 for infinite"),
"Whether persistent connections should be On or Off"),
"Enable identd (RFC 1413) user lookups - SLOW"),
"whether or not to send a Content-MD5 header with each request"),
"How to work out the ServerName : Port when constructing URLs"),
/* TODO: RlimitFoo should all be part of mod_cgi, not in the core */
RSRC_CONF, "The name of a module"),
/* TODO: ListenBacklog in MPM */
"Name of the config file to be included"),
"Level of verbosity in error logging"),
"A numeric IP address:port, or the name of a host"),
#ifdef _OSD_POSIX
"Name of server User's bs2000 logon account name"),
#endif
#ifdef WIN32
"Where to find interpreter to run Win32 scripts (Registry or script shebang line)"),
#endif
"Determine tokens displayed in the Server: header - Min(imal), OS or Full"),
"Limit on maximum size of an HTTP request line"),
"Limit on maximum size of an HTTP request header field"),
"Limit (0 = unlimited) on max number of header fields in a request message"),
"Limit (in bytes) on maximum size of request message body"),
"Limit (in bytes) on maximum size of an XML-based request "
"body"),
/* System Resource Controls */
#ifdef RLIMIT_CPU
#else
#endif
#else
#endif
#ifdef RLIMIT_NPROC
#else
#endif
{ NULL }
};
/*****************************************************************
*
* Core handlers for various phases of server operation...
*/
{
if (r->proxyreq) {
return HTTP_FORBIDDEN;
}
"Invalid URI in request %s", r->the_request);
return HTTP_BAD_REQUEST;
}
}
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 /
*/
&& (*(r->uri) == '/')) {
NULL);
}
else {
NULL);
}
}
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 =
int rangestatus, errstatus;
#ifdef USE_MMAP_FILES
#endif
/* This handler has no use for a request body (yet), but we still
* need to read and discard it if the client sent one.
*/
return errstatus;
}
if (r->method_number == M_INVALID) {
"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;
}
"File does not exist: %s",r->path_info ?
: r->filename);
return HTTP_NOT_FOUND;
}
if (r->method_number != M_GET) {
return HTTP_METHOD_NOT_ALLOWED;
}
"file permissions deny server access: %s", r->filename);
return HTTP_FORBIDDEN;
}
ap_set_etag(r);
return errstatus;
}
#ifdef CHARSET_EBCDIC
if (d->content_md5 & 1) {
/* The call to ap_checkconv() in ap_send_http_header() is
* sufficient for most paths. Sending the MD5 digest in a
* header is special in that any change to translation decided
* by ap_checkconv() must be done before building that header,
* and thus before calling ap_send_http_header().
*/
ap_checkconv(r);
}
#endif /* CHARSET_EBCDIC */
#ifdef USE_MMAP_FILES
/* we need to protect ourselves in case we die while we've got the
* file mmapped */
"default_handler: mmap failed: %s", r->filename);
}
}
else {
}
#endif
#ifdef APACHE_XLATE
if (d->content_md5 & 1) {
}
#else
if (d->content_md5 & 1) {
}
#endif /* APACHE_XLATE */
rangestatus = ap_set_byterange(r);
if (!r->header_only) {
apr_size_t nbytes = 0;
if (!rangestatus) {
}
else {
"error byteserving file: %s", r->filename);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
}
}
#ifdef USE_MMAP_FILES
}
else {
unsigned char *addr;
if (d->content_md5 & 1) {
#ifdef APACHE_XLATE
}
#endif
}
rangestatus = ap_set_byterange(r);
if (!r->header_only) {
if (!rangestatus) {
}
else {
}
}
}
}
#endif
return OK;
}
static const handler_rec core_handlers[] = {
{ "*/*", default_handler },
{ "default-handler", default_handler },
};
{
}
{
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 register_hooks(void)
{
/* FIXME: I suspect we can eliminate the need for these - Ben */
}
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 */
};