http_core.c revision 7afdaa3ee342af2e075f62c619b60628556f7205
219N/A/* ==================================================================== 219N/A * The Apache Software License, Version 1.1 219N/A * Copyright (c) 2000 The Apache Software Foundation. All rights 219N/A * Redistribution and use in source and binary forms, with or without 219N/A * modification, are permitted provided that the following conditions 219N/A * 1. Redistributions of source code must retain the above copyright 219N/A * notice, this list of conditions and the following disclaimer. 219N/A * 2. Redistributions in binary form must reproduce the above copyright 219N/A * notice, this list of conditions and the following disclaimer in 219N/A * the documentation and/or other materials provided with the 219N/A * 3. The end-user documentation included with the redistribution, 219N/A * if any, must include the following acknowledgment: 219N/A * "This product includes software developed by the 219N/A * Alternately, this acknowledgment may appear in the software itself, 219N/A * if and wherever such third-party acknowledgments normally appear. 219N/A * 4. The names "Apache" and "Apache Software Foundation" must 219N/A * not be used to endorse or promote products derived from this 219N/A * software without prior written permission. For written 219N/A * permission, please contact apache@apache.org. 219N/A * 5. Products derived from this software may not be called "Apache", 219N/A * nor may "Apache" appear in their name, without prior written 219N/A * permission of the Apache Software Foundation. 219N/A * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 219N/A * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 219N/A * 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 * ==================================================================== * 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. #
include "http_main.h" /* For the default_handler below... *//* Make sure we don't write less than 4096 bytes at any one time. /* Allow Apache to use ap_mmap */ /* 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. #
endif /* MMAP_THRESHOLD */#
endif /* AP_USE_MMAP_FILES *//* LimitXMLRequestBody handling */ /* 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 /* there was no explicit setting of new->opts, so we merge * preserve the invariant (opts_add & opts_remove) == 0 /* otherwise we just copy, because an explicit opts setting * overrides all earlier +/- modifiers /* Add per-directory configuration entry (for <directory> section); * these are part of the core server 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. /* XXX: Fairly certain this is correct... '/' must prefix the path * or else in the case xyz:/ or abc/xyz:/, '/' must follow the ':'. * If there is no leading '/' or embedded ':/', then we are special. /* 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). /* we know they're both not special */ /* 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 /* we have to allocate tmp space to do a stable sort */ for (i = 0; i <
nelts; ++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 /* 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 /* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */ /* single reverse failed, so don't bother */ /* If we haven't checked the host name, and we want to */ /* if failed, set it to the NULL string to indicate error */ * 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). /* If we haven't checked the identity, and we want to */ /* 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... /* Read to NULL buffer to determine value size */ /* 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. * 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 */ /* Retrieve the name of the script filetype extension */ /* Open the key associated with the script filetype extension */ /* Open the key for the script command path by: * and if the strict arg is false, then continue trying: * The canonical way shell command entries are entered in the Win32 * registry is as follows: * shell [options] "%1" [args] * shell - full path name to interpreter or shell to run. * E.g., c:\usr\local\ntreskit\perl\bin\perl.exe * options - optional switches * "%1" - Place holder for file to run the shell against. * options - additional arguments * If we find a %1 or a quoted %1, lop off the remainder to arguments. /* Find the file extension */ "\tCOMSPEC variable is missing from the environment.",
ext);
/* 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! "ScriptInterpreterSource config directive set to \"registry-strict\"." APR_EOL_STR "\tInterpreter not found for files of type '%s'.",
ext);
"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... */ /* 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++) {
for (i =
2;
buffer[i] ==
' ' ; ++i)
/* Not a script, is it an executable? */ /***************************************************************** * 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 */ /* ### it would be nice to have atom-ized directives */ " cannot occur within <VirtualHost> section",
NULL);
" cannot occur within <Limit> section",
NULL);
void *
d_,
const char *
arg)
"Warning: DocumentRoot [%s] does not exist",
return "DocumentRoot must be a directory";
/* 1st parameter should be a 3 digit number, which we recognize; * convert it into an array index /* Heuristic to determine second argument. */ /* 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!");
/* hack. Prefix a " if it is a msg; as that is what * a msg and a (local) path. if (*w ==
'+' || *w ==
'-') {
else if (!
strcasecmp(w,
"SymLinksIfOwnerMatch")) {
else if (!
strcasecmp(w,
"RunScripts")) {
/* AI backcompat. Yuck */ /* we ensure the invariant (d->opts_add & d->opts_remove) == 0 */ return "Satisfy either 'any' or 'all'.";
return "TRACE cannot be controlled by <Limit>";
* Deal with <Limit> by adding the method to the list. * <LimitExcept>, so remove any/all occurrences of the method * in the extension array. /* Killing two features with one function, * if (tog == NULL) <Limit>, else <LimitExcept> /* We use this in <DirectoryMatch> and <FilesMatch>, to ensure that * people don't get bitten by wrong-cased regex matches * Report a missing-'>' syntax error. "> directive missing closing '>'",
NULL);
/* Treat 'default' path / as an inalienable root */ /* Treat UNC path // as an inalienable root */ /* Ensure that the pathname is canonical */ /* initialize our config and fetch it */ "> arguments not (yet) supported.",
NULL);
/* initialize our config and fetch it */ "> arguments not (yet) supported.",
NULL);
/* Only if not an .htaccess file */ /* Ensure that the pathname is canonical */ /* initialize our config and fetch it */ "> arguments not (yet) supported.",
NULL);
if ((!
not &&
defined) || (
not && !
defined)) {
/* httpd.conf commands... beginning with the <VirtualHost> business */ /* 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 */ return "<VirtualHost> doesn't nest!";
return "ServerAlias only used in <VirtualHost>";
"': not in list of loaded modules",
NULL);
/* This one's pretty generic... */ if (
port <= 0 ||
port >=
65536) {
/* 65536 == 1<<16 */ "\" is outside the appropriate range " "(i.e., 1..65535).",
NULL);
return "ServerSignature: use one of: off | on | email";
return "ServerRoot must be a valid directory";
/* We've changed it to On/Off, but used to use numbers * so we accept anything but "Off" or "0" as "On" return "parameter must be 'on', 'off', or 'double'";
return "parameter must be 'on', 'off', or 'dns'";
return "LogLevel requires level keyword: one of " return "LogLevel requires level keyword";
" Server at <A HREF=\"mailto:",
* Load an authorisation realm into our location configuration, applying the * usual rules that apply to realms. * 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 SrvTk_FULL,
/* eg: Apache/1.3.0 (UNIX) PHP/3.0 FooBar/1.2b */ * 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. * Tack the given component identifier to the end of * This routine adds the real server base identity to the version string, * and then locks out changes until the next reconfig. * Lock the server_version string if we're not displaying "\" must be a non-negative integer",
NULL);
"must not exceed the precompiled maximum of %d",
"\" must be a non-negative integer (0 = no limit)",
"must not exceed the precompiled maximum of %d",
"\" must be a non-negative integer (0 = no limit)",
/* 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 "LimitXMLRequestBody requires a non-negative integer.";
"\" must be \"registry\", \"registry-strict\" or " "%s not supported on this platform",
cmd->
cmd->
name);
const char *
arg,
const char *
arg2)
const char *
arg,
const char *
arg2)
/* XXX handle checking for non-blocking socket */ /* If the write did not complete, adjust the iovecs and issue /* Skip over the vectors that have already been written */ /* Handle partial write of vec i */ * 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. apr_off_t o;
/* Track the file offset for partial writes */ * writev_it_all handles partial writes. * XXX: optimization... if headers are less than MIN_WRITE_SIZE, copy /* Seek the file to 'offset' */ /* Send the file, making sure to handle partial writes */ o +=
bytes_sent;
/* o is where we are in the buffer */ * XXX: optimization... if it will fit, send this on the last send in the /* Note --- ErrorDocument will now work from .htaccess files. * The AllowOverride of Fileinfo allows webmasters to turn it off /* Old access config file commands */ "Container for directives affecting resources located in the specified " "Container for directives affecting resources accessed through the " "Container to map directives to a particular virtual host, takes one or " "Container for directives affecting files matching specified patterns"),
"Container for authentication directives when accessed using specified HTTP " "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 " "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')"),
"Directory to plop gmon.out files"),
"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 " "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 */ /* 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"),
"Name of server User's bs2000 logon account name"),
"Where to find interpreter to run Win32 scripts (Registry or script shebang line)"),
"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 " /* System Resource Controls */ /* 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 "filters to be run on the request body"),
/***************************************************************** * Core handlers for various phases of server operation... * Make sure that we do not mess up the translation by adding two * /'s in a row. This happens under windows when the document /* XXX if/when somebody writes a content-md5 filter we either need to * remove this support or coordinate when to use the filter vs. * 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). "file permissions deny server access: %s", r->
filename);
/* we need to protect ourselves in case we die while we've got the "default_handler: mmap failed: %s", r->
filename);
* This is a simple filter to coalesce many small buckets into one large * This implementation of coalesce_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. char *
buf;
/* Start of buffer */ char *
cur;
/* Pointer to next location to write */ /* Iterate across the buckets, coalescing the small buckets into a /* Coalesce this bucket into the buffer */ /* 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. /* This bucket was not able to be coalesced because it either * exceeds MIN_BUCKET_SIZE or its contents will not fit into /* If there is even a single bucket that cannot be coalesced, * then we must pass the brigade down to the next filter. /* Insert ctx->buf into the correct spotin the brigade */ /* Get ctx->buf ready for the next brigade */ /* The brigade should be empty now because all the buckets * were coalesced into the coalesce_filter buf * HTTP/1.1 chunked transfer encoding filter. char chunk_hdr[
20];
/* enough space for the snprintf below */ /* there shouldn't be anything after the eos */ /* unknown amount of data (e.g. a pipe) */ * 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. /* 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. * 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 */ * Insert the chunk header, specifying the number of bytes in /* XXX might be nice to have APR_OFF_T_FMT_HEX */ * Insert the end-of-chunk CRLF before the EOS bucket, or * appended to the brigade /* RFC 2616, Section 3.6.1 * If there is an EOS bucket, then prefix it with: * 1) the last-chunk marker ("0" CRLF) * 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 /* XXX: (2) trailers ... does not yet exist */ /* pass the brigade to the next filter. */ if (!f->
ctx) {
/* If we haven't passed up the socket yet... */ /* Either some code lost track of the socket * bucket or we already found out that the /* 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 /* If we have a saved brigade, concatenate the new brigade to it */ /* Iterate over the brigade collecting iovecs */ nbytes = 0;
/* in case more points to another brigade */ /* Assume there is at most one AP_BUCKET_FILE in the brigade */ /* The bucket is a trailer to a file bucket */ /* Split the brigade and break */ /* Completed iterating over the brigades, now determine if we want to * buffer the brigade or send the brigade out on the network /* NEVER save an EOS in here. If we are saving a brigade with an * EOS bucket, then we are doing keepalive connections, and we want * to process to second request fully. /* Prepare the socket to be reused */ fd,
/* The file to send */ &
hdtr,
/* Header and trailer iovecs */ &
foffset,
/* Offset in file to begin sending from */ /* If apr_sendfile() returns APR_ENOTIMPL, call send_the_file() to * 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. /* FIXME: I suspect we can eliminate the need for these - Ben */ /* register the core's insert_filter hook and register core-provided