From: (no author) <(no author)@unknown> Date: Mon, 9 Jul 2001 17:53:16 +0000 (+0000) Subject: This commit was manufactured by cvs2svn to create tag X-Git-Tag: 2.0.20^0 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b9374d2641f5430f11f835d098c9bf712ecbc5c4;p=thirdparty%2Fapache%2Fhttpd.git This commit was manufactured by cvs2svn to create tag 'APACHE_2_0_20'. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/tags/2.0.20@89526 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 1590153e924..4d4a023ed48 100644 --- a/CHANGES +++ b/CHANGES @@ -1,7 +1,4 @@ -Changes with Apache 2.0.21-dev - Changes with Apache 2.0.20 - *) Fix problem in content-length filter where the filter would buffer all the output from a CGI before sending any bytes down the filter stack to the network. This problem would cause diff --git a/docs/manual/bind.html.en b/docs/manual/bind.html.en deleted file mode 100644 index 208c6c54a21..00000000000 --- a/docs/manual/bind.html.en +++ /dev/null @@ -1,78 +0,0 @@ - -
-When Apache starts, it connects to some port and address on the
-local machine and waits for incoming requests. By default, it
-listens to all addresses on the machine, and to the port
-as specified by the Port directive in the server configuration.
-However, it can be told to listen to more the one port, or to listen
-to only selected addresses, or a combination. This is often combined
-with the Virtual Host feature which determines how Apache
-responds to different IP addresses, hostnames and ports.
The Listen directive tells the server to accept
-incoming requests only on the specified port or address-and-port
-combinations. If only a port number is specified in the
-Listen directive, the server listens to the given port on
-all interfaces, instead of the port given by the Port
-directive. If an IP address is given as well as a port, the server
-will listen on the given port and interface. Multiple Listen
-directives may be used to specify a number of addresses and ports to
-listen to. The server will respond to requests from any of the listed
-addresses and ports.
For example, to make the server accept connections on both port -80 and port 8000, use: -
- Listen 80 - Listen 8000 -- -To make the server accept connections on two specified -interfaces and port numbers, use -
- Listen 192.170.2.1:80 - Listen 192.170.2.5:8000 -- -
Listen does not implement Virtual Hosts. It only tells the -main server what addresses and ports to listen to. If no -<VirtualHost> directives are used, the server will behave the -same for all accepted requests. However, <VirtualHost> can be -used to specify a different behavior for one or more of the addresses -and ports. To implement a VirtualHost, the server must first be told -to listen to the address and port to be used. Then a -<VirtualHost> section should be created for a specified address -and port to set the behavior of this virtual host. Note that if the -<VirtualHost> is set for an address and port that the server is -not listening to, it cannot be accessed. - -
As implemented in Apache 1.1.1 and earlier versions, the method -Apache used to create PATH_INFO in the CGI environment was -counterintuitive, and could result in crashes in certain cases. In -Apache 1.2 and beyond, this behavior has changed. Although this -results in some compatibility problems with certain legacy CGI -applications, the Apache 1.2 behavior is still compatible with the -CGI/1.1 specification, and CGI scripts can be easily modified (see below). - -
Apache 1.1.1 and earlier implemented the PATH_INFO and SCRIPT_NAME -environment variables by looking at the filename, not the URL. While -this resulted in the correct values in many cases, when the filesystem -path was overloaded to contain path information, it could result in -errant behavior. For example, if the following appeared in a config -file: -
- Alias /cgi-ralph /usr/local/httpd/cgi-bin/user.cgi/ralph --
In this case, user.cgi is the CGI script, the "/ralph"
-is information to be passed onto the CGI. If this configuration was in
-place, and a request came for "/cgi-ralph/script/", the
-code would set PATH_INFO to "/ralph/script", and
-SCRIPT_NAME to "/cgi-". Obviously, the latter is
-incorrect. In certain cases, this could even cause the server to
-crash.
Apache 1.2 and later now determine SCRIPT_NAME and PATH_INFO by
-looking directly at the URL, and determining how much of the URL is
-client-modifiable, and setting PATH_INFO to it. To use the above
-example, PATH_INFO would be set to "/script", and
-SCRIPT_NAME to "/cgi-ralph". This makes sense and results
-in no server behavior problems. It also permits the script to be
-guaranteed that
-"http://$SERVER_NAME:$SERVER_PORT$SCRIPT_NAME$PATH_INFO"
-will always be an accessible URL that points to the current script,
-something which was not necessarily true with previous versions of
-Apache.
-
-
However, the "/ralph"
-information from the Alias directive is lost. This is
-unfortunate, but we feel that using the filesystem to pass along this
-sort of information is not a recommended method, and a script making
-use of it "deserves" not to work. Apache 1.2b3 and later, however, do
-provide a workaround.
-
-
It may be necessary for a script that was designed for earlier -versions of Apache or other servers to need the information that the -old PATH_INFO variable provided. For this purpose, Apache 1.2 (1.2b3 -and later) sets an additional variable, FILEPATH_INFO. This -environment variable contains the value that PATH_INFO would have had -with Apache 1.1.1.
- -A script that wishes to work with both Apache 1.2 and earlier -versions can simply test for the existence of FILEPATH_INFO, and use -it if available. Otherwise, it can use PATH_INFO. For example, in -Perl, one might use: -
- $path_info = $ENV{'FILEPATH_INFO'} || $ENV{'PATH_INFO'};
-
-
-By doing this, a script can work with all servers supporting the -CGI/1.1 specification, including all versions of Apache.
- - - - - diff --git a/docs/manual/content-negotiation.html.en b/docs/manual/content-negotiation.html.en deleted file mode 100644 index d1b4ab20abc..00000000000 --- a/docs/manual/content-negotiation.html.en +++ /dev/null @@ -1,590 +0,0 @@ - - - --Apache's support for content negotiation has been updated to meet the -HTTP/1.1 specification. It can choose the best representation of a -resource based on the browser-supplied preferences for media type, -languages, character set and encoding. It is also implements a -couple of features to give more intelligent handling of requests from -browsers which send incomplete negotiation information.
- -Content negotiation is provided by the -mod_negotiation module, -which is compiled in by default. - -
-A resource may be available in several different representations. For -example, it might be available in different languages or different -media types, or a combination. One way of selecting the most -appropriate choice is to give the user an index page, and let them -select. However it is often possible for the server to choose -automatically. This works because browsers can send as part of each -request information about what representations they prefer. For -example, a browser could indicate that it would like to see -information in French, if possible, else English will do. Browsers -indicate their preferences by headers in the request. To request only -French representations, the browser would send - -
- Accept-Language: fr -- -
-Note that this preference will only be applied when there is a choice -of representations and they vary by language. -
- -As an example of a more complex request, this browser has been -configured to accept French and English, but prefer French, and to -accept various media types, preferring HTML over plain text or other -text types, and preferring GIF or JPEG over other media types, but also -allowing any other media type as a last resort: - -
- Accept-Language: fr; q=1.0, en; q=0.5 - Accept: text/html; q=1.0, text/*; q=0.8, image/gif; q=0.6, - image/jpeg; q=0.6, image/*; q=0.5, */*; q=0.1 -- -Apache 1.2 supports 'server driven' content negotiation, as defined in -the HTTP/1.1 specification. It fully supports the Accept, -Accept-Language, Accept-Charset and Accept-Encoding request headers. -Apache 1.3.4 also supports 'transparent' content negotiation, which is -an experimental negotiation protocol defined in RFC 2295 and RFC 2296. -It does not offer support for 'feature negotiation' as defined in -these RFCs. -
- -A resource is a conceptual entity identified by a URI -(RFC 2396). An HTTP server like Apache provides access to -representations of the resource(s) within its namespace, -with each representation in the form of a sequence of bytes with a -defined media type, character set, encoding, etc. Each resource may be -associated with zero, one, or more than one representation -at any given time. If multiple representations are available, -the resource is referred to as negotiable and each of its -representations is termed a variant. The ways in which the -variants for a negotiable resource vary are called the -dimensions of negotiation. - -
-In order to negotiate a resource, the server needs to be given -information about each of the variants. This is done in one of two -ways: - -
*.var file) which
- names the files containing the variants explicitly, or
-
-A type map is a document which is associated with the handler
-named type-map (or, for backwards-compatibility with
-older Apache configurations, the mime type
-application/x-type-map). Note that to use this feature,
-you must have a handler set in the configuration that defines a
-file suffix as type-map; this is best done with a
-
-
- AddHandler type-map .var -- -in the server configuration file. See the comments in the sample config -file for more details.
- -Type map files have an entry for each available variant; these entries -consist of contiguous HTTP-format header lines. Entries for -different variants are separated by blank lines. Blank lines are -illegal within an entry. It is conventional to begin a map file with -an entry for the combined entity as a whole (although this -is not required, and if present will be ignored). An example -map file is: - -
- URI: foo - - URI: foo.en.html - Content-type: text/html - Content-language: en - - URI: foo.fr.de.html - Content-type: text/html;charset=iso-8859-2 - Content-language: fr, de -- -If the variants have different source qualities, that may be indicated -by the "qs" parameter to the media type, as in this picture (available -as jpeg, gif, or ASCII-art): - -
- URI: foo - - URI: foo.jpeg - Content-type: image/jpeg; qs=0.8 - - URI: foo.gif - Content-type: image/gif; qs=0.5 - - URI: foo.txt - Content-type: text/plain; qs=0.01 --
- -qs values can vary in the range 0.000 to 1.000. Note that any variant with -a qs value of 0.000 will never be chosen. Variants with no 'qs' -parameter value are given a qs factor of 1.0. The qs parameter indicates -the relative 'quality' of this variant compared to the other available -variants, independent of the client's capabilities. For example, a jpeg -file is usually of higher source quality than an ascii file if it is -attempting to represent a photograph. However, if the resource being -represented is an original ascii art, then an ascii representation would -have a higher source quality than a jpeg representation. A qs value -is therefore specific to a given variant depending on the nature of -the resource it represents. - -
-The full list of headers recognized is: - -
URI:
- Content-Type:
- image/gif, text/plain, or
- text/html; level=3.
- Content-Language:
- en for English,
- kr for Korean, etc.).
- Content-Encoding:
- x-compress
- for compress'd files, and x-gzip for gzip'd files.
- The x- prefix is ignored for encoding comparisons.
- Content-Length:
- Description:
-
-MultiViews is a per-directory option, meaning it can be set with
-an Options directive within a <Directory>,
-<Location> or <Files>
-section in access.conf, or (if AllowOverride
-is properly set) in .htaccess files. Note that
-Options All does not set MultiViews; you
-have to ask for it by name.
-
-
-The effect of MultiViews is as follows: if the server
-receives a request for /some/dir/foo, if
-/some/dir has MultiViews enabled, and
-/some/dir/foo does not exist, then the server reads the
-directory looking for files named foo.*, and effectively fakes up a
-type map which names all those files, assigning them the same media
-types and content-encodings it would have if the client had asked for
-one of them by name. It then chooses the best match to the client's
-requirements.
-
-
-MultiViews may also apply to searches for the file named by the
-DirectoryIndex directive, if the server is trying to
-index a directory. If the configuration files specify
-
-
- DirectoryIndex index -- -then the server will arbitrate between
index.html
-and index.html3 if both are present. If neither are
-present, and index.cgi is there, the server will run it.
-
--If one of the files found when reading the directive is a CGI script, -it's not obvious what should happen. The code gives that case -special treatment --- if the request was a POST, or a GET with -QUERY_ARGS or PATH_INFO, the script is given an extremely high quality -rating, and generally invoked; otherwise it is given an extremely low -quality rating, which generally causes one of the other views (if any) -to be retrieved. - -
- -There are two negotiation methods: - -
| Dimension - | Notes - |
|---|---|
| Media Type - | Browser indicates preferences with the Accept header field. Each item -can have an associated quality factor. Variant description can also -have a quality factor (the "qs" parameter). - |
| Language - | Browser indicates preferences with the Accept-Language header field. -Each item can have a quality factor. Variants can be associated with none, one -or more than one language. - |
| Encoding - | Browser indicates preference with the Accept-Encoding header field. -Each item can have a quality factor. - |
| Charset - | Browser indicates preference with the Accept-Charset header field. -Each item can have a quality factor. -Variants can indicate a charset as a parameter of the media type. - |
-Apache can use the following algorithm to select the 'best' variant -(if any) to return to the browser. This algorithm is not -further configurable. It operates as follows: - -
LanguagePriority
- directive (if present).
-
-text/* media type but not explicitly associated
- with a particular charset are assumed to be in ISO-8859-1.
-
--Apache sometimes changes the quality values from what would be -expected by a strict interpretation of the Apache negotiation -algorithm above. This is to get a better result from the algorithm for -browsers which do not send full or accurate information. Some of the -most popular browsers send Accept header information which would -otherwise result in the selection of the wrong variant in many -cases. If a browser sends full and correct information these fiddles -will not be applied. -
- -
-The Accept: request header indicates preferences for media types. It -can also include 'wildcard' media types, such as "image/*" or "*/*" -where the * matches any string. So a request including: -
- Accept: image/*, */* -- -would indicate that any type starting "image/" is acceptable, -as is any other type (so the first "image/*" is redundant). Some -browsers routinely send wildcards in addition to explicit types they -can handle. For example: -
- Accept: text/html, text/plain, image/gif, image/jpeg, */* -- -The intention of this is to indicate that the explicitly -listed types are preferred, but if a different representation is -available, that is ok too. However under the basic algorithm, as given -above, the */* wildcard has exactly equal preference to all the other -types, so they are not being preferred. The browser should really have -sent a request with a lower quality (preference) value for *.*, such -as: -
- Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01 -- -The explicit types have no quality factor, so they default to a -preference of 1.0 (the highest). The wildcard */* is given -a low preference of 0.01, so other types will only be returned if -no variant matches an explicitly listed type. -
- -If the Accept: header contains no q factors at all, Apache sets -the q value of "*/*", if present, to 0.01 to emulate the desired -behavior. It also sets the q value of wildcards of the format -"type/*" to 0.02 (so these are preferred over matches against -"*/*". If any media type on the Accept: header contains a q factor, -these special values are not applied, so requests from browsers -which send the correct information to start with work as expected. - -
-If some of the variants for a particular resource have a language -attribute, and some do not, those variants with no language -are given a very low language quality factor of 0.001.
- -The reason for setting this language quality factor for -variant with no language to a very low value is to allow -for a default variant which can be supplied if none of the -other variants match the browser's language preferences. - -For example, consider the situation with three variants: - -
-The meaning of a variant with no language is that it is -always acceptable to the browser. If the request Accept-Language -header includes either en or fr (or both) one of foo.en.html -or foo.fr.html will be returned. If the browser does not list -either en or fr as acceptable, foo.html will be returned instead. - -
{encoding ..} element is used in
-variant lists to label variants which are available with a specific
-content-encoding only. The implementation of the
-RVSA/1.0 algorithm (RFC 2296) is extended to recognize encoded
-variants in the list, and to use them as candidate variants whenever
-their encodings are acceptable according to the Accept-Encoding
-request header. The RVSA/1.0 implementation does not round computed
-quality factors to 5 decimal places before choosing the best variant.
-
--If you are using language negotiation you can choose between -different naming conventions, because files can have more than one -extension, and the order of the extensions is normally irrelevant -(see mod_mime documentation for details). -
-A typical file has a MIME-type extension (e.g., html), -maybe an encoding extension (e.g., gz), and of course a -language extension (e.g., en) when we have different -language variants of this file. - -
-Examples: -
-Here some more examples of filenames together with valid and invalid -hyperlinks: -
- -| Filename | -Valid hyperlink | -Invalid hyperlink | -
|---|---|---|
| foo.html.en | -foo - foo.html |
- - | -
| foo.en.html | -foo | -foo.html | -
| foo.html.en.gz | -foo - foo.html |
- foo.gz - foo.html.gz |
-
| foo.en.html.gz | -foo | -foo.html - foo.html.gz - foo.gz |
-
| foo.gz.html.en | -foo - foo.gz - foo.gz.html |
- foo.html | -
| foo.html.gz.en | -foo - foo.html - foo.html.gz |
- foo.gz | -
-Looking at the table above you will notice that it is always possible to -use the name without any extensions in an hyperlink (e.g., foo). -The advantage is that you can hide the actual type of a -document rsp. file and can change it later, e.g., from html -to shtml or cgi without changing any -hyperlink references. - -
-If you want to continue to use a MIME-type in your hyperlinks (e.g. -foo.html) the language extension (including an encoding extension -if there is one) must be on the right hand side of the MIME-type extension -(e.g., foo.html.en). - - -
-When a cache stores a representation, it associates it with the request URL. -The next time that URL is requested, the cache can use the stored -representation. But, if the resource is negotiable at the server, -this might result in only the first requested variant being cached and -subsequent cache hits might return the wrong response. To prevent this, -Apache normally marks all responses that are returned after content negotiation -as non-cacheable by HTTP/1.0 clients. Apache also supports the HTTP/1.1 -protocol features to allow caching of negotiated responses.
- -For requests which come from a HTTP/1.0 compliant client (either a -browser or a cache), the directive CacheNegotiatedDocs can be -used to allow caching of responses which were subject to negotiation. -This directive can be given in the server config or virtual host, and -takes no arguments. It has no effect on requests from HTTP/1.1 clients. - - - - diff --git a/docs/manual/custom-error.html.en b/docs/manual/custom-error.html.en deleted file mode 100644 index 09604ea972b..00000000000 --- a/docs/manual/custom-error.html.en +++ /dev/null @@ -1,177 +0,0 @@ - - -
-Customizable responses can be defined to be activated in the - event of a server detected error or problem. - -
e.g. if a script crashes and produces a "500 Server Error" - response, then this response can be replaced with either some - friendlier text or by a redirection to another URL (local or - external). -
- -
- -
Redirecting to another URL can be useful, but only if some information - can be passed which can then be used to explain and/or log the - error/problem - more clearly. - -
To achieve this, Apache will define new CGI-like environment - variables, e.g. - -
-REDIRECT_HTTP_ACCEPT=*/*, image/gif, image/x-xbitmap, image/jpeg
-REDIRECT_HTTP_USER_AGENT=Mozilla/1.1b2 (X11; I; HP-UX A.09.05 9000/712)
-REDIRECT_PATH=.:/bin:/usr/local/bin:/etc
-REDIRECT_QUERY_STRING=
-REDIRECT_REMOTE_ADDR=121.345.78.123
-REDIRECT_REMOTE_HOST=ooh.ahhh.com
-REDIRECT_SERVER_NAME=crash.bang.edu
-REDIRECT_SERVER_PORT=80
-REDIRECT_SERVER_SOFTWARE=Apache/0.8.15
-REDIRECT_URL=/cgi-bin/buggy.pl
-
-
- note the REDIRECT_ prefix.
-
-
At least REDIRECT_URL and REDIRECT_QUERY_STRING
- will
- be passed to the new URL (assuming it's a cgi-script or a cgi-include).
- The
- other variables will exist only if they existed prior to the
- error/problem.
- None of these will be set if your ErrorDocument is an
- external redirect (i.e., anything starting with a
- scheme name
- like http:, even if it refers to the same host as the
- server).
- -
Here are some examples... - -
-ErrorDocument 500 /cgi-bin/crash-recover
-ErrorDocument 500 "Sorry, our script crashed. Oh dear
-ErrorDocument 500 http://xxx/
-ErrorDocument 404 /Lame_excuses/not_found.html
-ErrorDocument 401 /Subscription/how_to_subscribe.html
-
-
- The syntax is, - -
ErrorDocument
-<3-digit-code> action
-
-
where the action can be, - -
- -
- -
- -
REDIRECT_. REDIRECT_ environment
-variables are created from the CGI environment variables which existed
-prior to the redirect, they are renamed with a REDIRECT_
-prefix, i.e., HTTP_USER_AGENT becomes
-REDIRECT_HTTP_USER_AGENT. In addition to these new
-variables, Apache will define REDIRECT_URL and
-REDIRECT_STATUS to help the script trace its origin.
-Both the original URL and the URL being redirected to can be logged in
-the access log.
-
--If the ErrorDocument specifies a local redirect to a CGI script, the script -should include a "Status:" header field in its output -in order to ensure the propagation all the way back to the client -of the error condition that caused it to be invoked. For instance, a Perl -ErrorDocument script might include the following: -
-
- :
- print "Content-type: text/html\n";
- printf "Status: %s Condition Intercepted\n", $ENV{"REDIRECT_STATUS"};
- :
-
--If the script is dedicated to handling a particular error condition, such as -404 Not Found, it can use the specific code and -error text instead. -
- - - - diff --git a/docs/manual/developer/API.html b/docs/manual/developer/API.html deleted file mode 100644 index 496be760c97..00000000000 --- a/docs/manual/developer/API.html +++ /dev/null @@ -1,1161 +0,0 @@ - - -Warning: -This document has not been updated to take into account changes -made in the 2.0 version of the Apache HTTP Server. Some of the -information may still be relevant, but please use it -with care. -- -
- -A few notes on general pedagogical style here. In the interest of -conciseness, all structure declarations here are incomplete --- the -real ones have more slots that I'm not telling you about. For the -most part, these are reserved to one component of the server core or -another, and should be altered by modules with caution. However, in -some cases, they really are things I just haven't gotten around to -yet. Welcome to the bleeding edge.
- -Finally, here's an outline, to give you some bare idea of what's -coming up, and in what order: - -
SetEnv, which don't really fit well elsewhere.
- OK.
- DECLINED. In this case, the
- server behaves in all respects as if the handler simply hadn't
- been there.
- */* (i.e., a
-wildcard MIME type specification). However, wildcard handlers are
-only invoked if the server has already tried and failed to find a more
-specific response handler for the MIME type of the requested object
-(either none existed, or they all declined).
-
-The handlers themselves are functions of one argument (a
-request_rec structure. vide infra), which returns an
-integer, as above.
- -
ScriptAlias config file
-command. It's actually a great deal more complicated than most
-modules, but if we're going to have only one example, it might as well
-be the one with its fingers in every place.
-
-Let's begin with handlers. In order to handle the CGI scripts, the
-module declares a response handler for them. Because of
-ScriptAlias, it also has handlers for the name
-translation phase (to recognize ScriptAliased URIs), the
-type-checking phase (any ScriptAliased request is typed
-as a CGI script).
-
-The module needs to maintain some per (virtual)
-server information, namely, the ScriptAliases in effect;
-the module structure therefore contains pointers to a functions which
-builds these structures, and to another which combines two of them (in
-case the main server and a virtual server both have
-ScriptAliases declared).
-
-Finally, this module contains code to handle the
-ScriptAlias command itself. This particular module only
-declares one command, but there could be more, so modules have
-command tables which declare their commands, and describe
-where they are permitted, and how they are to be invoked.
-
-A final note on the declared types of the arguments of some of these
-commands: a pool is a pointer to a resource pool
-structure; these are used by the server to keep track of the memory
-which has been allocated, files opened, etc., either to service a
-particular request, or to handle the process of configuring itself.
-That way, when the request is over (or, for the configuration pool,
-when the server is restarting), the memory can be freed, and the files
-closed, en masse, without anyone having to write explicit code to
-track them all down and dispose of them. Also, a
-cmd_parms structure contains various information about
-the config file being read, and other status information, which is
-sometimes of use to the function which processes a config-file command
-(such as ScriptAlias).
-
-With no further ado, the module itself:
-
-
-/* Declarations of handlers. */
-
-int translate_scriptalias (request_rec *);
-int type_scriptalias (request_rec *);
-int cgi_handler (request_rec *);
-
-/* Subsidiary dispatch table for response-phase handlers, by MIME type */
-
-handler_rec cgi_handlers[] = {
-{ "application/x-httpd-cgi", cgi_handler },
-{ NULL }
-};
-
-/* Declarations of routines to manipulate the module's configuration
- * info. Note that these are returned, and passed in, as void *'s;
- * the server core keeps track of them, but it doesn't, and can't,
- * know their internal structure.
- */
-
-void *make_cgi_server_config (pool *);
-void *merge_cgi_server_config (pool *, void *, void *);
-
-/* Declarations of routines to handle config-file commands */
-
-extern char *script_alias(cmd_parms *, void *per_dir_config, char *fake,
- char *real);
-
-command_rec cgi_cmds[] = {
-{ "ScriptAlias", script_alias, NULL, RSRC_CONF, TAKE2,
- "a fakename and a realname"},
-{ NULL }
-};
-
-module cgi_module = {
- STANDARD_MODULE_STUFF,
- NULL, /* initializer */
- NULL, /* dir config creator */
- NULL, /* dir merger --- default is to override */
- make_cgi_server_config, /* server config */
- merge_cgi_server_config, /* merge server config */
- cgi_cmds, /* command table */
- cgi_handlers, /* handlers */
- translate_scriptalias, /* filename translation */
- NULL, /* check_user_id */
- NULL, /* check auth */
- NULL, /* check access */
- type_scriptalias, /* type_checker */
- NULL, /* fixups */
- NULL, /* logger */
- NULL /* header parser */
-};
-
-
-request_rec structure.
-This structure describes a particular request which has been made to
-the server, on behalf of a client. In most cases, each connection to
-the client generates only one request_rec structure.- -
request_recrequest_rec contains pointers to a resource pool
-which will be cleared when the server is finished handling the
-request; to structures containing per-server and per-connection
-information, and most importantly, information on the request itself.- -The most important such information is a small set of character -strings describing attributes of the object being requested, including -its URI, filename, content-type and content-encoding (these being filled -in by the translation and type-check handlers which handle the -request, respectively).
-
-Other commonly used data items are tables giving the MIME headers on
-the client's original request, MIME headers to be sent back with the
-response (which modules can add to at will), and environment variables
-for any subprocesses which are spawned off in the course of servicing
-the request. These tables are manipulated using the
-ap_table_get and ap_table_set routines.
-
- Note that the Content-type header value cannot be - set by module content-handlers using the ap_table_*() - routines. Rather, it is set by pointing the content_type - field in the request_rec structure to an appropriate - string. E.g., --Finally, there are pointers to two data structures which, in turn, -point to per-module configuration structures. Specifically, these -hold pointers to the data structures which the module has built to -describe the way it has been configured to operate in a given -directory (via- r->content_type = "text/html"; --
.htaccess files or
-<Directory> sections), for private data it has
-built in the course of servicing the request (so modules' handlers for
-one phase can pass `notes' to their handlers for other phases). There
-is another such configuration vector in the server_rec
-data structure pointed to by the request_rec, which
-contains per (virtual) server configuration data.- -Here is an abridged declaration, giving the fields most commonly used:
- -
-struct request_rec {
-
- pool *pool;
- conn_rec *connection;
- server_rec *server;
-
- /* What object is being requested */
-
- char *uri;
- char *filename;
- char *path_info;
- char *args; /* QUERY_ARGS, if any */
- struct stat finfo; /* Set by server core;
- * st_mode set to zero if no such file */
-
- char *content_type;
- char *content_encoding;
-
- /* MIME header environments, in and out. Also, an array containing
- * environment variables to be passed to subprocesses, so people can
- * write modules to add to that environment.
- *
- * The difference between headers_out and err_headers_out is that
- * the latter are printed even on error, and persist across internal
- * redirects (so the headers printed for ErrorDocument handlers will
- * have them).
- */
-
- table *headers_in;
- table *headers_out;
- table *err_headers_out;
- table *subprocess_env;
-
- /* Info about the request itself... */
-
- int header_only; /* HEAD request, as opposed to GET */
- char *protocol; /* Protocol, as given to us, or HTTP/0.9 */
- char *method; /* GET, HEAD, POST, etc. */
- int method_number; /* M_GET, M_POST, etc. */
-
- /* Info for logging */
-
- char *the_request;
- int bytes_sent;
-
- /* A flag which modules can set, to indicate that the data being
- * returned is volatile, and clients should be told not to cache it.
- */
-
- int no_cache;
-
- /* Various other config info which may change with .htaccess files
- * These are config vectors, with one void* pointer for each module
- * (the thing pointed to being the module's business).
- */
-
- void *per_dir_config; /* Options set in config files, etc. */
- void *request_config; /* Notes on *this* request */
-
-};
-
-
-
-request_rec structures are built by reading an HTTP
-request from a client, and filling in the fields. However, there are
-a few exceptions:
-
-*.var file), or a CGI script which returned a
- local `Location:', then the resource which the user requested
- is going to be ultimately located by some URI other than what
- the client originally supplied. In this case, the server does
- an internal redirect, constructing a new
- request_rec for the new URI, and processing it
- almost exactly as if the client had requested the new URI
- directly. - -
ErrorDocument is in scope, the same internal
- redirect machinery comes into play.- -
-
- Such handlers can construct a sub-request, using the
- functions ap_sub_req_lookup_file,
- ap_sub_req_lookup_uri, and
- ap_sub_req_method_uri; these construct a new
- request_rec structure and processes it as you
- would expect, up to but not including the point of actually
- sending a response. (These functions skip over the access
- checks if the sub-request is for a file in the same directory
- as the original request).
-
- (Server-side includes work by building sub-requests and then
- actually invoking the response handler for them, via the
- function ap_run_sub_req).
-
request_rec, has to return an int to
-indicate what happened. That can either be
-
-REDIRECT, then
-the module should put a Location in the request's
-headers_out, to indicate where the client should be
-redirected to. - -
request_rec structure (or, in the case of access
-checkers, simply by returning the correct error code). However,
-response handlers have to actually send a request back to the client.
-
-They should begin by sending an HTTP response header, using the
-function ap_send_http_header. (You don't have to do
-anything special to skip sending the header for HTTP/0.9 requests; the
-function figures out on its own that it shouldn't do anything). If
-the request is marked header_only, that's all they should
-do; they should return after that, without attempting any further
-output.
-
-Otherwise, they should produce a request body which responds to the
-client as appropriate. The primitives for this are ap_rputc
-and ap_rprintf, for internally generated output, and
-ap_send_fd, to copy the contents of some FILE *
-straight to the client.
-
-At this point, you should more or less understand the following piece
-of code, which is the handler which handles GET requests
-which have no more specific handler; it also shows how conditional
-GETs can be handled, if it's desirable to do so in a
-particular response handler --- ap_set_last_modified checks
-against the If-modified-since value supplied by the
-client, if any, and returns an appropriate code (which will, if
-nonzero, be USE_LOCAL_COPY). No similar considerations apply for
-ap_set_content_length, but it returns an error code for
-symmetry.
- -
-int default_handler (request_rec *r)
-{
- int errstatus;
- FILE *f;
-
- if (r->method_number != M_GET) return DECLINED;
- if (r->finfo.st_mode == 0) return NOT_FOUND;
-
- if ((errstatus = ap_set_content_length (r, r->finfo.st_size))
- || (errstatus = ap_set_last_modified (r, r->finfo.st_mtime)))
- return errstatus;
-
- f = fopen (r->filename, "r");
-
- if (f == NULL) {
- log_reason("file permissions deny server access",
- r->filename, r);
- return FORBIDDEN;
- }
-
- register_timeout ("send", r);
- ap_send_http_header (r);
-
- if (!r->header_only) send_fd (f, r);
- ap_pfclose (r->pool, f);
- return OK;
-}
-
-
-Finally, if all of this is too much of a challenge, there are a few
-ways out of it. First off, as shown above, a response handler which
-has not yet produced any output can simply return an error code, in
-which case the server will automatically produce an error response.
-Secondly, it can punt to some other handler by invoking
-ap_internal_redirect, which is how the internal redirection
-machinery discussed above is invoked. A response handler which has
-internally redirected should always return OK.
-
-(Invoking ap_internal_redirect from handlers which are
-not response handlers will lead to serious confusion).
-
-
ap_auth_type,
- ap_auth_name, and ap_requires.
- ap_get_basic_auth_pw,
- which sets the connection->user structure field
- automatically, and ap_note_basic_auth_failure, which
- arranges for the proper WWW-Authenticate: header
- to be sent back).
-request_rec structures which are
-threaded through the r->prev and r->next
-pointers. The request_rec which is passed to the logging
-handlers in such cases is the one which was originally built for the
-initial request from the client; note that the bytes_sent field will
-only be correct in the last request in the chain (the one for which a
-response was actually sent).
-
--One of the problems of writing and designing a server-pool server is -that of preventing leakage, that is, allocating resources (memory, -open files, etc.), without subsequently releasing them. The resource -pool machinery is designed to make it easy to prevent this from -happening, by allowing resource to be allocated in such a way that -they are automatically released when the server is done with -them. -
--The way this works is as follows: the memory which is allocated, file -opened, etc., to deal with a particular request are tied to a -resource pool which is allocated for the request. The pool -is a data structure which itself tracks the resources in question. -
--When the request has been processed, the pool is cleared. At -that point, all the memory associated with it is released for reuse, -all files associated with it are closed, and any other clean-up -functions which are associated with the pool are run. When this is -over, we can be confident that all the resource tied to the pool have -been released, and that none of them have leaked. -
--Server restarts, and allocation of memory and resources for per-server -configuration, are handled in a similar way. There is a -configuration pool, which keeps track of resources which were -allocated while reading the server configuration files, and handling -the commands therein (for instance, the memory that was allocated for -per-server module configuration, log files and other files that were -opened, and so forth). When the server restarts, and has to reread -the configuration files, the configuration pool is cleared, and so the -memory and file descriptors which were taken up by reading them the -last time are made available for reuse. -
-
-It should be noted that use of the pool machinery isn't generally
-obligatory, except for situations like logging handlers, where you
-really need to register cleanups to make sure that the log file gets
-closed when the server restarts (this is most easily done by using the
-function ap_pfopen, which also
-arranges for the underlying file descriptor to be closed before any
-child processes, such as for CGI scripts, are execed), or
-in case you are using the timeout machinery (which isn't yet even
-documented here). However, there are two benefits to using it:
-resources allocated to a pool never leak (even if you allocate a
-scratch string, and just forget about it); also, for memory
-allocation, ap_palloc is generally faster than
-malloc.
-
-We begin here by describing how memory is allocated to pools, and then -discuss how other resources are tracked by the resource pool -machinery. -
-
-Memory is allocated to pools by calling the function
-ap_palloc, which takes two arguments, one being a pointer to
-a resource pool structure, and the other being the amount of memory to
-allocate (in chars). Within handlers for handling
-requests, the most common way of getting a resource pool structure is
-by looking at the pool slot of the relevant
-request_rec; hence the repeated appearance of the
-following idiom in module code:
-
-int my_handler(request_rec *r)
-{
- struct my_structure *foo;
- ...
-
- foo = (foo *)ap_palloc (r->pool, sizeof(my_structure));
-}
-
-
-Note that there is no ap_pfree ---
-ap_palloced memory is freed only when the associated
-resource pool is cleared. This means that ap_palloc does not
-have to do as much accounting as malloc(); all it does in
-the typical case is to round up the size, bump a pointer, and do a
-range check.
-
-(It also raises the possibility that heavy use of ap_palloc
-could cause a server process to grow excessively large. There are
-two ways to deal with this, which are dealt with below; briefly, you
-can use malloc, and try to be sure that all of the memory
-gets explicitly freed, or you can allocate a sub-pool of
-the main pool, allocate your memory in the sub-pool, and clear it out
-periodically. The latter technique is discussed in the section on
-sub-pools below, and is used in the directory-indexing code, in order
-to avoid excessive storage allocation when listing directories with
-thousands of files).
-
-There are functions which allocate initialized memory, and are
-frequently useful. The function ap_pcalloc has the same
-interface as ap_palloc, but clears out the memory it
-allocates before it returns it. The function ap_pstrdup
-takes a resource pool and a char * as arguments, and
-allocates memory for a copy of the string the pointer points to,
-returning a pointer to the copy. Finally ap_pstrcat is a
-varargs-style function, which takes a pointer to a resource pool, and
-at least two char * arguments, the last of which must be
-NULL. It allocates enough memory to fit copies of each
-of the strings, as a unit; for instance:
-
- ap_pstrcat (r->pool, "foo", "/", "bar", NULL); --
-returns a pointer to 8 bytes worth of memory, initialized to
-"foo/bar".
-
-A pool is really defined by its lifetime more than anything else. There -are some static pools in http_main which are passed to various -non-http_main functions as arguments at opportune times. Here they are: -
--For almost everything folks do, r->pool is the pool to use. But you -can see how other lifetimes, such as pchild, are useful to some -modules... such as modules that need to open a database connection once -per child, and wish to clean it up when the child dies. -
--You can also see how some bugs have manifested themself, such as setting -connection->user to a value from r->pool -- in this case -connection exists -for the lifetime of ptrans, which is longer than r->pool (especially if -r->pool is a subrequest!). So the correct thing to do is to allocate -from connection->pool. -
--And there was another interesting bug in mod_include/mod_cgi. You'll see -in those that they do this test to decide if they should use r->pool -or r->main->pool. In this case the resource that they are registering -for cleanup is a child process. If it were registered in r->pool, -then the code would wait() for the child when the subrequest finishes. -With mod_include this could be any old #include, and the delay can be up -to 3 seconds... and happened quite frequently. Instead the subprocess -is registered in r->main->pool which causes it to be cleaned up when -the entire request is done -- i.e., after the output has been sent to -the client and logging has happened. -
-
-As indicated above, resource pools are also used to track other sorts
-of resources besides memory. The most common are open files. The
-routine which is typically used for this is ap_pfopen, which
-takes a resource pool and two strings as arguments; the strings are
-the same as the typical arguments to fopen, e.g.,
-
- ...
- FILE *f = ap_pfopen (r->pool, r->filename, "r");
-
- if (f == NULL) { ... } else { ... }
-
-
-There is also a ap_popenf routine, which parallels the
-lower-level open system call. Both of these routines
-arrange for the file to be closed when the resource pool in question
-is cleared.
-
-Unlike the case for memory, there are functions to close
-files allocated with ap_pfopen, and ap_popenf,
-namely ap_pfclose and ap_pclosef. (This is
-because, on many systems, the number of files which a single process
-can have open is quite limited). It is important to use these
-functions to close files allocated with ap_pfopen and
-ap_popenf, since to do otherwise could cause fatal errors on
-systems such as Linux, which react badly if the same
-FILE* is closed more than once.
-
-(Using the close functions is not mandatory, since the
-file will eventually be closed regardless, but you should consider it
-in cases where your module is opening, or could open, a lot of files).
-
-More text goes here. Describe the the cleanup primitives in terms of
-which the file stuff is implemented; also, spawn_process.
-
--Pool cleanups live until clear_pool() is called: clear_pool(a) recursively -calls destroy_pool() on all subpools of a; then calls all the cleanups for a; -then releases all the memory for a. destroy_pool(a) calls clear_pool(a) -and then releases the pool structure itself. i.e., clear_pool(a) doesn't -delete a, it just frees up all the resources and you can start using it -again immediately. -
-ap_palloc() and the
-associated primitives may result in undesirably profligate resource
-allocation. You can deal with such a case by creating a
-sub-pool, allocating within the sub-pool rather than the main
-pool, and clearing or destroying the sub-pool, which releases the
-resources which were associated with it. (This really is a
-rare situation; the only case in which it comes up in the standard
-module set is in case of listing directories, and then only with
-very large directories. Unnecessary use of the primitives
-discussed here can hair up your code quite a bit, with very little
-gain).
-
-The primitive for creating a sub-pool is ap_make_sub_pool,
-which takes another pool (the parent pool) as an argument. When the
-main pool is cleared, the sub-pool will be destroyed. The sub-pool
-may also be cleared or destroyed at any time, by calling the functions
-ap_clear_pool and ap_destroy_pool, respectively.
-(The difference is that ap_clear_pool frees resources
-associated with the pool, while ap_destroy_pool also
-deallocates the pool itself. In the former case, you can allocate new
-resources within the pool, and clear it again, and so forth; in the
-latter case, it is simply gone).
-
-One final note --- sub-requests have their own resource pools, which
-are sub-pools of the resource pool for the main request. The polite
-way to reclaim the resources associated with a sub request which you
-have allocated (using the ap_sub_req_... functions)
-is ap_destroy_sub_req, which frees the resource pool.
-Before calling this function, be sure to copy anything that you care
-about which might be allocated in the sub-request's resource pool into
-someplace a little less volatile (for instance, the filename in its
-request_rec structure).
-
-(Again, under most circumstances, you shouldn't feel obliged to call
-this function; only 2K of memory or so are allocated for a typical sub
-request, and it will be freed anyway when the main request pool is
-cleared. It is only when you are allocating many, many sub-requests
-for a single main request that you should seriously consider the
-ap_destroy_... functions).
-
-
-
-However, just giving the modules command tables is not enough to
-divorce them completely from the server core. The server has to
-remember the commands in order to act on them later. That involves
-maintaining data which is private to the modules, and which can be
-either per-server, or per-directory. Most things are per-directory,
-including in particular access control and authorization information,
-but also information on how to determine file types from suffixes,
-which can be modified by AddType and
-DefaultType directives, and so forth. In general, the
-governing philosophy is that anything which can be made
-configurable by directory should be; per-server information is
-generally used in the standard set of modules for information like
-Aliases and Redirects which come into play
-before the request is tied to a particular place in the underlying
-file system.
-
-Another requirement for emulating the NCSA server is being able to
-handle the per-directory configuration files, generally called
-.htaccess files, though even in the NCSA server they can
-contain directives which have nothing at all to do with access
-control. Accordingly, after URI -> filename translation, but before
-performing any other phase, the server walks down the directory
-hierarchy of the underlying filesystem, following the translated
-pathname, to read any .htaccess files which might be
-present. The information which is read in then has to be
-merged with the applicable information from the server's own
-config files (either from the <Directory> sections
-in access.conf, or from defaults in
-srm.conf, which actually behaves for most purposes almost
-exactly like <Directory />).
-
-Finally, after having served a request which involved reading
-.htaccess files, we need to discard the storage allocated
-for handling them. That is solved the same way it is solved wherever
-else similar problems come up, by tying those structures to the
-per-transaction resource pool.
- -
mod_mime.c,
-which defines the file typing handler which emulates the NCSA server's
-behavior of determining file types from suffixes. What we'll be
-looking at, here, is the code which implements the
-AddType and AddEncoding commands. These
-commands can appear in .htaccess files, so they must be
-handled in the module's private per-directory data, which in fact,
-consists of two separate tables for MIME types and
-encoding information, and is declared as follows:
-
-
-typedef struct {
- table *forced_types; /* Additional AddTyped stuff */
- table *encoding_types; /* Added with AddEncoding... */
-} mime_dir_config;
-
-
-When the server is reading a configuration file, or
-<Directory> section, which includes one of the MIME
-module's commands, it needs to create a mime_dir_config
-structure, so those commands have something to act on. It does this
-by invoking the function it finds in the module's `create per-dir
-config slot', with two arguments: the name of the directory to which
-this configuration information applies (or NULL for
-srm.conf), and a pointer to a resource pool in which the
-allocation should happen.
-
-(If we are reading a .htaccess file, that resource pool
-is the per-request resource pool for the request; otherwise it is a
-resource pool which is used for configuration data, and cleared on
-restarts. Either way, it is important for the structure being created
-to vanish when the pool is cleared, by registering a cleanup on the
-pool if necessary).
-
-For the MIME module, the per-dir config creation function just
-ap_pallocs the structure above, and a creates a couple of
-tables to fill it. That looks like this:
-
-
-void *create_mime_dir_config (pool *p, char *dummy)
-{
- mime_dir_config *new =
- (mime_dir_config *) ap_palloc (p, sizeof(mime_dir_config));
-
- new->forced_types = ap_make_table (p, 4);
- new->encoding_types = ap_make_table (p, 4);
-
- return new;
-}
-
-
-Now, suppose we've just read in a .htaccess file. We
-already have the per-directory configuration structure for the next
-directory up in the hierarchy. If the .htaccess file we
-just read in didn't have any AddType or
-AddEncoding commands, its per-directory config structure
-for the MIME module is still valid, and we can just use it.
-Otherwise, we need to merge the two structures somehow. - -To do that, the server invokes the module's per-directory config merge -function, if one is present. That function takes three arguments: -the two structures being merged, and a resource pool in which to -allocate the result. For the MIME module, all that needs to be done -is overlay the tables from the new per-directory config structure with -those from the parent: - -
-void *merge_mime_dir_configs (pool *p, void *parent_dirv, void *subdirv)
-{
- mime_dir_config *parent_dir = (mime_dir_config *)parent_dirv;
- mime_dir_config *subdir = (mime_dir_config *)subdirv;
- mime_dir_config *new =
- (mime_dir_config *)ap_palloc (p, sizeof(mime_dir_config));
-
- new->forced_types = ap_overlay_tables (p, subdir->forced_types,
- parent_dir->forced_types);
- new->encoding_types = ap_overlay_tables (p, subdir->encoding_types,
- parent_dir->encoding_types);
-
- return new;
-}
-
-
-As a note --- if there is no per-directory merge function present, the
-server will just use the subdirectory's configuration info, and ignore
-the parent's. For some modules, that works just fine (e.g., for the
-includes module, whose per-directory configuration information
-consists solely of the state of the XBITHACK), and for
-those modules, you can just not declare one, and leave the
-corresponding structure slot in the module itself NULL.- -
AddType and AddEncoding commands. To find
-commands, the server looks in the module's command table.
-That table contains information on how many arguments the commands
-take, and in what formats, where it is permitted, and so forth. That
-information is sufficient to allow the server to invoke most
-command-handling functions with pre-parsed arguments. Without further
-ado, let's look at the AddType command handler, which
-looks like this (the AddEncoding command looks basically
-the same, and won't be shown here):
-
-
-char *add_type(cmd_parms *cmd, mime_dir_config *m, char *ct, char *ext)
-{
- if (*ext == '.') ++ext;
- ap_table_set (m->forced_types, ext, ct);
- return NULL;
-}
-
-
-This command handler is unusually simple. As you can see, it takes
-four arguments, two of which are pre-parsed arguments, the third being
-the per-directory configuration structure for the module in question,
-and the fourth being a pointer to a cmd_parms structure.
-That structure contains a bunch of arguments which are frequently of
-use to some, but not all, commands, including a resource pool (from
-which memory can be allocated, and to which cleanups should be tied),
-and the (virtual) server being configured, from which the module's
-per-server configuration data can be obtained if required.
-
-Another way in which this particular command handler is unusually
-simple is that there are no error conditions which it can encounter.
-If there were, it could return an error message instead of
-NULL; this causes an error to be printed out on the
-server's stderr, followed by a quick exit, if it is in
-the main config files; for a .htaccess file, the syntax
-error is logged in the server error log (along with an indication of
-where it came from), and the request is bounced with a server error
-response (HTTP error status, code 500).
- -The MIME module's command table has entries for these commands, which -look like this: - -
-command_rec mime_cmds[] = {
-{ "AddType", add_type, NULL, OR_FILEINFO, TAKE2,
- "a mime type followed by a file extension" },
-{ "AddEncoding", add_encoding, NULL, OR_FILEINFO, TAKE2,
- "an encoding (e.g., gzip), followed by a file extension" },
-{ NULL }
-};
-
-
-The entries in these tables are:
-
-(void *) pointer, which is passed in the
- cmd_parms structure to the command handler ---
- this is useful in case many similar commands are handled by the
- same function.
- AllowOverride
- option, and an additional mask bit, RSRC_CONF,
- indicating that the command may appear in the server's own
- config files, but not in any .htaccess
- file.
- TAKE2 indicates two pre-parsed arguments. Other
- options are TAKE1, which indicates one pre-parsed
- argument, FLAG, which indicates that the argument
- should be On or Off, and is passed in
- as a boolean flag, RAW_ARGS, which causes the
- server to give the command the raw, unparsed arguments
- (everything but the command name itself). There is also
- ITERATE, which means that the handler looks the
- same as TAKE1, but that if multiple arguments are
- present, it should be called multiple times, and finally
- ITERATE2, which indicates that the command handler
- looks like a TAKE2, but if more arguments are
- present, then it should be called multiple times, holding the
- first argument constant.
- NULL).
-request_rec's per-directory configuration vector by using
-the ap_get_module_config function.
-
-
-int find_ct(request_rec *r)
-{
- int i;
- char *fn = ap_pstrdup (r->pool, r->filename);
- mime_dir_config *conf = (mime_dir_config *)
- ap_get_module_config(r->per_dir_config, &mime_module);
- char *type;
-
- if (S_ISDIR(r->finfo.st_mode)) {
- r->content_type = DIR_MAGIC_TYPE;
- return OK;
- }
-
- if((i=ap_rind(fn,'.')) < 0) return DECLINED;
- ++i;
-
- if ((type = ap_table_get (conf->encoding_types, &fn[i])))
- {
- r->content_encoding = type;
-
- /* go back to previous extension to try to use it as a type */
-
- fn[i-1] = '\0';
- if((i=ap_rind(fn,'.')) < 0) return OK;
- ++i;
- }
-
- if ((type = ap_table_get (conf->forced_types, &fn[i])))
- {
- r->content_type = type;
- }
-
- return OK;
-}
-
-
-
-
-
-The only substantial difference is that when a command needs to
-configure the per-server private module data, it needs to go to the
-cmd_parms data to get at it. Here's an example, from the
-alias module, which also indicates how a syntax error can be returned
-(note that the per-directory configuration argument to the command
-handler is declared as a dummy, since the module doesn't actually have
-per-directory config data):
-
-
-char *add_redirect(cmd_parms *cmd, void *dummy, char *f, char *url)
-{
- server_rec *s = cmd->server;
- alias_server_conf *conf = (alias_server_conf *)
- ap_get_module_config(s->module_config,&alias_module);
- alias_entry *new = ap_push_array (conf->redirects);
-
- if (!ap_is_url (url)) return "Redirect to non-URL";
-
- new->fake = f; new->real = url;
- return NULL;
-}
-
-
-
diff --git a/docs/manual/developer/modules.html.en b/docs/manual/developer/modules.html.en
deleted file mode 100644
index d2d898f88ff..00000000000
--- a/docs/manual/developer/modules.html.en
+++ /dev/null
@@ -1,239 +0,0 @@
-
-
-
--This is a first attempt at writing the lessons I learned when trying to convert the mod_mmap_static module to Apache 2.0. It's by no means definitive and probably won't even be correct in some ways, but it's a start. -
--These now need to be of type apr_status_t and return a value of that type. Normally the return value will be APR_SUCCESS unless there is some need to signal an error in the cleanup. Be aware that even though you signal an error not all code yet checks and acts upon the error. -
- --These should now be renamed to better signify where they sit in the overall process. So the name gets a small change from mmap_init to mmap_post_config. The arguments passed have undergone a radical change and now look like -
--A lot of the data types have been moved into the APR. This means that some have had a name change, such as the one shown above. The following is a brief list of some of the changes that you are likely to have to make. -
-The new architecture uses a series of hooks to provide for calling your functions. These you'll need to add to your module by way of a new function, static void register_hooks(void). The function is really reasonably straightforward once you understand what needs to be done. Each function that needs calling at some stage in the processing of a request needs to be registered, handlers do not. There are a number of phases where functions can be added, and for each you can specify with a high degree of control the relative order that the function will be called in. -
--This is the code that was added to mod_mmap_static: -
-
-static void register_hooks(void)
-{
- static const char * const aszPre[]={ "http_core.c",NULL };
- ap_hook_post_config(mmap_post_config,NULL,NULL,HOOK_MIDDLE);
- ap_hook_translate_name(mmap_static_xlat,aszPre,NULL,HOOK_LAST);
-};
-
--This registers 2 functions that need to be called, one in the post_config stage (virtually every module will need this one) and one for the translate_name phase. note that while there are different function names the format of each is identical. So what is the format? -
--ap_hook_[phase_name](function_name, predecessors, successors, position); -
--There are 3 hook positions defined... -
--To define the position you use the position and then modify it with the predecessors and successors. each of the modifiers can be a list of functions that should be called, either before the function is run (predecessors) or after the function has run (successors). -
--In the mod_mmap_static case I didn't care about the post_config stage, but the mmap_static_xlat MUST be called after the core module had done it's name translation, hence the use of the aszPre to define a modifier to the position HOOK_LAST. -
--There are now a lot fewer stages to worry about when creating your module definition. The old defintion looked like -
-
-module MODULE_VAR_EXPORT [module_name]_module =
-{
- STANDARD_MODULE_STUFF,
- /* initializer */
- /* dir config creater */
- /* dir merger --- default is to override */
- /* server config */
- /* merge server config */
- /* command handlers */
- /* handlers */
- /* filename translation */
- /* check_user_id */
- /* check auth */
- /* check access */
- /* type_checker */
- /* fixups */
- /* logger */
- /* header parser */
- /* child_init */
- /* child_exit */
- /* post read-request */
-};
-
--The new structure is a great deal simpler... -
-
-module MODULE_VAR_EXPORT [module_name]_module =
-{
- STANDARD20_MODULE_STUFF,
- /* create per-directory config structures */
- /* merge per-directory config structures */
- /* create per-server config structures */
- /* merge per-server config structures */
- /* command handlers */
- /* handlers */
- /* register hooks */
- };
-
--Some of these read directly across, some don't. I'll try to summarise what should be done below. -
--The stages that read directly across : -
--The remainder of the old functions should be registered as hooks. There are the following hook stages defined so far... -
- -- - -- - diff --git a/docs/manual/filter.html.en b/docs/manual/filter.html.en deleted file mode 100644 index c62b4315b0f..00000000000 --- a/docs/manual/filter.html.en +++ /dev/null @@ -1,58 +0,0 @@ - - - -- -- --Apache 1.3
- -Originally written by
-Dynamic Shared Object (DSO)
-Support -
-Ralf S. Engelschall <rse@apache.org>, April 1998 - -Background
- -On modern Unix derivatives there exists a nifty mechanism usually called -dynamic linking/loading of Dynamic Shared Objects (DSO) which -provides a way to build a piece of program code in a special format for -loading it at run-time into the address space of an executable program. - -
This loading can usually be done in two ways: Automatically by a system -program called
ld.sowhen an executable program is started or -manually from within the executing program via a programmatic system interface -to the Unix loader through the system callsdlopen()/dlsym(). - -In the first way the DSO's are usually called shared libraries or -DSO libraries and named
libfoo.soor -libfoo.so.1.2. They reside in a system directory (usually -/usr/lib) and the link to the executable program is established -at build-time by specifying-lfooto the linker command. This -hard-codes library references into the executable program file so that at -start-time the Unix loader is able to locatelibfoo.soin -/usr/lib, in paths hard-coded via linker-options like --Ror in paths configured via the environment variable -LD_LIBRARY_PATH. It then resolves any (yet unresolved) symbols in -the executable program which are available in the DSO. - -Symbols in the executable program are usually not referenced by the DSO -(because it's a reusable library of general code) and hence no further -resolving has to be done. The executable program has no need to do anything on -its own to use the symbols from the DSO because the complete resolving is done -by the Unix loader. (In fact, the code to invoke
ld.sois part of -the run-time startup code which is linked into every executable program which -has been bound non-static). The advantage of dynamic loading of common library -code is obvious: the library code needs to be stored only once, in a system -library likelibc.so, saving disk space for every program. - -In the second way the DSO's are usually called shared objects or -DSO files and can be named with an arbitrary extension (although the -canonical name is
foo.so). These files usually stay inside a -program-specific directory and there is no automatically established link to -the executable program where they are used. Instead the executable program -manually loads the DSO at run-time into its address space via -dlopen(). At this time no resolving of symbols from the DSO for -the executable program is done. But instead the Unix loader automatically -resolves any (yet unresolved) symbols in the DSO from the set of symbols -exported by the executable program and its already loaded DSO libraries -(especially all symbols from the ubiquitouslibc.so). This way -the DSO gets knowledge of the executable program's symbol set as if it had -been statically linked with it in the first place. - -Finally, to take advantage of the DSO's API the executable program has to -resolve particular symbols from the DSO via
dlsym()for later use -inside dispatch tables etc. In other words: The executable program has to -manually resolve every symbol it needs to be able to use it. The advantage of -such a mechanism is that optional program parts need not be loaded (and thus -do not spend memory) until they are needed by the program in question. When -required, these program parts can be loaded dynamically to extend the base -program's functionality. - -Although this DSO mechanism sounds straightforward there is at least one -difficult step here: The resolving of symbols from the executable program for -the DSO when using a DSO to extend a program (the second way). Why? Because -"reverse resolving" DSO symbols from the executable program's symbol set is -against the library design (where the library has no knowledge about the -programs it is used by) and is neither available under all platforms nor -standardized. In practice the executable program's global symbols are often -not re-exported and thus not available for use in a DSO. Finding a way to -force the linker to export all global symbols is the main problem one has to -solve when using DSO for extending a program at run-time. - -
Practical Usage
- -The shared library approach is the typical one, because it is what the DSO -mechanism was designed for, hence it is used for nearly all types of libraries -the operating system provides. On the other hand using shared objects for -extending a program is not used by a lot of programs. - -
As of 1998 there are only a few software packages available which use the -DSO mechanism to actually extend their functionality at run-time: Perl 5 (via -its XS mechanism and the DynaLoader module), Netscape Server, etc. Starting -with version 1.3, Apache joined the crew, because Apache already uses a module -concept to extend its functionality and internally uses a dispatch-list-based -approach to link external modules into the Apache core functionality. So, -Apache is really predestined for using DSO to load its modules at run-time. - -
As of Apache 1.3, the configuration system supports two optional features -for taking advantage of the modular DSO approach: compilation of the Apache -core program into a DSO library for shared usage and compilation of the -Apache modules into DSO files for explicit loading at run-time. - -
Implementation
- -The DSO support for loading individual Apache modules is based on a module -named
mod_so.cwhich has to be -statically compiled into the Apache core. It is the only module besides -http_core.cwhich cannot be put into a DSO itself -(bootstrapping!). Practically all other distributed Apache modules then can -then be placed into a DSO by individually enabling the DSO build for them via -configure's--enable-sharedoption (see top-level -INSTALLfile) or by changing theAddModulecommand -in yoursrc/Configurationinto aSharedModule-command (seesrc/INSTALLfile). After a module is compiled into -a DSO namedmod_foo.soyou can usemod_so'sLoadModulecommand in your -httpd.conffile to load this module at server startup or restart. - -To simplify this creation of DSO files for Apache modules -(especially for third-party modules) a new support program named apxs (APache eXtenSion) is -available. It can be used to build DSO based modules outside -of the Apache source tree. The idea is simple: When installing -Apache the
configure'smake install-procedure installs the Apache C header files and puts the -platform-dependent compiler and linker flags for building DSO files -into theapxsprogram. This way the user can use -apxsto compile his Apache module sources without the -Apache distribution source tree and without having to fiddle with the -platform-dependent compiler and linker flags for DSO support. - -To place the complete Apache core program into a DSO library (only required -on some of the supported platforms to force the linker to export the apache -core symbols -- a prerequisite for the DSO modularization) the rule -
SHARED_COREhas to be enabled viaconfigure's ---enable-rule=SHARED_COREoption (see top-level -INSTALLfile) or by changing theRulecommand in -yourConfigurationfile toRule SHARED_CORE=yes(see -src/INSTALLfile). The Apache core code is then placed into a DSO -library namedlibhttpd.so. Because one cannot link a DSO against -static libraries on all platforms, an additional executable program named -libhttpd.epis created which both binds this static code and -provides a stub for themain()function. Finally the -httpdexecutable program itself is replaced by a bootstrapping -code which automatically makes sure the Unix loader is able to load and start -libhttpd.epby providing theLD_LIBRARY_PATHto -libhttpd.so. - -Supported Platforms
- -Apache's
src/Configurescript currently has only limited but -adequate built-in knowledge on how to compile DSO files, because as already -mentioned this is heavily platform-dependent. Nevertheless all major Unix -platforms are supported. The definitive current state (May 1999) is this: - --
-
- -- Out-of-the-box supported platforms:
-(actually tested versions in parenthesis) - --o FreeBSD (2.1.5, 2.2.x, 3.x, 4.x) -o OpenBSD (2.x) -o NetBSD (1.3.1) -o BSDI (3.x, 4.x) -o Linux (Debian/1.3.1, RedHat/4.2) -o Solaris (2.4, 2.5, 2.6, 2.7) -o SunOS (4.1.3) -o Digital UNIX (4.0) -o IRIX (5.3, 6.2) -o HP/UX (10.20) -o UnixWare (2.01, 2.1.2) -o SCO (5.0.4) -o AIX (3.2, 4.1.5, 4.2, 4.3) -o ReliantUNIX/SINIX (5.43) -o SVR4 (-) -o Mac OS X Server (1.0) -o Mac OS (10.0 preview 1) -o OpenStep/Mach (4.2) -o DGUX (??) -o NetWare (5.1) -- --
- Explicitly unsupported platforms: - -
-o Ultrix (no dlopen-style interface under this platform) -- -Usage Summary
- -To give you an overview of the DSO features of Apache 1.3, here is a short -and concise summary: - -
- -
- -- Placing the Apache core code (all the stuff which usually forms the -
httpdbinary) into a DSOlibhttpd.so, an executable -programlibhttpd.epand a bootstrapping executable program -httpd(Notice: this is only required on some of the supported -platforms to force the linker to export the Apache core symbols, which in turn -is a prerequisite for the DSO modularization): - --
-
- -- Build and install via
configure(preferred): -- -
- -$ ./configure --prefix=/path/to/install - --enable-rule=SHARED_CORE ... -$ make install --- Build and install manually: -
-
- -- Edit src/Configuration: - << Rule SHARED_CORE=default - >> Rule SHARED_CORE=yes - << EXTRA_CFLAGS= - >> EXTRA_CFLAGS= -DSHARED_CORE_DIR=\"/path/to/install/modules\" -$ make -$ cp src/libhttpd.so* /path/to/install/modules/ -$ cp src/libhttpd.ep /path/to/install/modules/ -$ cp src/httpd /path/to/install/bin/ --- Build and install a distributed Apache module, say -
mod_foo.c, into its own DSOmod_foo.so: - --
-
- -- Build and install via
configure(preferred): -- -
- -$ ./configure --prefix=/path/to/install - --enable-shared=foo -$ make install --- Build and install manually: -
-
- -- Edit src/Configuration: - << AddModule modules/xxxx/mod_foo.o - >> SharedModule modules/xxxx/mod_foo.so -$ make -$ cp src/xxxx/mod_foo.so /path/to/install/modules -- Edit /path/to/install/etc/httpd.conf - >> LoadModule foo_module /path/to/install/modules/mod_foo.so --- Build and install a third-party Apache module, say -
mod_foo.c, into its own DSOmod_foo.so- --
-
- -- Build and install via
configure(preferred): -- -
- -$ ./configure --add-module=/path/to/3rdparty/mod_foo.c - --enable-shared=foo -$ make install --- Build and install manually: -
-
- -$ cp /path/to/3rdparty/mod_foo.c /path/to/apache-1.3/src/modules/extra/ -- Edit src/Configuration: - >> SharedModule modules/extra/mod_foo.so -$ make -$ cp src/xxxx/mod_foo.so /path/to/install/modules -- Edit /path/to/install/etc/httpd.conf - >> LoadModule foo_module /path/to/install/modules/mod_foo.so ---
- Build and install a third-party Apache module, say -
mod_foo.c, into its own DSOmod_foo.sooutside -of the Apache source tree: - --
-
- -- Build and install via apxs: -
-
- -$ cd /path/to/3rdparty -$ apxs -c mod_foo.c -$ apxs -i -a -n foo mod_foo.so --Advantages & Disadvantages
- -The above DSO based features of Apache 1.3 have the following advantages: - -
-
- -- The server package is more flexible at run-time because the actual server - process can be assembled at run-time via
LoadModule-httpd.confconfiguration commands instead of -ConfigurationAddModulecommands at build-time. - For instance this way one is able to run different server instances - (standard & SSL version, minimalistic & powered up version - [mod_perl, PHP3], etc.) with only one Apache installation. --
- The server package can be easily extended with third-party modules even - after installation. This is at least a great benefit for vendor package - maintainers who can create a Apache core package and additional packages - containing extensions like PHP3, mod_perl, mod_fastcgi, etc. -
-
- Easier Apache module prototyping because with the DSO/
apxs- pair you can both work outside the Apache source tree and only need an -apxs -icommand followed by anapachectl - restartto bring a new version of your currently developed module - into the running Apache server. -DSO has the following disadvantages: - -
-
- - -- The DSO mechanism cannot be used on every platform because not all - operating systems support dynamic loading of code into the address space - of a program. -
-
- The server is approximately 20% slower at startup time because of the - symbol resolving overhead the Unix loader now has to do. -
-
- The server is approximately 5% slower at execution time under some - platforms because position independent code (PIC) sometimes needs - complicated assembler tricks for relative addressing which are not - necessarily as fast as absolute addressing. -
-
- Because DSO modules cannot be linked against other DSO-based libraries - (
ld -lfoo) on all platforms (for instance a.out-based - platforms usually don't provide this functionality while ELF-based - platforms do) you cannot use the DSO mechanism for all types of modules. - Or in other words, modules compiled as DSO files are restricted to only - use symbols from the Apache core, from the C library (libc) - and all other dynamic or static libraries used by the Apache core, or - from static library archives (libfoo.a) containing position - independent code. The only chances to use other code is to either make - sure the Apache core itself already contains a reference to it, loading - the code yourself viadlopen()or enabling the -SHARED_CHAINrule while building Apache when your platform - supports linking DSO files against DSO libraries. --
- Under some platforms (many SVR4 systems) there is no way to force the - linker to export all global symbols for use in DSO's when linking the - Apache httpd executable program. But without the visibility of the Apache - core symbols no standard Apache module could be used as a DSO. The only - chance here is to use the
SHARED_COREfeature because this - way the global symbols are forced to be exported. As a consequence the - Apachesrc/Configurescript automatically enforces -SHARED_COREon these platforms when DSO features are used in - theConfigurationfile or on the configure command line. -
|
-Related Modules - -mod_ext_filter -mod_include - |
-
-Related Directives - -ExtFilterDefine -ExtFilterOptions -SetInputFilter -SetOutputFilter - |
-
A filter is a process which is applied to data that is -sent or received by the server. Data sent by clients to the server -is processed by input filters while data sent by the -server to the client is processed by output filters. -Multiple filters can be applied to the data, and the order -of the filters can be explicitly specified.
- -Filters are used internally by Apache to perform functions such as
-chunking and byte-range request handling. In addition, modules can
-provide filters which are selectable using run-time configuration
-directives. The set of filters which apply to data can be manipulated
-with the SetInputFilter and SetOutputFilter
-directives.
The only configurable filter currently included with the Apache
-distribution is the INCLUDES filter which is provided by
-mod_include to process output for
-Server Side Includes. There is also an experimental module called mod_ext_filter which allows for
-external programs to be defined as filters.
This document covers compilation and installation of Apache on Unix -and Unix-like systems only. For compiling and installation on Windows, -see Using Apache with Microsoft -Windows. For other platforms, see the platform documentation.
- -Apache 2.0's configuration and installation environment has changed -completely from Apache 1.3. Apache 1.3 used a custom set of scripts -to achieve easy installation. Apache 2.0 now uses libtool and -autoconf to create an environment that looks like many other Open -Source projects.
- -| Download | -$ lynx http://www.apache.org/dist/httpd/httpd-2_0_NN.tar.gz
- |
| Extract | -$ gzip -d httpd-2_0_NN.tar.gz |
| Configure | -$ ./configure --prefix=PREFIX
- |
| Compile | -$ make
- |
| Install | -$ make install
- |
| Customize | -$ vi PREFIX/conf/httpd.conf
- |
| Test | -$ PREFIX/bin/apachectl start
- |
NN must be replaced with the current minor version number,
-and PREFIX must be replaced with the filesystem path under
-which the server should be installed. If PREFIX is not
-specified, it defaults to /usr/local/apache2.
Each section of the compilation and installation process is -described in more detail below, beginning with the requirements -for compiling and installing Apache HTTPD.
- -The following requirements exist for building Apache:
- -PATH must contain basic
-build tools such as make.Apache can be downloaded from the Apache Software Foundation -download site or from a nearby mirror.
- -Version numbers that end in alpha indicate early
-pre-test versions which may or may not work. Version numbers ending
-in beta indicate more reliable releases that still
-require further testing or bug fixing. If you wish to download the
-best available production release of the Apache HTTP Server, you
-should choose the latest version with neither alpha nor
-beta in its filename.
After downloading, especially if a mirror site is used, it is
-important to verify that you have a complete and unmodified version of
-the Apache HTTP Server. This can be accomplished by testing the
-downloaded tarball against the PGP signature. This, in turn, is a two
-step procedure. First, you must obtain the KEYS file
-from the Apache distribution
-site. (To assure that the KEYS file itself has not
-been modified, it may be a good idea to use a file from a previous
-distribution of Apache or import the keys from a public key server.)
-The keys are imported into your personal key ring using
-one of the following commands (depending on your pgp version):
-$ pgp < KEYS
-
-or
-
-$ gpg --import KEYS
-
-
-The next step is to test the tarball against the PGP signature,
-which should always be obtained from the main Apache website. The
-signature file has a filename identical to the source tarball with the
-addition of .asc. Then you can check the distribution
-with one of the following commands (again, depending on your pgp
-version):
-$ pgp httpd-2_0_NN.tar.gz.asc
-
-or
-
-$ gpg --verify httpd-2_0_NN.tar.gz.asc
-You should receive a message like
-
-Good signature from user "Martin Kraemer <martin@apache.org>".
-
-Depending on the trust relationships contained
-in your key ring, you may also receive a message saying that
-the relationship between the key and the signer of the key
-cannot be verified. This is not a problem if you trust the
-authenticity of the KEYS file.
Extracting the source from the Apache HTTPD tarball is a simple -matter of uncompressing, and then untarring:
- -
-$ gzip -d httpd-2_0_NN.tar.gz
-$ tar xvf httpd-2_0_NN.tar
-
-
-This will create a new directory under the current directory
-containing the source code for the distribution. You should
-cd into that directory before proceeding with
-compiling the server.
The next step is to configure the Apache source tree for your
-particular platform and personal requirements. This is done using the
-script configure included in the root directory of the
-distribution. (Developers downloading the CVS version of the Apache
-source tree will need to have autoconf and
-libtool installed and will need to run
-buildconf before proceeding with the next steps. This is
-not necessary for official releases.)
To configure the source tree using all the default options, simply
-type ./configure. To change the default options,
-configure accepts a variety of variables and command line
-options. Environment variables are generally placed before the
-./configure command, while other options are placed
-after. The most important option here is the location prefix where
-Apache is to be installed later, because Apache has to be configured
-for this location to work correctly. But there are a lot of other
-options available for your pleasure.
For a short impression of what possibilities you have, here is a -typical example which compiles Apache for the installation tree -/sw/pkg/apache with a particular compiler and flags plus the two -additional modules mod_rewrite and mod_speling for later loading -through the DSO mechanism:
- -
- $ CC="pgcc" CFLAGS="-O2" \
- ./configure --prefix=/sw/pkg/apache \
- --enable-rewrite=shared \
- --enable-speling=shared
-
-
-When configure is run it will take several minutes to test for -the availability of features on your system and build Makefiles -which will later be used to compile the server.
- -The easiest way to find all of the configuration flags for Apache -is to run ./configure --help. What follows is a brief description -of most of the arguments and environment variables.
- -The autoconf build process uses several environment variables to
-configure the build environment. In general, these variables change
-the method used to build Apache, but not the eventual features of the
-server. These variables can be placed in the environment before
-invoking configure, but it is usually easier to specify
-them on the configure command line as demonstrated
-in the example above.
CC=...CPPFLAGS=...CFLAGS=...LDFLAGS=...LIBS=...INCLUDES=...TARGET=... [Default: apache]NOTEST_CPPFLAGS=...NOTEST_CFLAGS=...NOTEST_LDFLAGS=...NOTEST_LIBS=...SHLIB_PATH=...--help--quiet--verboseThere are currently two ways to configure the pathnames under -which Apache will install its files. First, you can specify -a directory and have Apache install itself under that directory -in its default locations.
- ---prefix=PREFIX [Default:
-/usr/local/apache2]It is possible to specify that architecture-dependent files should -be placed under a different directory.
- ---exec-prefix=EPREFIX [Default:
-PREFIX]The second, and more flexible way to configure the install path
-locations for Apache is using the config.layout file.
-Using this method, it is possible to separately specify the location
-for each type of file within the Apache installation. The
-config.layout file contains several example
-configurations, and you can also create your own custom configuration
-following the examples. The different layouts in this file are
-grouped into <Layout FOO>...</Layout>
-sections and referred to by name as in FOO.
--enable-layout=LAYOUTconfig.layout file
-to specify the installation paths.Presently it is not possible to mix the
---enable-layout and --prefix options. Nor
-is it possible to individually specify detailed pathnames on the
-configure command line. If you want just a basic
-install, you can simply use the --prefix option on its
-own. If you want to customize your install, you should edit the
-config.layout file and use the
---enable-layout option.
Apache is a modular server. Only the most basic functionality is -included in the core server. Extended features are available in -various modules. During the configuration process, you must select -which modules to compile for use with your server. You can view a list of modules included in the -documentation. Those modules with a status -of "Base" are included by default and must be specifically disabled if -you do not want them. Modules with any other status must be -specifically enabled if you wish to use them.
- -There are two ways for a module to be compiled and used with
-Apache. Modules may be statically compiled, which means that
-they are permanently included in the Apache binary. Alternatively, if
-your operating system supports Dynamic Shared Objects (DSOs) and
-autoconf can detect that support, then modules may be dynamically
-compiled. DSO modules are stored separately from the Apache
-binary, and may be included or excluded from the server using the
-run-time configuration directives provided by mod_so. The mod_so is automatically
-included in the server if any dynamic modules are included in the
-compilation. If you would like to make your server capable of loading
-DSOs without actually compiling any dynamic modules, you can
-explicitly --enable-so.
--enable-MODULE[=shared]=shared.--disable-MODULE--enable-modules=MODULE-LIST --enable-mods-shared=MODULE-LIST The MODULE-LIST in the --enable-modules and
---enable-mods-shared options is usually a space-separated list
-of module identifiers. For example, to enable mod_dav and mod_info, you
-can either use
-./configure --enable-dav --enable-info
-
-or, equivalently,
-
-./configure --enable-modules="dav info"
-
-In addition, the special keywords all
-or most can be used to add all or most of the modules
-in one step. You can then remove any modules that you do not want
-with the --disable-MODULE option. For example,
-to include all modules as DSOs with the exception of mod_info, you can use
-./configure --enable-mods-shared=all --disable-info
-
-
-In addition to the standard set of modules, Apache 2.0 also
-includes a choice of Multi-Processing Modules
-(MPMs). One, and only one MPM must be included in the compilation
-process. The default MPMs for each platform are listed on the MPM documentation page, but can be overridden
-on the configure command line.
-
-
--with-mpm=NAMEApache includes a support program called suexec which can be used to isolate user CGI -programs. However, if suexec is improperly configured, it can cause -serious security problems. Therefore, you should carefully read and -consider the suexec documentation before -implementing this feature.
- - -Now you can build the various parts which form the Apache package -by simply running the command:
- -
- $ make
-
-
-Please be patient here, since a base configuration takes -approximately 3 minutes to compile under a Pentium III/Linux 2.2 -system, but this will vary widely depending on your hardware and the -number of modules which you have enabled.
- - -Now its time to install the package under the configured
-installation PREFIX (see --prefix option above)
-by running:
$ make install
-
-
-If you are upgrading, the installation will not overwrite -your configuration files or documents.
- - -Next, you can customize your Apache HTTP server by editing the configuration files under -PREFIX/conf/.
- -
-$ vi PREFIX/conf/httpd.conf
-
-
-Have a look at the Apache manual under docs/manual/ or http://httpd.apache.org/docs/ -for a complete reference of available configuration directives.
- -Now you can start your Apache HTTP -server by immediately running:
- -
- $ PREFIX/bin/apachectl start
-
-
-and then you should be able to request your first document via URL
-http://localhost/. The web page you see is located under the DocumentRoot which will usually
-be PREFIX/htdocs/. Then stop the server again by running:
$ PREFIX/bin/apachectl stop
-
-
-
-
-
-
diff --git a/docs/manual/invoking.html.en b/docs/manual/invoking.html.en
deleted file mode 100644
index 9f42048c627..00000000000
--- a/docs/manual/invoking.html.en
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-
-On Windows, Apache is normally run as a service on Windows NT, or -as a console application on Windows 95. For details, see running Apache for Windows.
- -On Unix, the httpd program is run -as a daemon which executes continuously in the background to handle -requests.
- -If the Port specified in the
-configuration file is the default of 80 (or any other port below
-1024), then it is necessary to have root privileges in order to start
-apache, so that it can bind to this privileged port. Once the server
-has started and performed a few preliminary activities such as opening
-its log files, it will launch several child processes which
-do the work of listening for and answering requests from clients. The
-main httpd process continues to run as the root user, but
-the child processes run as a less privileged user. This is controlled
-by the selected Multi-Processing Module.
The first thing that httpd does when it is invoked is
-to locate and read the configuration
-file httpd.conf. The location of this file is set at
-compile-time, but it is possible to specify its location at run time
-using the -f command-line option as in
/usr/local/apache/bin/httpd -f
-/usr/local/apache/conf/httpd.conf
-
-As an alternative to invoking the httpd binary
-directly, a shell script called apachectl is provided which can be
-used to control the daemon process with simple commands such as
-apachectl start and apachectl stop.
If all goes well during startup, the server will detach from the -terminal and the command prompt will return almost immediately. -This indicates that the server is up and running. You can then -use your browser to connect to the server and view the test -page in the DocumentRoot -directory and the local copy of the documentation linked from -that page.
- -If Apache suffers a fatal problem during startup, it will write a
-message describing the problem either to the console or to the ErrorLog before exiting. One of the
-most common error messages is "Unable to bind to Port
-...". This message is usually caused by either:
For further trouble-shooting instructions, consult the Apache FAQ.
- -If you want your server to continue running after a system reboot,
-you should add a call to httpd or apachectl
-to your system startup files (typically rc.local or a
-file in an rc.N directory). This will start Apache as
-root. Before doing this ensure that your server is properly configured
-for security and access restrictions. The apachectl
-script is designed so that it can often be linked directly as an init
-script, but be sure to check the exact requirements of your system.
Additional information about the command-line options of httpd and apachectl as well as other support -programs included with the server is available on the Server and Supporting Programs page. There is -also documentation on all the modules included with -the Apache distribution and the directives that they provide.
- - - - - diff --git a/docs/manual/mod/directive-dict.html.en b/docs/manual/mod/directive-dict.html.en deleted file mode 100644 index 8b2f6679fb7..00000000000 --- a/docs/manual/mod/directive-dict.html.en +++ /dev/null @@ -1,283 +0,0 @@ - - - -- Each Apache configuration directive is described using a common format - that looks like this: -
-- Each of the directive's attributes, complete with possible values - where possible, are described in this document. -
- -- This indicates the format of the directive as it would appear in a - configuration file. This syntax is extremely directive-specific, - and is described in detail in the directive's definition. - Generally, the directive name is followed by a series of one or - more arguments. Optional arguments are enclosed in square brackets. - Where an argument can take on more than one possible value, possible - values are separated by a vertical bar. Literal text is presented - in the default font, while argument-types for which substitution - is necessary are emphasized. Directives which can take a variable - number of arguments will end in "..." indicating that the last - argument is repeated. -
- -- If the directive has a default value (i.e., if you omit it - from your configuration entirely, the Apache Web server will behave as - though you set it to a particular value), it is described here. If - there is no default value, this section should say - "None". -
- -- This indicates where in the server's configuration files the directive - is legal. It's a comma-separated list of one or more of the following - values: -
--
--
--
--
-- The directive is only allowed within the designated context; - if you try to use it elsewhere, you'll get a configuration error that - will either prevent the server from handling requests in that context - correctly, or will keep the server from operating at all -- - i.e., the server won't even start. -
-- The valid locations for the directive are actually the result of a - Boolean OR of all of the listed contexts. In other words, a directive - that is marked as being valid in "server config, - .htaccess" can be used in the httpd.conf file - and in .htaccess files, but not within any - <Directory> or <VirtualHost> containers. -
- -- This directive attribute indicates which configuration override must - be active in order for the directive to be processed when it appears - in a .htaccess file. If the directive's - context - doesn't permit it to appear in .htaccess files, this - attribute should say "Not applicable". -
-- Overrides are activated by the - AllowOverride - directive, and apply to a particular scope (such as a directory) and - all descendants, unless further modified by other - AllowOverride directives at lower levels. The - documentation for that directive also lists the possible override - names available. -
- -- This indicates how tightly bound into the Apache Web server the - directive is; in other words, you may need to recompile the server - with an enhanced set of modules in order to gain access to the - directive and its functionality. Possible values for this attribute - are: -
--
--
--
--
--
-- This quite simply lists the name of the source module which defines - the directive. -
- -- If the directive wasn't part of the original Apache version 1 - distribution, the version in which it was introduced should be listed - here. If the directive has the same name as one from the NCSA HTTPd - server, any inconsistencies in behaviour between the two should also - be mentioned. Otherwise, this attribute should say "No - compatibility issues." -
- - - diff --git a/docs/manual/mod/module-dict.html.en b/docs/manual/mod/module-dict.html.en deleted file mode 100644 index 7d99828e817..00000000000 --- a/docs/manual/mod/module-dict.html.en +++ /dev/null @@ -1,144 +0,0 @@ - - - -- Each Apache module is described using a common format that looks - like this: -
-- Each of the attributes, complete with values where possible, are - described in this document. -
- -- This indicates how tightly bound into the Apache Web server the - module is; in other words, you may need to recompile the server in - order to gain access to the module and its functionality. Possible - values for this attribute are: -
--
--
--
--
--
-
- This quite simply lists the name of the source file which contains
- the code for the module. This is also the name used by the <IfModule>
- directive.
-
- This is a string which identifies the module for use in the LoadModule directive when - dynamically loading modules. In particular, it is the name - of the external variable of type module in the source file. -
- -- If the module was not part of the original Apache version 2 - distribution, the version in which it was introduced should be listed - here. -
- - - diff --git a/docs/manual/mpm.html.en b/docs/manual/mpm.html.en deleted file mode 100644 index 6e9ada16503..00000000000 --- a/docs/manual/mpm.html.en +++ /dev/null @@ -1,90 +0,0 @@ - - - -The Apache HTTP Server is designed to be a powerful and flexible -web server that can work on a very wide variety of platforms in a -range of different environments. Different platforms and different -environments often require different features, or may have different -ways of implementing the same feature most efficiently. Apache has -always accommodated a wide variety of environments through its modular -design. This design allows the webmaster to choose which features -will be included in the server by selecting which modules to load -either at compile-time or at run-time.
- -Apache 2.0 extends this modular design to the most basic functions -of a web server. The server ships with a selection of -Multi-Processing Modules (MPMs) which are responsible for binding to -network ports on the machine, accepting requests, and dispatching -children to handle the requests.
- -Extending the modular design to this level of the server -allows two important benefits: -
At the user level, MPMs appear much like other Apache modules. -The main difference is that one and only one MPM must be loaded -into the server at any time. The list of available MPMs -appears on the module index page.
- -MPMs must be chosen during configuration, and compiled into the server. -Compilers are capable of optimizing a lot of functions if threads are used, -but only if they know that threads are being used. Because some MPMs use -threads on Unix and others don't, Apache will always perform better if the -MPM is chosen at configuration time and built into Apache.
- -To actually choose the desired MPM, use the argument --with-mpm= -NAME with the ./configure script. NAME is the name of -the desired MPM.
- -Once the server has been compiled, it is possible to determine which
-MPM was chosen by using ./httpd -l. This command will list
-every module that is compiled into the server, including the MPM.
Enhancements: Core | Module - -
The sections <Directory>, <Location> and <Files> can contain
-directives which only apply to specified directories, URLs or files
-respectively. Also htaccess files can be used inside a directory to
-apply directives to that directory. This document explains how these
-different sections differ and how they relate to each other when
-Apache decides which directives apply for a particular directory or
-request URL.
Everything that is syntactically allowed in
-<Directory> is also allowed in
-<Location> (except a sub-<Files>
-section). Semantically, however some things, most
-notably AllowOverride and the two options
-FollowSymLinks and SymLinksIfOwnerMatch,
-make no sense in <Location>,
-<LocationMatch> or <DirectoryMatch>.
-The same for <Files> -- syntactically everything
-is fine, but semantically some things are different.
The order of merging is:
- -<Directory> (except regular expressions) and
- .htaccess done simultaneously (with .htaccess, if allowed, overriding
- <Directory>)
-
-<DirectoryMatch>, and
- <Directory> with regular expressions
-
-<Files> and <FilesMatch> done
- simultaneously
- <Location> and <LocationMatch> done
- simultaneously
- Apart from <Directory>, each group is processed in
-the order that they appear in the configuration
-files. <Directory> (group 1 above) is processed in
-the order shortest directory component to longest. If multiple
-<Directory> sections apply to the same directory
-they they are processed in the configuration file order. The
-configuration files are read in the order httpd.conf, srm.conf and
-access.conf. Configurations included via the Include
-directive will be treated as if they were inside the including file
-at the location of the Include directive.
Sections inside <VirtualHost> sections are applied
-after the corresponding sections outside the virtual host
-definition. This allows virtual hosts to override the main server
-configuration.
Later sections override earlier ones.
- -The general guidelines are:
- -<Directory> and/or
- <Files>.
-<Location>
-But a notable exception is:
- -<Directory>. This is
- a legacy mistake because the proxy existed prior to
- <Location>. A future version of the config
- language should probably switch this to
- <Location>.
-Note about .htaccess parsing:
- -<Location> and symbolic links:
Options FollowSymLinks"
- or "Options SymLinksIfOwnerMatch" inside a
- <Location>, <LocationMatch>
- or <DirectoryMatch> section
- (the options are simply ignored).
- Using the options in question is only possible inside a
- <Directory> section (or a .htaccess file).
-<Files> and Options:
Options
- directive inside a <Files> section has no effect.
-Another note:
- -<Location>/<LocationMatch>
- sequence performed just before the name translation phase (where
- Aliases and DocumentRoots are used to
- map URLs to filenames). The results of this sequence are
- completely thrown away after the translation has completed.
-This document covers stopping and restarting Apache on Unix-like -systems. Windows users should see Signalling Apache when -running.
- -You will notice many httpd executables running on your system,
-but you should not send signals to any of them except the parent, whose
-pid is in the PidFile. That is to
-say you shouldn't ever need to send signals to any process except the
-parent. There are three signals that you can send the parent:
-TERM, HUP, and USR1, which will
-be described in a moment.
-
-
To send a signal to the parent you should issue a command such as: -
- -You can read about its progress by issuing: - -- kill -TERM `cat /usr/local/apache/logs/httpd.pid` -
- -Modify those examples to match your -ServerRoot and -PidFile settings. - -- tail -f /usr/local/apache/logs/error_log -
A shell script called apachectl is provided which -automates the processing of signalling Apache. For details about this -script, see the documentation on starting -Apache.
- -Signal: TERM
-apachectl stop
Sending the TERM signal to the parent causes it to
-immediately attempt to kill off all of its children. It may take it
-several seconds to complete killing off its children. Then the
-parent itself exits. Any requests in progress are terminated, and no
-further requests are served.
-
-
Signal: WINCH
-apachectl graceful
The WINCH signal causes the parent process to advise
-the children to exit after their current request (or to exit immediately
-if they're not serving anything). The parent re-reads its configuration
-files and re-opens its log files. As each child dies off the parent
-replaces it with a child from the new generation of the
-configuration, which begins serving new requests immediately.
This code is designed to always respect the MaxClients, MinSpareServers, and MaxSpareServers -settings. Furthermore, it respects StartServers in the -following manner: if after one second at least StartServers new -children have not been created, then create enough to pick up the -slack. This is to say that the code tries to maintain both the number -of children appropriate for the current load on the server, and -respect your wishes with the StartServers parameter.
- -Users of the
-status module
-will notice that the server statistics
-are not set to zero when a USR1 is sent. The
-code
-was written to both minimize the time in which the server is unable to serve
-new requests (they will be queued up by the operating system, so they're
-not lost in any event) and to respect your tuning parameters. In order
-to do this it has to keep the scoreboard used to keep track
-of all children across generations.
-
-
The status module will also use a G to indicate those
-children which are still serving requests started before the graceful
-restart was given.
-
-
At present there is no way for a log rotation script using
-WINCH to know for certain that all children writing the
-pre-restart log have finished. We suggest that you use a suitable delay
-after sending the WINCH signal before you do anything with the
-old log. For example if most of your hits take less than 10 minutes to
-complete for users on low bandwidth links then you could wait 15 minutes
-before doing anything with the old log.
-
-
Note: If your configuration file has errors in it
-when you issue a restart then your parent will not restart, it will
-exit with an error. In the case of graceful restarts it will also
-leave children running when it exits. (These are the children which
-are "gracefully exiting" by handling their last request.) This will
-cause problems if you attempt to restart the server -- it will not be
-able to bind to its listening ports. Before doing a restart, you can
-check the syntax of the configuration files with the -t
-command line argument (see httpd). This still will not guarantee
-that the server will restart correctly. To check the semantics of the
-configuration files as well as the syntax, you can try starting httpd
-as a non-root user. If there are no errors it will attempt to open
-its sockets and logs and fail because it's not root (or because the
-currently running httpd already has those ports bound). If it fails
-for any other reason then it's probably a config file error and the
-error should be fixed before issuing the graceful restart.
-
-
-
Signal: HUP
-apachectl restart
Sending the HUP signal to the parent causes it to kill off
-its children like in TERM but the parent doesn't exit. It
-re-reads its configuration files, and re-opens any log files.
-Then it spawns a new set of children and continues
-serving hits.
-
-
Users of the
-status module
-will notice that the server statistics are
-set to zero when a HUP is sent.
-
-
Note: If your configuration file has errors in it when -you issue a -restart then your parent will not restart, it will exit with an error. -See below for a method of avoiding this. - - -
Prior to Apache 1.2b9 there were several race conditions -involving the restart and die signals (a simple description of race -condition is: a time-sensitive problem, as in if something happens at just -the wrong time it won't behave as expected). For those architectures that -have the "right" feature set we have eliminated as many as we can. -But it should be noted that there still do exist race conditions on -certain architectures. - -
Architectures that use an on disk
-ScoreBoardFile
-have the potential to corrupt their scoreboards. This can result in
-the "bind: Address already in use" (after HUP) or
-"long lost child came home!" (after USR1). The former is
-a fatal error, while the latter just causes the server to lose a scoreboard
-slot. So it might be advisable to use graceful restarts, with
-an occasional hard restart. These problems are very difficult to work
-around, but fortunately most architectures do not require a scoreboard file.
-See the ScoreBoardFile documentation for a
-architecture uses it.
-
-
NEXT and MACHTEN (68k only) have small race
-conditions
-which can cause a restart/die signal to be lost, but should not cause the
-server to do anything otherwise problematic.
-
-
-
All architectures have a small race condition in each child involving -the second and subsequent requests on a persistent HTTP connection -(KeepAlive). It may exit after reading the request line but before -reading any of the request headers. There is a fix that was discovered -too late to make 1.2. In theory this isn't an issue because the KeepAlive -client has to expect these events because of network latencies and -server timeouts. In practice it doesn't seem to affect anything either --- in a test case the server was restarted twenty times per second and -clients successfully browsed the site without getting broken images or -empty documents. - - - - diff --git a/docs/manual/suexec.html.en b/docs/manual/suexec.html.en deleted file mode 100644 index 8988cd42b8f..00000000000 --- a/docs/manual/suexec.html.en +++ /dev/null @@ -1,516 +0,0 @@ - - -
--
-The suEXEC feature -- introduced in Apache 1.2 -- provides -Apache users the ability to run CGI and SSI -programs under user IDs different from the user ID of the calling web-server. -Normally, when a CGI or SSI program executes, it runs as the same user who is -running the web server. -
- --Used properly, this feature can reduce considerably the security risks involved -with allowing users to develop and run private CGI or SSI programs. However, -if suEXEC is improperly configured, it can cause any number of problems and -possibly create new holes in your computer's security. If you aren't familiar -with managing setuid root programs and the security issues they present, we -highly recommend that you not consider using suEXEC. -
- - - --Before jumping head-first into this document, you should be aware of the -assumptions made on the part of the Apache Group and this document. -
- --First, it is assumed that you are using a UNIX derivate operating system that -is capable of setuid and setgid operations. -All command examples are given in this regard. Other platforms, if they are -capable of supporting suEXEC, may differ in their configuration. -
- --Second, it is assumed you are familiar with some basic concepts of your -computer's security and its administration. This involves an understanding -of setuid/setgid operations and the various effects they -may have on your system and its level of security. -
- --Third, it is assumed that you are using an unmodified -version of suEXEC code. All code for suEXEC has been carefully scrutinized and -tested by the developers as well as numerous beta testers. Every precaution -has been taken to ensure a simple yet solidly safe base of code. Altering this -code can cause unexpected problems and new security risks. It is -highly recommended you not alter the suEXEC code unless you -are well versed in the particulars of security programming and are willing to -share your work with the Apache Group for consideration. -
- --Fourth, and last, it has been the decision of the Apache Group to -NOT make suEXEC part of the default installation of Apache. -To this end, suEXEC configuration requires of the administrator careful -attention to details. After due consideration has been given to the various -settings for suEXEC, the administrator may install suEXEC through normal -installation methods. The values for these settings need to be carefully -determined and specified by the administrator to properly maintain system -security during the use of suEXEC functionality. It is through this detailed -process that the Apache Group hopes to limit suEXEC installation only to those -who are careful and determined enough to use it. -
- --Still with us? Yes? Good. Let's move on! -
- - - --Before we begin configuring and installing suEXEC, we will first discuss -the security model you are about to implement. By doing so, you may -better understand what exactly is going on inside suEXEC and what precautions -are taken to ensure your system's security. -
- --suEXEC is based on a setuid "wrapper" program that is -called by the main Apache web server. This wrapper is called when an HTTP -request is made for a CGI or SSI program that the administrator has designated -to run as a userid other than that of the main server. When such a request -is made, Apache provides the suEXEC wrapper with the program's name and the -user and group IDs under which the program is to execute. -
- --The wrapper then employs the following process to determine success or -failure -- if any one of these conditions fail, the program logs the failure -and exits with an error, otherwise it will continue: -
- The wrapper will only execute if it is given the proper number of arguments. - The proper argument format is known to the Apache web server. If the - wrapper - is not receiving the proper number of arguments, it is either being hacked, - or - there is something wrong with the suEXEC portion of your Apache binary. --
- This is to ensure that the user executing the wrapper is truly a user of the - system. --
- Is this user the user allowed to run this wrapper? Only one user (the - Apache user) is allowed to execute this program. --
- Does the target program contain a leading '/' or have a '..' backreference? - These are not allowed; the target program must reside within the Apache - webspace. --
- Does the target user exist? --
- Does the target group exist? --
- Presently, suEXEC does not allow 'root' to execute CGI/SSI programs. --
- The minimum user ID number is specified during configuration. This allows - you - to set the lowest possible userid that will be allowed to execute CGI/SSI - programs. This is useful to block out "system" accounts. --
- Presently, suEXEC does not allow the 'root' group to execute CGI/SSI - programs. --
- The minimum group ID number is specified during configuration. This allows - you - to set the lowest possible groupid that will be allowed to execute CGI/SSI - programs. This is useful to block out "system" groups. --
- Here is where the program becomes the target user and group via setuid and - setgid - calls. The group access list is also initialized with all of the groups - of which - the user is a member. --
- If it doesn't exist, it can't very well contain files. --
- If the request is for a regular portion of the server, is the requested - directory - within the server's document root? If the request is for a UserDir, is - the requested - directory within the user's document root? --
- We don't want to open up the directory to others; only the owner user - may be able - to alter this directories contents. --
- If it doesn't exists, it can't very well be executed. --
- We don't want to give anyone other than the owner the ability to - change the program. --
- We do not want to execute programs that will then change our UID/GID again. --
- Is the user the owner of the file? --
- suEXEC cleans the process' environment by establishing a safe - execution PATH (defined - during configuration), as well as only passing through those - variables whose names - are listed in the safe environment list (also created during - configuration). --
- Here is where suEXEC ends and the target program begins. --
-This is the standard operation of the the suEXEC wrapper's security model. -It is somewhat stringent and can impose new limitations and guidelines for -CGI/SSI design, but it was developed carefully step-by-step with security -in mind. -
- --For more information as to how this security model can limit your possibilities -in regards to server configuration, as well as what security risks can be -avoided with a proper suEXEC setup, see the -"Beware the Jabberwock" -section of this document. -
- - - -
-Here's where we begin the fun. If you use Apache 1.2 or prefer to configure
-Apache 1.3 with the "src/Configure" script you have to edit
-the suEXEC header file and install the binary in its proper location
-manually. The following sections describe the configuration and installation
-for Apache 1.3 with the AutoConf-style interface (APACI).
-
-APACI's suEXEC configuration options
-
--enable-suexec
---suexec-caller=UID
---suexec-docroot=DIR
---datadir=/home/apache" the directory
- "/home/apache/htdocs" is used as document root for
- the suEXEC wrapper.
---suexec-logfile=FILE
---suexec-userdir=DIR
---suexec-uidmin=UID
---suexec-gidmin=GID
---suexec-safepath=PATH
-
-Checking your suEXEC setup
-Before you compile and install the suEXEC wrapper you can check
-the configuration with the --layout option.
-
-Example output:
-
- suEXEC setup: - suexec binary: /usr/local/apache/sbin/suexec - document root: /usr/local/apache/share/htdocs - userdir suffix: public_html - logfile: /usr/local/apache/var/log/suexec_log - safe path: /usr/local/bin:/usr/bin:/bin - caller ID: www - minimum user ID: 100 - minimum group ID: 100 -- - -
-Compiling and installing the suEXEC wrapper
-If you have enabled the suEXEC feature with the --enable-suexec option
-the suexec binary (together with Apache itself) is automatically built
-if you execute the command "make".
-
-After all components have been built you can execute the command
-"make install" to install them.
-The binary image "suexec" is installed in the directory defined by
-the --sbindir option. Default location is "/usr/local/apache/sbin/suexec".
-
-Please note that you need root privileges for
-the installation step. In order for the wrapper to set the user ID, it
-must be installed as owner root and must have the
-setuserid execution bit set for file modes.
-
-Upon startup of Apache, it looks for the file "suexec" in the "sbin" -directory (default is "/usr/local/apache/sbin/suexec"). -If Apache finds a properly configured suEXEC wrapper, it will print -the following message to the error log: -
- [notice] suEXEC mechanism enabled (wrapper: /path/to/suexec) --If you don't see this message at server startup, the server is most -likely not finding the wrapper program where it expects it, or the -executable is not installed setuid root. -
-Virtual Hosts:
-One way to use the suEXEC wrapper is through the
-User and
-Group directives in
-VirtualHost
-definitions. By setting these directives to values different from the
-main server user ID, all requests for CGI resources will be executed as
-the User and Group defined for that
-<VirtualHost>. If only one or
-neither of these directives are specified for a
-<VirtualHost> then the main
-server userid is assumed.
-
-User directories:
-The suEXEC wrapper can also be used to execute CGI programs as
-the user to which the request is being directed. This is accomplished by
-using the "~" character prefixing the user
-ID for whom execution is desired.
-The only requirement needed for this feature to work is for CGI
-execution to be enabled for the user and that the script must meet the
-scrutiny of the security checks above.
-
-
-The suEXEC wrapper will write log information to the file defined -with the --suexec-logfile option as indicated above. If you feel you have -configured and installed the wrapper properly, have a look at this log -and the error_log for the server to see where you may have gone astray. -
- - - --NOTE! This section may not be complete. For the latest -revision of this section of the documentation, see the Apache Group's -Online Documentation -version. -
- --There are a few points of interest regarding the wrapper that can cause -limitations on server setup. Please review these before submitting any -"bugs" regarding suEXEC. -
- For security and efficiency reasons, all suexec requests must - remain within either a top-level document root for virtual - host requests, or one top-level personal document root for - userdir requests. For example, if you have four VirtualHosts - configured, you would need to structure all of your VHosts' - document roots off of one main Apache document hierarchy to - take advantage of suEXEC for VirtualHosts. (Example forthcoming.) --
- This can be a dangerous thing to change. Make certain every - path you include in this define is a trusted - directory. You don't want to open people up to having someone - from across the world running a trojan horse on them. --
- Again, this can cause Big Trouble if you try - this without knowing what you are doing. Stay away from it - if at all possible. --
In order to assist folks upgrading, we maintain a document
-describing information critical to existing Apache users. These are
-intended to be brief notes, and you should be able to find more
-information in either the New
-Features document, or in the src/CHANGES file.
-
-
autoconf and libtool
-system for configuring the build processes. Using this system
-is similar to, but not the same as, using the APACI system in
-Apache 1.3. Further documentation to follow.CacheNegotiatedDocs directive now takes
-the argument on or off. Existing
-instances of CacheNegotiatedDocs should be replaced
-with CacheNegotiatedDocs on.ErrorDocument directive no longer uses a quote at
-the beginning of the argument to indicate a text message. Instead,
-you should enclose the message in double quotes. For example,
-existing instances of ErrorDocument 403 "Some
-Message should be replaced with
-ErrorDocument 403 "Some
-Message" As long as the second argument is not a
-valid URL or pathname, it will be treated as a text message.AccessConfig and ResourceConfig
-directives no longer exist. Existing instances of these directives
-can be replaced with the Include directive which
-has equivalent functionality. If you were making use of the default
-values of these directives without including them in the configuration
-files, you may need to add Include conf/access.conf and
-Include conf/srm.conf to your httpd.conf. In order to
-assure that Apache reads the configuration files in the same order as
-was implied by the older directives, the Include
-directives should be placed at the end of httpd.conf, with the one for
-srm.conf preceding the one for
-access.conf.BindAddress directive no longer exists.
-Equivalent functionality is provided with the more flexible Listen directive.
-
-ExtendedStatus directive no longer exists.
-Status reporting has been completely rewritten to take advantage
-of the new MPM system.ServerType directive no longer exists.
-The method used to serve requests is now determined by the selection
-of MPM. There is currently no MPM designed to be launched by
-inetd.AgentLog, RefererLog and
-RefererIgnore directives have been removed. Agent and
-referer logs are still available using the CustomLog directive of
-mod_log_config.AddModule and ClearModuleList
-directives no longer exist. These directives where used to ensure
-that modules could be enabled in the correct order. The new
-Apache 2.0 API allows modules to explicitly specify their ordering,
-eliminating the need for these directives.WINCH rather than
-USR1.httpd command line option -S
-which was used for printing the virtual host configuration has
-been replaced by -t -D DUMP_VHOSTS.httpd command line option -X has
-been removed. Most MPMs allow the same functionality to be requested
-by using the -D ONE_PROCESS command line
-option. In addition, a -D NO_DETACH command line
-option is available.src directory. Instead,
-the sources are logically organized under the main distribution
-directory, and installations of the compiled server should be
-directed to a separate directory.Extensive changes were made to the server API in Apache 2.0. -Existing modules designed for the Apache 1.3 API will not -work in Apache 2.0 without modification. Details are provided in -the developer documentation.
- - - - diff --git a/docs/manual/urlmapping.html.en b/docs/manual/urlmapping.html.en deleted file mode 100755 index 47e48731629..00000000000 --- a/docs/manual/urlmapping.html.en +++ /dev/null @@ -1,253 +0,0 @@ - - - -This document explains the method in which Apache determines -what filesystem location to serve a file from based on the -URL of a request.
- -|
-Related Modules - -mod_alias -mod_rewrite -mod_userdir -mod_speling -mod_vhost_alias - - |
-Related Directives - -Alias -AliasMatch -CheckSpelling -DocumentRoot -ErrorDocument -Options -Redirect -RedirectMatch -RewriteCond -RewriteRule -ScriptAlias -ScriptAliasMatch -UserDir - - |
In deciding what file to serve for a given request, Apache's
-default behavior is to take the URL-Path for the request (the part of
-the URL following the first single slash) and add it to the end of the
-DocumentRoot specified in
-your configuration files. Therefore, the files and directories
-underneath the DocumentRoot make up the basic document
-tree which will be visible from the web.
Apache is also capable of Virtual Hosting,
-where the server receives requests for more than one host. In this
-case, a different DocumentRoot can be specified for each
-virtual host, or alternatively, the directives provided by the module
-mod_vhost_alias can be used to
-dynamically determine the appropriate place from which to serve
-content based on the requested IP address or hostname.
There are frequently circumstances where it is necessary to allow
-web access to parts of the filesystem which are not strictly
-underneath the DocumentRoot.
-Apache offers several different ways to accomplish this. On Unix
-systems, symbolic links can be used to bring other parts of the
-filesystem under the DocumentRoot. For security reasons,
-symbolic links will only be followed if the Options setting for the relevant
-directory includes FollowSymLinks or
-SymLinksIfOwnerMatch.
Alternatively, the Alias -directive can be used to map any part of the filesystem into the web -space. For example, with
- -Alias /docs /var/web/
-
-
-the URL http://www.example.com/docs/dir/file.html will
-be served from /var/web/dir/file.html. The ScriptAlias directive works
-the same way, with the additional effect that all content located at
-the target path is treated as CGI scripts.
For situations where additional flexibility is required, the AliasMatch and ScriptAliasMatch -directives can do powerful regular-expression based matching and -substitution. For example,
- - ScriptAliasMatch ^/~([^/]*)/cgi-bin/(.*)
-/home/$1/cgi-bin/$2
-
-will map a request to
-http://example.com/~user/cgi-bin/script.cgi to the path
-/home/user/cgi-bin/script.cgi and will treat the
-resulting file as a CGI script.
Traditionally on Unix systems, the home directory of a particular
-user can be referred to as ~user/. The module
-mod_userdir extends this idea to
-the web by allowing files under each user's home directory to be
-accessed using URLs such as the following.
http://www.example.com/~user/file.html
-
-For security reasons, it would be inappropriate to give direct
-access to a user's home directory from the web. Therefore, the UserDir directive is used to
-specify a directory underneath the user's home directory where web
-files will be located. Using the default setting of Userdir
-public_html, the above URL would look for a file at a directory
-like /home/user/public_html/file.html where the
-/home/user/ is the user's home directory as specified in
-/etc/passwd.
There are also several other forms of the Userdir
-directive which can be used on systems where /etc/passwd
-cannot be used to find the location of the home directory.
Some people find the "~" symbol (which is often encoded on the web
-as %7e) to be awkward and prefer to use an alternate
-string to represent user directories. This functionality is not
-supported by mod_userdir. However, if users' home directories are
-structured in a regular way, then it is possible to use the AliasMatch directive to
-achieve the desired effect. For example, to make
-http://www.example.com/upages/user/file.html map to
-/home/user/public_html/file.html, the following
-AliasMatch directive can be used.
-AliasMatch ^/upages/([^/]*)/?(.*) /home/$1/public_html/$2
-
-
-The configuration directives discussed in the above sections are
-used to tell Apache to get content from a specific place in the
-filesystem and return it to the client. Sometimes, it is desirable
-instead to inform the client that the content being requested is
-located at an different URL, and instruct the client to make a new
-request with the new URL. This is referred to as redirection
-and is implemented by the Redirect directive. For example,
-if the contents of the directory /foo/ under the
-DocumentRoot have been moved to the new directory
-/bar/, clients can instructed to request the content at
-the new location as follows.
Redirect permanent
-/foo/ http://www.example.com/bar/
-
-This will redirect any URL-Path starting in /foo/ to
-the same URL path on the www.example.com server with
-/bar/ substituted for /foo/. Note that
-clients can be redirected to any server, not only the origin
-server.
Apache also provides a RedirectMatch directive -which can be used for more complicated rewriting problems. For -example, to redirect requests for the site home page to a different -site, but leave all other requests alone, the following configuration -can be used.
- -
-RedirectMatch permanent ^/$ http://www.example.com/startpage.html
-
-
-Alternatively, to temporarily redirect all pages on a site to one -particular page, the following configuration is useful.
- -
-RedirectMatch temp .* http://www.example.com/startpage.html
-
-
-When even more powerful substitution is required, the rewriting -engine provided by mod_rewrite can -be useful. The directives provided by this module can use -characteristics of the request such as browser type or source IP -address in deciding from where to serve content. In addition, -mod_rewrite can use external database files or programs to determine -how to handle a request. Many practical examples employing -mod_rewrite are discussed in the URL -Rewriting Guide.
- -Inevitably, URLs will be requested for which no matching file can -be found in the filesystem. This can happen for several reasons. In -some cases, it can be a result of moving documents from one location -to another. In this case, it is best to use URL -redirection to inform clients of the new location of the resource. -In this way, you can assure that old bookmarks and links will continue -to work, even though the resource is at a new location.
- -Another common cause of "File Not Found" errors is accidental -mistyping of URLs, either directly in the browser, or in HTML links. -Apache provides the module mod_speling -(sic) to help with this problem. When this module is activated, it -will intercept "File Not Found" errors and look for a resource with a -similar filename. If one such file is found, mod_speling will send an -HTTP redirect to the client informing it of the correct location. If -several "close" files are found, a list of available alternatives will -be presented to the client.
- -An especially useful feature of mod_speling, is that it will -compare filenames without respect to case. This can be useful for -systems where users are unaware of the case-sensitive nature of URLs -and the unix filesystem. However, using mod_speling for anything more -than the occasional URL correction can lead to additional load on the -server, since each "incorrect" request is followed by a URL -redirection and a new request from the client.
- -If all attempts to locate the content fail, Apache returns an error -page with HTTP status code 404 (file not found). The appearance of -this page is controlled with the ErrorDocument directive and can -be customized in a flexible manner as discussed in the Custom error responses and International Server Error -Responses documents.
- - - - diff --git a/docs/manual/vhosts/fd-limits.html.en b/docs/manual/vhosts/fd-limits.html.en deleted file mode 100644 index 6b9d0f93c46..00000000000 --- a/docs/manual/vhosts/fd-limits.html.en +++ /dev/null @@ -1,59 +0,0 @@ - - - --When using a large number of Virtual Hosts, Apache may run out of available -file descriptors (sometimes called file handles if each Virtual -Host specifies different log files. -The total number of file descriptors used by Apache is one for each distinct -error log file, one for every other log file directive, plus 10-20 for -internal use. Unix operating systems limit the number of file descriptors that -may be used by a process; the limit is typically 64, and may usually be -increased up to a large hard-limit. -
-Although Apache attempts to increase the limit as required, this -may not work if: -
-#!/bin/sh
-ulimit -S -n 100
-exec httpd
--Please see the -Descriptors and Apache -document containing further details about file descriptor problems and how -they can be solved on your operating system. -
- - - - diff --git a/docs/manual/vhosts/index.html.en b/docs/manual/vhosts/index.html.en deleted file mode 100644 index bb4a0f89312..00000000000 --- a/docs/manual/vhosts/index.html.en +++ /dev/null @@ -1,65 +0,0 @@ - - - -The term Virtual Host refers to the practice of maintaining -more than one server on one machine, as differentiated by their apparent -hostname. For example, it is often desirable for companies sharing a -web server to have their own domains, with web servers accessible as -www.company1.com and www.company2.com, -without requiring the user to know any extra path information.
- -Apache was one of the first servers to support IP-based -virtual hosts right out of the box. Versions 1.1 and later of -Apache support both, IP-based and name-based virtual hosts (vhosts). -The latter variant of virtual hosts is sometimes also called host-based or -non-IP virtual hosts.
- -Below is a list of documentation pages which explain all details -of virtual host support in Apache version 1.3 and later.
- -Folks trying to debug their virtual host configuration may find the
-Apache -S command line switch useful. It will dump out a
-description of how Apache parsed the configuration file. Careful
-examination of the IP addresses and server names may help uncover
-configuration mistakes.
-
-
-
-
diff --git a/docs/manual/vhosts/name-based.html.en b/docs/manual/vhosts/name-based.html.en
deleted file mode 100644
index 1d834f29893..00000000000
--- a/docs/manual/vhosts/name-based.html.en
+++ /dev/null
@@ -1,169 +0,0 @@
-
-
Early versions of HTTP (like many other protocols, e.g. FTP) -required a different IP address for each virtual host on the server. -On some platforms this can limit the number of virtual hosts you can -run, and because there are concerns about the availability of IP -addresses it is strongly discouraged by the registraries (ARIN, RIPE, -and APNIC).
- -The HTTP/1.1 protocol, and a common extension to
-HTTP/1.0, includes a method for the server to identify
-what name it is being addressed as. Apache 1.1 and later support this
-approach as well as the old IP-address-per-hostname method.
The benefits of using the name-based virtual hosts is a practically -unlimited number of servers, ease of configuration and use, and it -requires no additional hardware or software. The main disadvantage is -that the client must support this part of the protocol. Almost all -browsers do, but there are still tiny numbers of very old browsers in -use which do not. This can cause problems, although a possible -solution is addressed below.
- -Using name-based virtual hosts is quite easy, and superficially looks
-like the old method. The notable difference between IP-based and
-name-based virtual host configuration is the
-NameVirtualHost
-directive which specifies an IP address that should be used as a
-target for name-based virtual hosts, or the wildcard * to
-indicate that the server only does name-based virtual hosting (no
-IP-based virtual hosting).
For example, suppose that both www.domain.tld and
-www.otherdomain.tld point at the IP address of your
-server. Then you simply add to one of the Apache configuration files
-(most likely httpd.conf or srm.conf) code
-similar to the following:
- NameVirtualHost * - - <VirtualHost *> - ServerName www.domain.tld - DocumentRoot /www/domain - </VirtualHost> - - <VirtualHost *> - ServerName www.otherdomain.tld - DocumentRoot /www/otherdomain - </VirtualHost> -- -
Of course, any additional directives can (and should) be placed
-into the <VirtualHost> section. To make this work,
-all that is needed is to make sure that the names
-www.domain.tld and www.otherdomain.tld
-are pointing to the right IP address.
-
-
Note: When you specify an IP address in a NameVirtualHost
-directive then requests to that IP address will only ever be served
-by matching <VirtualHost>s. The "main server" will
-never be served from the specified IP address.
-If you specify a wildcard then the "main server" isn't used at all.
-If you start to use virtual hosts you should stop using the "main server"
-as an independent server and rather use it as a place for
-configuration directives that are common for all your virtual hosts.
-In other words, you should add a <VirtualHost> section for
-every server (hostname) you want to maintain on your server.
-
-
Additionally, many servers may wish to be accessible by more than
-one name. For example, the example server might want to be accessible
-as domain.tld, or www2.domain.tld, assuming
-the IP addresses pointed to the same server. In fact, one might want it
-so that all addresses at domain.tld were picked up by the
-server. This is possible with the
-ServerAlias
-directive, placed inside the <VirtualHost> section. For
-example:
- ServerAlias domain.tld *.domain.tld -- -
Note that you can use * and ? as wild-card
-characters.
You also might need ServerAlias if you are
-serving local users who do not always include the domain name.
-For example, if local users are
-familiar with typing "www" or "www.foobar" then you will need to add
-ServerAlias www www.foobar. It isn't possible for the
-server to know what domain the client uses for their name resolution
-because the client doesn't provide that information in the request.
-The ServerAlias directive is generally a way to have different
-hostnames pointing to the same virtual host.
-
As mentioned earlier, there are still some clients in use who -do not send the required data for the name-based virtual hosts to work -properly. These clients will always be sent the pages from the -first virtual host listed for that IP address (the -primary name-based virtual host).
- -There is a possible workaround with the
-ServerPath
-directive, albeit a slightly cumbersome one:
Example configuration: - -
- NameVirtualHost 111.22.33.44 - - <VirtualHost 111.22.33.44> - ServerName www.domain.tld - ServerPath /domain - DocumentRoot /web/domain - </VirtualHost> -- -
What does this mean? It means that a request for any URI beginning
-with "/domain" will be served from the virtual host
-www.domain.tld This means that the pages can be accessed as
-http://www.domain.tld/domain/ for all clients, although
-clients sending a Host: header can also access it as
-http://www.domain.tld/.
In order to make this work, put a link on your primary virtual host's page -to http://www.domain.tld/domain/ -Then, in the virtual host's pages, be sure to use either purely -relative links (e.g., "file.html" or -"../icons/image.gif" or links containing the prefacing -/domain/ -(e.g., "http://www.domain.tld/domain/misc/file.html" or -"/domain/misc/file.html").
- -This requires a bit of -discipline, but adherence to these guidelines will, for the most part, -ensure that your pages will work with all browsers, new and old.
- -See also: ServerPath configuration -example
- - - - diff --git a/include/ap_release.h b/include/ap_release.h index 5b20de5d1bf..088793a733f 100644 --- a/include/ap_release.h +++ b/include/ap_release.h @@ -73,7 +73,7 @@ */ #define AP_SERVER_BASEVENDOR "Apache Software Foundation" #define AP_SERVER_BASEPRODUCT "Apache" -#define AP_SERVER_BASEREVISION "2.0.21-dev" +#define AP_SERVER_BASEREVISION "2.0.20" #define AP_SERVER_BASEVERSION AP_SERVER_BASEPRODUCT "/" AP_SERVER_BASEREVISION #define AP_SERVER_VERSION AP_SERVER_BASEVERSION diff --git a/modules/proxy/.cvsignore b/modules/proxy/.cvsignore deleted file mode 100644 index efec0263f68..00000000000 --- a/modules/proxy/.cvsignore +++ /dev/null @@ -1,10 +0,0 @@ -Debug -Release -Makefile -*.lo -*.slo -*.la -*.so -modules.mk -.deps -.libs diff --git a/modules/proxy/.indent.pro b/modules/proxy/.indent.pro deleted file mode 100644 index 20c2d83371d..00000000000 --- a/modules/proxy/.indent.pro +++ /dev/null @@ -1,55 +0,0 @@ --i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1 --TBUFF --TFILE --TTRANS --TUINT4 --T_trans --Tallow_options_t --Tapache_sfio --Tarray_header --Tbool_int --Tbuf_area --Tbuff_struct --Tbuffy --Tcmd_how --Tcmd_parms --Tcommand_rec --Tcommand_struct --Tconn_rec --Tcore_dir_config --Tcore_server_config --Tdir_maker_func --Tevent --Tglobals_s --Thandler_func --Thandler_rec --Tjoblist_s --Tlisten_rec --Tmerger_func --Tmode_t --Tmodule --Tmodule_struct --Tmutex --Tn_long --Tother_child_rec --Toverrides_t --Tparent_score --Tpid_t --Tpiped_log --Tpool --Trequest_rec --Trequire_line --Trlim_t --Tscoreboard --Tsemaphore --Tserver_addr_rec --Tserver_rec --Tserver_rec_chain --Tshort_score --Ttable --Ttable_entry --Tthread --Tu_wide_int --Tvtime_t --Twide_int --Tproxy_server_conf diff --git a/modules/proxy/CHANGES b/modules/proxy/CHANGES deleted file mode 100644 index ce33ed932f7..00000000000 --- a/modules/proxy/CHANGES +++ /dev/null @@ -1,173 +0,0 @@ - -mod_proxy changes for httpd 2.0.20-dev - - *) Fix abort code path in proxy_http.c, similar to FTP fix. - [Chuck Murcko");
- } else {
- str = apr_psprintf(p, "\n\n(%s)\n\n
\n\n", pwd);
- }
- e = apr_bucket_pool_create(str, strlen(str), p);
- APR_BRIGADE_INSERT_TAIL(out, e);
-
- /* print README */
- if (readme) {
- str = apr_psprintf(p, "%s\n\n\n
\n\n\n",
- readme);
-
- e = apr_bucket_pool_create(str, strlen(str), p);
- APR_BRIGADE_INSERT_TAIL(out, e);
- }
-
- /* make sure page intro gets sent out */
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(out, e);
- if (APR_SUCCESS != (rv = ap_pass_brigade(f->next, out))) {
- return rv;
- }
- apr_brigade_cleanup(out);
-
- ctx->state = BODY;
- }
-
- /* loop through each line of directory */
- while (BODY == ctx->state) {
- char *filename;
- int found = 0;
- int eos = 0;
-
- /* get a complete line */
- /* if the buffer overruns - throw data away */
- while (!found && !APR_BRIGADE_EMPTY(ctx->in)) {
- char *pos, *response;
- apr_size_t len, max;
- e = APR_BRIGADE_FIRST(ctx->in);
- if (APR_BUCKET_IS_EOS(e)) {
- eos = 1;
- break;
- }
- if (APR_SUCCESS != (rv = apr_bucket_read(e, (const char **)&response, &len, APR_BLOCK_READ))) {
- return rv;
- }
- pos = memchr(response, APR_ASCII_LF, len);
- if (pos != NULL) {
- if ((pos - response + 1) != len) {
- len = pos - response + 1;
- apr_bucket_split(e, pos - response + 1);
-
- }
- found = 1;
- }
- max = sizeof(ctx->buffer)-strlen(ctx->buffer)-1;
- if (len > max) {
- len = max;
- }
-/* strncat works here, but apr_cpystrn does not - the last char gets chopped, dunno why */
-/* apr_cpystrn(ctx->buffer+strlen(ctx->buffer), response, len);*/
- strncat(ctx->buffer, response, len);
- APR_BUCKET_REMOVE(e);
- apr_bucket_destroy(e);
- }
-
- /* EOS? jump to footer */
- if (eos) {
- ctx->state = FOOTER;
- break;
- }
-
- /* not complete? leave and try get some more */
- if (!found) {
- return APR_SUCCESS;
- }
-
- /* a symlink? */
- if (ctx->buffer[0] == 'l' && (filename=strstr(ctx->buffer, " -> ")) != NULL) {
- char *link_ptr = filename;
-
- do {
- filename--;
- } while (filename[0] != ' ');
- *(filename++) = '\0';
- *(link_ptr++) = '\0';
- if ((n = strlen(link_ptr)) > 1 && link_ptr[n - 1] == '\n')
- link_ptr[n - 1] = '\0';
- str = apr_psprintf(p, "%s %s %s\n", ctx->buffer, filename, filename, link_ptr);
- }
-
- /* a directory/file? */
- else if (ctx->buffer[0] == 'd' || ctx->buffer[0] == '-' || ctx->buffer[0] == 'l' || apr_isdigit(ctx->buffer[0])) {
- int searchidx = 0;
- char *searchptr = NULL;
- int firstfile = 1;
- if (apr_isdigit(ctx->buffer[0])) { /* handle DOS dir */
- searchptr = strchr(ctx->buffer, '<');
- if (searchptr != NULL)
- *searchptr = '[';
- searchptr = strchr(ctx->buffer, '>');
- if (searchptr != NULL)
- *searchptr = ']';
- }
-
- filename = strrchr(ctx->buffer, ' ');
- *(filename++) = 0;
- filename[strlen(filename) - 1] = 0;
-
- /* handle filenames with spaces in 'em */
- if (!strcmp(filename, ".") || !strcmp(filename, "..") || firstfile) {
- firstfile = 0;
- searchidx = filename - ctx->buffer;
- }
- else if (searchidx != 0 && ctx->buffer[searchidx] != 0) {
- *(--filename) = ' ';
- ctx->buffer[searchidx - 1] = 0;
- filename = &ctx->buffer[searchidx];
- }
-
- /* Special handling for '.' and '..' */
- if (!strcmp(filename, ".") || !strcmp(filename, "..") || ctx->buffer[0] == 'd') {
- str = apr_psprintf(p, "%s %s\n",
- ctx->buffer, filename, filename);
- }
- else {
- str = apr_psprintf(p, "%s %s\n",
- ctx->buffer, filename, filename);
- }
- }
- else {
- str = apr_pstrdup(p, ctx->buffer);
- }
-
- /* erase buffer for next time around */
- ctx->buffer[0] = 0;
-
- e = apr_bucket_pool_create(str, strlen(str), p);
- APR_BRIGADE_INSERT_TAIL(out, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(out, e);
- if (APR_SUCCESS != (rv = ap_pass_brigade(f->next, out))) {
- return rv;
- }
- apr_brigade_cleanup(out);
-
- }
-
- if (FOOTER == ctx->state) {
- str = apr_psprintf(p, "\n\n
\n\n%s\n\n\n\n", ap_psignature("", r));
- e = apr_bucket_pool_create(str, strlen(str), p);
- APR_BRIGADE_INSERT_TAIL(out, e);
-
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(out, e);
-
- e = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(out, e);
-
- if (APR_SUCCESS != (rv = ap_pass_brigade(f->next, out))) {
- return rv;
- }
- apr_brigade_destroy(out);
- }
-
- return APR_SUCCESS;
-}
-
-/* Common routine for failed authorization (i.e., missing or wrong password)
- * to an ftp service. This causes most browsers to retry the request
- * with username and password (which was presumably queried from the user)
- * supplied in the Authorization: header.
- * Note that we "invent" a realm name which consists of the
- * ftp://user@host part of the reqest (sans password -if supplied but invalid-)
- */
-static int ftp_unauthorized (request_rec *r, int log_it)
-{
- r->proxyreq = PROXYREQ_NONE;
- /* Log failed requests if they supplied a password
- * (log username/password guessing attempts)
- */
- if (log_it)
- ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r,
- "proxy: missing or failed auth to %s",
- apr_uri_unparse_components(r->pool,
- &r->parsed_uri, UNP_OMITPATHINFO));
-
- apr_table_setn(r->err_headers_out, "WWW-Authenticate",
- apr_pstrcat(r->pool, "Basic realm=\"",
- apr_uri_unparse_components(r->pool, &r->parsed_uri,
- UNP_OMITPASSWORD|UNP_OMITPATHINFO),
- "\"", NULL));
-
- return HTTP_UNAUTHORIZED;
-}
-
-
-/*
- * Handles direct access of ftp:// URLs
- * Original (Non-PASV) version from
- * Troy Morrison
- * PASV added by Chuck
- * Filters by [Graham Leggett ]
- */
-int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf,
- char *url, const char *proxyhost,
- apr_port_t proxyport)
-{
- apr_pool_t *p = r->pool;
- conn_rec *c = r->connection;
- proxy_conn_rec *backend;
- apr_socket_t *sock, *local_sock, *remote_sock;
- apr_sockaddr_t *connect_addr;
- apr_status_t rv;
- conn_rec *origin, *remote;
- int err;
- apr_bucket *e;
- apr_bucket_brigade *bb = apr_brigade_create(p);
- apr_bucket_brigade *cbb = apr_brigade_create(p);
- char *buf, *connectname;
- apr_port_t connectport;
- char buffer[MAX_STRING_LEN];
- char *path, *strp, *parms;
- char *user = NULL;
-/* char *account = NULL; how to supply an account in a URL? */
- const char *password = NULL;
- int i = 0, j, len, rc;
- int one = 1;
- char *size = NULL;
- apr_size_t readbytes = -1;
-
- /* stuff for PASV mode */
- int connect = 0, use_port = 0;
- char dates[AP_RFC822_DATE_LEN];
-
- /* is this for us? */
- if (proxyhost) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: rejecting URL %s - proxyhost %s specified:", url, proxyhost);
- return DECLINED; /* proxy connections are via HTTP */
- }
- if (strncasecmp(url, "ftp:", 4)) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: rejecting URL %s - not ftp:", url);
- return DECLINED; /* only interested in FTP */
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: serving URL %s", url);
-
- /* create space for state information */
- backend = (proxy_conn_rec *) ap_get_module_config(c->conn_config, &proxy_ftp_module);
- if (!backend) {
- backend = ap_pcalloc(c->pool, sizeof(proxy_conn_rec));
- backend->connection = NULL;
- backend->hostname = NULL;
- backend->port = 0;
- ap_set_module_config(c->conn_config, &proxy_ftp_module, backend);
- }
-
-
- /*
- * I: Who Do I Connect To?
- * -----------------------
- *
- * Break up the URL to determine the host to connect to
- */
-
- /* we only support GET and HEAD */
- if (r->method_number != M_GET)
- return HTTP_NOT_IMPLEMENTED;
-
-
- /* We break the URL into host, port, path-search */
- connectname = r->parsed_uri.hostname;
- connectport = (r->parsed_uri.port != 0)
- ? r->parsed_uri.port
- : apr_uri_default_port_for_scheme("ftp");
- path = apr_pstrdup(p, r->parsed_uri.path);
- path = (path != NULL && path[0] != '\0') ? &path[1] : "";
-
- parms = strchr(path, ';');
- if (parms != NULL)
- *(parms++) = '\0';
-
- /* The "Authorization:" header must be checked first.
- * We allow the user to "override" the URL-coded user [ & password ]
- * in the Browsers' User&Password Dialog.
- * NOTE that this is only marginally more secure than having the
- * password travel in plain as part of the URL, because Basic Auth
- * simply uuencodes the plain text password.
- * But chances are still smaller that the URL is logged regularly.
- */
- if ((password = apr_table_get(r->headers_in, "Authorization")) != NULL
- && strcasecmp(ap_getword(r->pool, &password, ' '), "Basic") == 0
- && (password = ap_pbase64decode(r->pool, password))[0] != ':') {
- /* Note that this allocation has to be made from r->connection->pool
- * because it has the lifetime of the connection. The other allocations
- * are temporary and can be tossed away any time.
- */
- user = ap_getword_nulls (r->connection->pool, &password, ':');
- r->ap_auth_type = "Basic";
- r->user = r->parsed_uri.user = user;
- }
- else if ((user = r->parsed_uri.user) != NULL) {
- user = apr_pstrdup(p, user);
- decodeenc(user);
- if ((password = r->parsed_uri.password) != NULL) {
- char *tmp = apr_pstrdup(p, password);
- decodeenc(tmp);
- password = tmp;
- }
- }
- else {
- user = "anonymous";
- password = "apache-proxy@";
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: connecting %s to %s:%d", url, connectname, connectport);
-
- /* do a DNS lookup for the destination host */
- err = apr_sockaddr_info_get(&connect_addr, connectname, APR_UNSPEC, connectport, 0, p);
-
- /* check if ProxyBlock directive on this host */
- if (OK != ap_proxy_checkproxyblock(r, conf, connect_addr)) {
- return ap_proxyerror(r, HTTP_FORBIDDEN,
- "Connect to remote machine blocked");
- }
-
-
- /*
- * II: Make the Connection
- * -----------------------
- *
- * We have determined who to connect to. Now make the connection.
- */
-
- /* get all the possible IP addresses for the destname and loop through them
- * until we get a successful connection
- */
- if (APR_SUCCESS != err) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p,
- "DNS lookup failure for: ",
- connectname, NULL));
- }
-
-
- if ((rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error creating socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-#if !defined(TPF) && !defined(BEOS)
- if (conf->recv_buffer_size > 0
- && (rv = apr_setsocketopt(sock, APR_SO_RCVBUF,
- conf->recv_buffer_size))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
- }
-#endif
-
- if (APR_SUCCESS != (rv = apr_setsocketopt(sock, APR_SO_REUSEADDR, one))) {
-#ifndef _OSD_POSIX /* BS2000 has this option "always on" */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error setting reuseaddr option: setsockopt(SO_REUSEADDR)");
- return HTTP_INTERNAL_SERVER_ERROR;
-#endif /*_OSD_POSIX*/
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: socket has been created");
-
-
- /*
- * At this point we have a list of one or more IP addresses of
- * the machine to connect to. If configured, reorder this
- * list so that the "best candidate" is first try. "best
- * candidate" could mean the least loaded server, the fastest
- * responding server, whatever.
- *
- * For now we do nothing, ie we get DNS round robin.
- * XXX FIXME
- */
-
-
- /* try each IP address until we connect successfully */
- {
- int failed = 1;
- while (connect_addr) {
-
- /* make the connection out of the socket */
- rv = apr_connect(sock, connect_addr);
-
- /* if an error occurred, loop round and try again */
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "proxy: FTP: attempt to connect to %pI (%s) failed", connect_addr, connectname);
- connect_addr = connect_addr->next;
- continue;
- }
-
- /* if we get here, all is well */
- failed = 0;
- break;
- }
-
- /* handle a permanent error from the above loop */
- if (failed) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_psprintf(r->pool,
- "Could not connect to remote machine: %s port %d",
- connectname, connectport));
- }
- }
-
- /* the socket is now open, create a new connection */
- origin = ap_new_connection(p, r->server, sock, r->connection->id);
- if (!origin) {
- /* the peer reset the connection already; ap_new_connection()
- * closed the socket */
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: an error occurred creating a new connection to %pI (%s)", connect_addr, connectname);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* if a keepalive connection is floating around, close it first! */
- /* we might support ftp keepalives later, but not now... */
- if (backend->connection) {
- apr_socket_close(backend->connection->client_socket);
- backend->connection = NULL;
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: control connection complete");
-
-
- /*
- * III: Send Control Request
- * -------------------------
- *
- * Log into the ftp server, send the username & password, change to the correct
- * directory...
- */
-
- /* set up the connection filters */
- ap_proxy_pre_http_connection(origin, NULL);
-
- /* possible results: */
- /* 120 Service ready in nnn minutes. */
- /* 220 Service ready for new user. */
- /* 421 Service not available, closing control connection. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, "Error reading from remote server");
- }
- if (rc == 120) {
- /* RFC2616 states:
- * 14.37 Retry-After
- *
- * The Retry-After response-header field can be used with a 503 (Service
- * Unavailable) response to indicate how long the service is expected to
- * be unavailable to the requesting client. [...] The value of this field
- * can be either an HTTP-date or an integer number of seconds (in decimal)
- * after the time of the response.
- * Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds )
- */
- for (i = 0; buffer[i] && !isdigit(buffer[i]); i++);
- if (buffer[i]) {
- ap_table_add(r->headers_out, "Retry-After", apr_psprintf(p, "%lu", 60*atol(buffer+i)));
- }
- return ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, buffer);
- }
- if (rc != 220) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: connected.");
-
- buf = apr_pstrcat(p, "USER ", user, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: USER %s", user);
-
- /* possible results; 230, 331, 332, 421, 500, 501, 530 */
- /* states: 1 - error, 2 - success; 3 - send password, 4,5 fail */
- /* 230 User logged in, proceed. */
- /* 331 User name okay, need password. */
- /* 332 Need account for login. */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* (This may include errors such as command line too long.) */
- /* 501 Syntax error in parameters or arguments. */
- /* 530 Not logged in. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, "Error reading from remote server");
- }
- if (rc == 530) {
- return ftp_unauthorized (r, 1); /* log it: user name guessing attempt? */
- }
- if (rc != 230 && rc != 331) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
- if (rc == 331) { /* send password */
- if (password == NULL) {
- return ftp_unauthorized (r, 0);
- }
- buf = apr_pstrcat(p, "PASS ", password, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: PASS %s", password);
-
- /* possible results 202, 230, 332, 421, 500, 501, 503, 530 */
- /* 230 User logged in, proceed. */
- /* 332 Need account for login. */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 503 Bad sequence of commands. */
- /* 530 Not logged in. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc == 332) {
- return ap_proxyerror(r, HTTP_UNAUTHORIZED,
- apr_pstrcat(p, "Need account for login: ", buffer, NULL));
- }
- /* @@@ questionable -- we might as well return a 403 Forbidden here */
- if (rc == 530) {
- return ftp_unauthorized (r, 1); /* log it: passwd guessing attempt? */
- }
- if (rc != 230 && rc != 202) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
- }
- apr_table_set(r->notes, "Directory-README", buffer);
-
- /* set the directory (walk directory component by component):
- * this is what we must do if we don't know the OS type of the remote
- * machine
- */
- for (;;) {
- strp = strchr(path, '/');
- if (strp == NULL)
- break;
- *strp = '\0';
-
- len = decodeenc(path);
- buf = apr_pstrcat(p, "CWD ", path, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: CWD %s", path);
- *strp = '/';
- /* responses: 250, 421, 500, 501, 502, 530, 550 */
- /* 250 Requested file action okay, completed. */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 502 Command not implemented. */
- /* 530 Not logged in. */
- /* 550 Requested action not taken. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc == 550) {
- return ap_proxyerror(r, HTTP_NOT_FOUND, buffer);
- }
- if (rc != 250) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
- path = strp + 1;
- }
-
- if (parms != NULL && strncasecmp(parms, "type=a", 6) == 0) {
- parms = "A";
- }
- else {
- parms = "I";
- }
-
- /* changed to make binary transfers the default */
- /* set type to binary */
- buf = apr_pstrcat(p, "TYPE ", parms, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: TYPE I");
- /* responses: 200, 421, 500, 501, 504, 530 */
- /* 200 Command okay. */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 504 Command not implemented for that parameter. */
- /* 530 Not logged in. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc != 200 && rc != 504) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
- /* Allow not implemented */
- if (rc == 504) {
- parms[0] = '\0';
- }
-
-
- /*
- * IV: Make Data Connection?
- * -------------------------
- *
- * Try EPSV, if that fails...
- * try PASV, if that fails...
- * try PORT.
- */
-/* this temporarily switches off EPSV/PASV */
-/*goto bypass;*/
-
- /* set up data connection - EPSV */
- {
- apr_sockaddr_t *remote_addr;
- char *remote_ip;
- apr_port_t remote_port;
-
- /* The EPSV command replaces PASV where both IPV4 and IPV6 is supported. Only
- * the port is returned, the IP address is always the same as that on the
- * control connection. Example:
- * Entering Extended Passive Mode (|||6446|)
- */
- buf = apr_pstrcat(p, "EPSV", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: EPSV");
- /* possible results: 227, 421, 500, 501, 502, 530 */
- /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 502 Command not implemented. */
- /* 530 Not logged in. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc != 229 && rc != 500 && rc != 501 && rc != 502) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
- else if (rc == 229) {
- char *pstr;
- char *tok_cntx;
-
- pstr = apr_pstrdup(p, buffer);
- pstr = apr_strtok(pstr, " ", &tok_cntx); /* separate result code */
- if (pstr != NULL) {
- if (*(pstr + strlen(pstr) + 1) == '=') {
- pstr += strlen(pstr) + 2;
- }
- else {
- pstr = apr_strtok(NULL, "(", &tok_cntx); /* separate address & port params */
- if (pstr != NULL)
- pstr = apr_strtok(NULL, ")", &tok_cntx);
- }
- }
-
- if (pstr) {
- apr_sockaddr_t *epsv_addr;
- remote_port = atoi(pstr+3);
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: EPSV contacting remote host on port %d",
- remote_port);
-
- if ((rv = apr_socket_create(&remote_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error creating EPSV socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-#if !defined (TPF) && !defined(BEOS)
- if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(remote_sock, APR_SO_RCVBUF,
- conf->recv_buffer_size))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
- }
-#endif
-
- /* make the connection */
- apr_socket_addr_get(&remote_addr, APR_REMOTE, sock);
- apr_sockaddr_ip_get(&remote_ip, remote_addr);
- apr_sockaddr_info_get(&epsv_addr, remote_ip, APR_INET, remote_port, 0, p);
- rv = apr_connect(remote_sock, epsv_addr);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "proxy: FTP: EPSV attempt to connect to %pI failed - Firewall/NAT?", epsv_addr);
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_psprintf(r->pool,
- "EPSV attempt to connect to %pI failed - firewall/NAT?", epsv_addr));
- }
- else {
- connect = 1;
- }
- }
- else {
- /* and try the regular way */
- apr_socket_close(remote_sock);
- }
- }
- }
-
- /* set up data connection - PASV */
- if (!connect) {
- buf = apr_pstrcat(p, "PASV", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: PASV");
- /* possible results: 227, 421, 500, 501, 502, 530 */
- /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 502 Command not implemented. */
- /* 530 Not logged in. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc != 227 && rc != 502) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
- else if (rc == 227) {
- unsigned int h0, h1, h2, h3, p0, p1;
- char *pstr;
- char *tok_cntx;
-
-/* FIXME: Check PASV against RFC1123 */
-
- pstr = apr_pstrdup(p, buffer);
- pstr = apr_strtok(pstr, " ", &tok_cntx); /* separate result code */
- if (pstr != NULL) {
- if (*(pstr + strlen(pstr) + 1) == '=') {
- pstr += strlen(pstr) + 2;
- }
- else {
- pstr = apr_strtok(NULL, "(", &tok_cntx); /* separate address & port params */
- if (pstr != NULL)
- pstr = apr_strtok(NULL, ")", &tok_cntx);
- }
- }
-
-/* FIXME: Only supports IPV4 - fix in RFC2428 */
-
- if (pstr != NULL && (sscanf(pstr,
- "%d,%d,%d,%d,%d,%d", &h3, &h2, &h1, &h0, &p1, &p0) == 6)) {
-
- apr_sockaddr_t *pasv_addr;
- int pasvport = (p1 << 8) + p0;
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: PASV contacting host %d.%d.%d.%d:%d",
- h3, h2, h1, h0, pasvport);
-
- if ((rv = apr_socket_create(&remote_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: error creating PASV socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-#if !defined (TPF) && !defined(BEOS)
- if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(remote_sock, APR_SO_RCVBUF,
- conf->recv_buffer_size))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
- }
-#endif
-
- /* make the connection */
- apr_sockaddr_info_get(&pasv_addr, apr_psprintf(p, "%d.%d.%d.%d", h3, h2, h1, h0), APR_INET, pasvport, 0, p);
- rv = apr_connect(remote_sock, pasv_addr);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "proxy: FTP: PASV attempt to connect to %pI failed - Firewall/NAT?", pasv_addr);
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_psprintf(r->pool,
- "PASV attempt to connect to %pI failed - firewall/NAT?", pasv_addr));
- }
- else {
- connect = 1;
- }
- }
- else {
- /* and try the regular way */
- apr_socket_close(remote_sock);
- }
- }
- }
-/*bypass:*/
-
- /* set up data connection - PORT */
- if (!connect) {
- apr_sockaddr_t *local_addr;
- char *local_ip;
- apr_port_t local_port;
- unsigned int h0, h1, h2, h3, p0, p1;
-
- if ((rv = apr_socket_create(&local_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error creating local socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- apr_socket_addr_get(&local_addr, APR_LOCAL, sock);
- apr_sockaddr_port_get(&local_port, local_addr);
- apr_sockaddr_ip_get(&local_ip, local_addr);
-
- if ((rv = apr_setsocketopt(local_sock, APR_SO_REUSEADDR, one)) != APR_SUCCESS) {
-#ifndef _OSD_POSIX /* BS2000 has this option "always on" */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error setting reuseaddr option");
- return HTTP_INTERNAL_SERVER_ERROR;
-#endif /*_OSD_POSIX*/
- }
-
- apr_sockaddr_info_get(&local_addr, local_ip, APR_UNSPEC, local_port, 0, r->pool);
-
- if ((rv = apr_bind(local_sock, local_addr)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error binding to ftp data socket %pI", local_addr);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* only need a short queue */
- if ((rv = apr_listen(local_sock, 2)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error listening to ftp data socket %pI", local_addr);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-/* FIXME: Sent PORT here */
-
- if (local_ip && (sscanf(local_ip,
- "%d.%d.%d.%d", &h3, &h2, &h1, &h0) == 4)) {
- p1 = (local_port >> 8);
- p0 = (local_port & 0xFF);
-
- buf = apr_psprintf(p, "PORT %d,%d,%d,%d,%d,%d" CRLF, h3, h2, h1, h0, p1, p0);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: PORT %d,%d,%d,%d,%d,%d", h3, h2, h1, h0, p1, p0);
- /* possible results: 200, 421, 500, 501, 502, 530 */
- /* 200 Command okay. */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 502 Command not implemented. */
- /* 530 Not logged in. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc != 200) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
- /* signal that we must use the EPRT/PORT loop */
- use_port = 1;
- }
- else {
-/* IPV6 FIXME:
- * The EPRT command replaces PORT where both IPV4 and IPV6 is supported. The first
- * number (1,2) indicates the protocol type. Examples:
- * EPRT |1|132.235.1.2|6275|
- * EPRT |2|1080::8:800:200C:417A|5282|
- */
- return ap_proxyerror(r, HTTP_NOT_IMPLEMENTED, "Connect to IPV6 ftp server using EPRT not supported. Enable EPSV.");
- }
- }
-
-
- /*
- * V: Set The Headers
- * -------------------
- *
- * Get the size of the request, set up the environment for HTTP.
- */
-
- /* set request; "path" holds last path component */
- len = decodeenc(path);
-
- /* TM - if len == 0 then it must be a directory (you can't RETR nothing) */
-
- if (len == 0) {
- parms = "d";
- }
- else {
- buf = apr_pstrcat(p, "SIZE ", path, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: SIZE %s", path);
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof buffer);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: returned status %d with response %s", rc, buffer);
- if (rc != 500) { /* Size command not recognized */
- if (rc == 550) { /* Not a regular file */
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: SIZE shows this is a directory");
- parms = "d";
- buf = apr_pstrcat(p, "CWD ", path, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: CWD %s", path);
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- /* possible results: 250, 421, 500, 501, 502, 530, 550 */
- /* 250 Requested file action okay, completed. */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 502 Command not implemented. */
- /* 530 Not logged in. */
- /* 550 Requested action not taken. */
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc == 550) {
- return ap_proxyerror(r, HTTP_NOT_FOUND, buffer);
- }
- if (rc != 250) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
- path = "";
- len = 0;
- }
- else if (i == 213) { /* Size command ok */
- for (j = 0; j < sizeof(buffer) && apr_isdigit(buffer[j]); j++);
- buffer[j] = '\0';
- if (buffer[0] != '\0')
- size = apr_pstrdup(p, buffer);
- }
- }
- }
-
-
-
-#ifdef AUTODETECT_PWD
- buf = apr_pstrcat(p, "PWD", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: PWD");
- /* responses: 257, 500, 501, 502, 421, 550 */
- /* 257 "" */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 502 Command not implemented. */
- /* 550 Requested action not taken. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1 || rc == 421) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc == 550) {
- return ap_proxyerror(r, HTTP_NOT_FOUND, buffer);
- }
- if (rc == 257) {
- const char *dirp = buffer;
- apr_table_set(r->notes, "Directory-PWD", ap_getword_conf(r->pool, &dirp));
- }
-#endif /*AUTODETECT_PWD*/
-
- if (parms[0] == 'd') {
- if (len != 0)
- buf = apr_pstrcat(p, "LIST ", path, CRLF, NULL);
- else
- buf = apr_pstrcat(p, "LIST -lag", CRLF, NULL);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: LIST %s", (len == 0 ? "-lag" : path));
- }
- else {
-/* FIXME: Handle range requests - send REST */
- buf = apr_pstrcat(p, "RETR ", path, CRLF, NULL);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: RETR %s", path);
- }
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- /* RETR: 110, 125, 150, 226, 250, 421, 425, 426, 450, 451, 500, 501, 530, 550
- * NLST: 125, 150, 226, 250, 421, 425, 426, 450, 451, 500, 501, 502, 530 */
- /* 110 Restart marker reply. */
- /* 125 Data connection already open; transfer starting. */
- /* 150 File status okay; about to open data connection. */
- /* 226 Closing data connection. */
- /* 250 Requested file action okay, completed. */
- /* 421 Service not available, closing control connection. */
- /* 425 Can't open data connection. */
- /* 426 Connection closed; transfer aborted. */
- /* 450 Requested file action not taken. */
- /* 451 Requested action aborted. Local error in processing. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 530 Not logged in. */
- /* 550 Requested action not taken. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc == 550) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: RETR failed, trying LIST instead");
- parms = "d";
- buf = apr_pstrcat(p, "CWD ", path, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: CWD %s", path);
- /* possible results: 250, 421, 500, 501, 502, 530, 550 */
- /* 250 Requested file action okay, completed. */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 502 Command not implemented. */
- /* 530 Not logged in. */
- /* 550 Requested action not taken. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc == 550) {
- return ap_proxyerror(r, HTTP_NOT_FOUND, buffer);
- }
- if (rc != 250) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
-#ifdef AUTODETECT_PWD
- buf = apr_pstrcat(p, "PWD ", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: PWD");
- /* responses: 257, 500, 501, 502, 421, 550 */
- /* 257 "" */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 502 Command not implemented. */
- /* 550 Requested action not taken. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1 || rc == 421) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc == 550) {
- return ap_proxyerror(r, HTTP_NOT_FOUND, buffer);
- }
- if (rc == 257) {
- const char *dirp = buffer;
- apr_table_set(r->notes, "Directory-PWD", ap_getword_conf(r->pool, &dirp));
- }
-#endif /*AUTODETECT_PWD*/
-
- buf = apr_pstrcat(p, "LIST -lag", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: LIST -lag");
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1)
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc != 125 && rc != 150 && rc != 226 && rc != 250) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
- r->status = HTTP_OK;
- r->status_line = "200 OK";
-
- apr_rfc822_date(dates, r->request_time);
- apr_table_setn(r->headers_out, "Date", dates);
- apr_table_setn(r->headers_out, "Server", ap_get_server_version());
-
- /* set content-type */
- if (parms[0] == 'd') {
- r->content_type = "text/html";
- }
- else {
- if (r->content_type) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: Content-Type set to %s", r->content_type);
- }
- else {
- r->content_type = ap_default_type(r);
- }
- if (parms[0] != 'a' && size != NULL) {
- /* We "trust" the ftp server to really serve (size) bytes... */
- apr_table_setn(r->headers_out, "Content-Length", size);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: Content-Length set to %s", size);
- }
- }
- apr_table_setn(r->headers_out, "Content-Type", r->content_type);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: Content-Type set to %s", r->content_type);
-
- /* set content-encoding */
- if (r->content_encoding != NULL && r->content_encoding[0] != '\0') {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: Content-Encoding set to %s", r->content_encoding);
- apr_table_setn(r->headers_out, "Content-Encoding", r->content_encoding);
- }
-
- /* wait for connection */
- if (use_port) {
- for(;;)
- {
- rv = apr_accept(&remote_sock, local_sock, r->pool);
- if (rv == APR_EINTR) {
- continue;
- }
- else if (rv == APR_SUCCESS) {
- break;
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: failed to accept data connection");
- return HTTP_BAD_GATEWAY;
- }
- }
- }
-
- /* the transfer socket is now open, create a new connection */
- remote = ap_new_connection(p, r->server, remote_sock, r->connection->id);
- if (!remote) {
- /* the peer reset the connection already; ap_new_connection()
- * closed the socket */
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: an error occurred creating the transfer connection");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* set up the connection filters */
- ap_proxy_pre_http_connection(remote, NULL);
-
-
- /*
- * VI: Receive the Response
- * ------------------------
- *
- * Get response from the remote ftp socket, and pass it up the
- * filter chain.
- */
-
- /* send response */
- r->sent_bodyct = 1;
-
- if (parms[0] == 'd') {
- /* insert directory filter */
- ap_add_output_filter("PROXY_SEND_DIR", NULL, r, r->connection);
- }
-
- /* send body */
- if (!r->header_only) {
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: start body send");
-
- /* read the body, pass it to the output filters */
- while (ap_get_brigade(remote->input_filters, bb, AP_MODE_BLOCKING, &readbytes) == APR_SUCCESS) {
- if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(r->output_filters, bb);
- break;
- }
- if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS) {
- /* Ack! Phbtt! Die! User aborted! */
- break;
- }
- apr_brigade_cleanup(bb);
- }
- }
- ap_flush_conn(remote);
- apr_socket_close(remote->client_socket);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: Closing Data connection.");
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- apr_brigade_cleanup(bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: end body send");
-
- /*
- * VII: Clean Up
- * -------------
- *
- * If there are no KeepAlives, or if the connection has been signalled
- * to close, close the socket and clean up
- */
-
- /* finish */
- buf = apr_pstrcat(p, "QUIT", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: QUIT");
-
- /* responses: 221, 500 */
- /* 221 Service closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- ap_flush_conn(origin);
- apr_socket_close(origin->client_socket);
- apr_brigade_destroy(bb);
- return OK;
-}
-
-static void ap_proxy_ftp_register_hook(apr_pool_t *p)
-{
- /* hooks */
- proxy_hook_scheme_handler(ap_proxy_ftp_handler, NULL, NULL, APR_HOOK_MIDDLE);
- proxy_hook_canon_handler(ap_proxy_ftp_canon, NULL, NULL, APR_HOOK_MIDDLE);
- /* filters */
- ap_register_output_filter("PROXY_SEND_DIR", ap_proxy_send_dir_filter, AP_FTYPE_CONTENT);
-}
-
-module AP_MODULE_DECLARE_DATA proxy_ftp_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- NULL, /* command apr_table_t */
- ap_proxy_ftp_register_hook /* register hooks */
-};
diff --git a/modules/proxy/proxy_ftp.dsp b/modules/proxy/proxy_ftp.dsp
deleted file mode 100644
index 8e78cadad01..00000000000
--- a/modules/proxy/proxy_ftp.dsp
+++ /dev/null
@@ -1,107 +0,0 @@
-# Microsoft Developer Studio Project File - Name="proxy_ftp" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=proxy_ftp - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "proxy_ftp.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "proxy_ftp.mak" CFG="proxy_ftp - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "proxy_ftp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "proxy_ftp - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "proxy_ftp - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I "..\..\include" /I "..\..\os\win32" /I "..\http" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\proxy_ftp" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /machine:I386 /out:"Release/proxy_ftp.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_ftp
-# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /machine:I386 /out:"Release/proxy_ftp.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_ftp
-
-!ELSEIF "$(CFG)" == "proxy_ftp - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I "..\..\include" /I "..\..\os\win32" /I "..\http" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\proxy_ftp" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"Debug/proxy_ftp.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_ftp
-# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"Debug/proxy_ftp.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_ftp
-
-!ENDIF
-
-# Begin Target
-
-# Name "proxy_ftp - Win32 Release"
-# Name "proxy_ftp - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
-# Begin Source File
-
-SOURCE=.\proxy_ftp.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter ".h"
-# Begin Source File
-
-SOURCE=.\mod_proxy.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/modules/proxy/proxy_http.c b/modules/proxy/proxy_http.c
deleted file mode 100644
index d1992bcdd29..00000000000
--- a/modules/proxy/proxy_http.c
+++ /dev/null
@@ -1,839 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 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
- * the documentation and/or other materials provided with the
- * 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.
- */
-
-/* HTTP routines for Apache proxy */
-
-#include "mod_proxy.h"
-
-module AP_MODULE_DECLARE_DATA proxy_http_module;
-
-int ap_proxy_http_canon(request_rec *r, char *url);
-int ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,
- char *url, const char *proxyname,
- apr_port_t proxyport);
-
-
-/*
- * Canonicalise http-like URLs.
- * scheme is the scheme for the URL
- * url is the URL starting with the first '/'
- * def_port is the default port for this scheme.
- */
-int ap_proxy_http_canon(request_rec *r, char *url)
-{
- char *host, *path, *search, sport[7];
- const char *err;
- const char *scheme;
- apr_port_t port, def_port;
-
- /* ap_default_port_for_scheme() */
- if (strncasecmp(url, "http:", 5) == 0) {
- url += 5;
- scheme = "http";
- }
- else if (strncasecmp(url, "https:", 6) == 0) {
- url += 6;
- scheme = "https:";
- }
- else {
- return DECLINED;
- }
- def_port = apr_uri_default_port_for_scheme(scheme);
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: HTTP: canonicalising URL %s", url);
-
- /* do syntatic check.
- * We break the URL into host, port, path, search
- */
- port = def_port;
- err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
- if (err)
- return HTTP_BAD_REQUEST;
-
- /* now parse path/search args, according to rfc1738 */
- /* N.B. if this isn't a true proxy request, then the URL _path_
- * has already been decoded. True proxy requests have r->uri
- * == r->unparsed_uri, and no others have that property.
- */
- if (r->uri == r->unparsed_uri) {
- search = strchr(url, '?');
- if (search != NULL)
- *(search++) = '\0';
- }
- else
- search = r->args;
-
- /* process path */
- path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq);
- if (path == NULL)
- return HTTP_BAD_REQUEST;
-
- if (port != def_port)
- apr_snprintf(sport, sizeof(sport), ":%d", port);
- else
- sport[0] = '\0';
-
- r->filename = apr_pstrcat(r->pool, "proxy:", scheme, "://", host, sport, "/",
- path, (search) ? "?" : "", (search) ? search : "", NULL);
- return OK;
-}
-
-static const char *ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url)
-{
- struct proxy_alias *ent;
- int i, l1, l2;
- char *u;
-
- /* XXX FIXME: Make sure this handled the ambiguous case of the :80
- * after the hostname */
-
- l1 = strlen(url);
- ent = (struct proxy_alias *)conf->raliases->elts;
- for (i = 0; i < conf->raliases->nelts; i++) {
- l2 = strlen(ent[i].real);
- if (l1 >= l2 && strncmp(ent[i].real, url, l2) == 0) {
- u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
- return ap_construct_url(r->pool, u, r);
- }
- }
- return url;
-}
-
-/* Clear all connection-based headers from the incoming headers table */
-static void ap_proxy_clear_connection(apr_pool_t *p, apr_table_t *headers)
-{
- const char *name;
- char *next = apr_pstrdup(p, apr_table_get(headers, "Connection"));
-
- apr_table_unset(headers, "Proxy-Connection");
- if (!next)
- return;
-
- while (*next) {
- name = next;
- while (*next && !apr_isspace(*next) && (*next != ','))
- ++next;
- while (*next && (apr_isspace(*next) || (*next == ','))) {
- *next = '\0';
- ++next;
- }
- apr_table_unset(headers, name);
- }
- apr_table_unset(headers, "Connection");
-}
-
-/*
- * This handles http:// URLs, and other URLs using a remote proxy over http
- * If proxyhost is NULL, then contact the server directly, otherwise
- * go via the proxy.
- * Note that if a proxy is used, then URLs other than http: can be accessed,
- * also, if we have trouble which is clearly specific to the proxy, then
- * we return DECLINED so that we can try another proxy. (Or the direct
- * route.)
- */
-int ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,
- char *url, const char *proxyname,
- apr_port_t proxyport)
-{
- request_rec *rp;
- const char *connectname;
- int connectport = 0;
- apr_sockaddr_t *uri_addr;
- apr_sockaddr_t *connect_addr;
- char server_portstr[32];
- apr_socket_t *sock;
- int i, len, backasswards, eos, close=0, failed=0, new=0;
- apr_status_t err, rv;
- apr_array_header_t *headers_in_array;
- apr_table_entry_t *headers_in;
- char buffer[HUGE_STRING_LEN];
- char *buf;
- conn_rec *origin = NULL;
- apr_uri_components uri;
- proxy_conn_rec *backend;
-
- /* Note: Memory pool allocation.
- * A downstream keepalive connection is always connected to the existence
- * (or not) of an upstream keepalive connection. If this is not done then
- * load balancing against multiple backend servers breaks (one backend
- * server ends up taking 100% of the load), and the risk is run of
- * downstream keepalive connections being kept open unnecessarily. This
- * keeps webservers busy and ties up resources.
- *
- * As a result, we allocate all sockets out of the upstream connection
- * pool, and when we want to reuse a socket, we check first whether the
- * connection ID of the current upstream connection is the same as that
- * of the connection when the socket was opened.
- */
- apr_pool_t *p = r->connection->pool;
- conn_rec *c = r->connection;
- apr_bucket *e;
- apr_bucket_brigade *bb = apr_brigade_create(p);
-
- /* is it for us? */
- if (strncasecmp(url, "http:", 5)) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: HTTP: rejecting URL %s", url);
- return DECLINED; /* only interested in HTTP */
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: HTTP: serving URL %s", url);
-
- /* create space for state information */
- backend = (proxy_conn_rec *) ap_get_module_config(c->conn_config, &proxy_http_module);
- if (!backend) {
- backend = ap_pcalloc(c->pool, sizeof(proxy_conn_rec));
- backend->connection = NULL;
- backend->hostname = NULL;
- backend->port = 0;
- ap_set_module_config(c->conn_config, &proxy_http_module, backend);
- }
-
- /*
- * Step One: Determine Who To Connect To
- *
- * Break up the URL to determine the host to connect to
- */
-
- /* we break the URL into host, port, uri */
- if (APR_SUCCESS != apr_uri_parse_components(p, url, &uri)) {
- return ap_proxyerror(r, HTTP_BAD_REQUEST,
- apr_pstrcat(p,"URI cannot be parsed: ", url, NULL));
- }
- if (!uri.port) {
- uri.port = apr_uri_default_port_for_scheme(uri.scheme);
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: HTTP connecting %s to %s:%d", url, uri.hostname, uri.port);
-
- /* do a DNS lookup for the destination host */
- /* see memory note above */
- err = apr_sockaddr_info_get(&uri_addr, apr_pstrdup(c->pool, uri.hostname), APR_UNSPEC, uri.port, 0, c->pool);
-
- /* allocate these out of the connection pool - the check on r->connection->id makes
- * sure that this string does not get accessed past the connection lifetime */
- /* are we connecting directly, or via a proxy? */
- if (proxyname) {
- connectname = apr_pstrdup(c->pool,proxyname);
- connectport = proxyport;
- /* see memory note above */
- err = apr_sockaddr_info_get(&connect_addr, connectname, APR_UNSPEC, connectport, 0, c->pool);
- }
- else {
- connectname = apr_pstrdup(c->pool, uri.hostname);
- connectport = uri.port;
- connect_addr = uri_addr;
- url = apr_pstrcat(p, uri.path, uri.query ? "?" : "",
- uri.query ? uri.query : "", uri.fragment ? "#" : "",
- uri.fragment ? uri.fragment : "", NULL);
- }
-
-
- /* Get the server port for the Via headers */
- {
- i = ap_get_server_port(r);
- if (ap_is_default_port(i,r)) {
- strcpy(server_portstr,"");
- } else {
- apr_snprintf(server_portstr, sizeof server_portstr, ":%d", i);
- }
- }
-
- /* check if ProxyBlock directive on this host */
- if (OK != ap_proxy_checkproxyblock(r, conf, uri_addr)) {
- return ap_proxyerror(r, HTTP_FORBIDDEN,
- "Connect to remote machine blocked");
- }
-
-
- /*
- * Step Two: Make the Connection
- *
- * We have determined who to connect to. Now make the connection, supporting
- * a KeepAlive connection.
- */
-
- /* get all the possible IP addresses for the destname and loop through them
- * until we get a successful connection
- */
- if (APR_SUCCESS != err) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p,
- "DNS lookup failure for: ",
- connectname, NULL));
- }
-
- /* if a keepalive socket is already open, check whether it must stay
- * open, or whether it should be closed and a new socket created.
- */
- /* see memory note above */
- if (backend->connection) {
- if ((backend->connection->id == c->id) &&
- (backend->port == connectport) &&
- (backend->hostname) &&
- (!apr_strnatcasecmp(backend->hostname,connectname))) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: keepalive address match (keep original socket)");
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: keepalive address mismatch / connection has"
- " changed (close old socket (%s/%s, %d/%d))",
- connectname, backend->hostname,
- connectport, backend->port);
- apr_socket_close(backend->connection->client_socket);
- backend->connection = NULL;
- }
- }
-
- /* get a socket - either a keepalive one, or a new one */
- new = 1;
- if ((backend->connection) && (backend->connection->id == c->id)) {
-
- /* use previous keepalive socket */
- origin = backend->connection;
- sock = origin->client_socket;
- new = 0;
-
- /* reset the connection filters */
- ap_proxy_reset_output_filters(origin);
-
- /* XXX FIXME: If the socket has since closed, change new to 1 so
- * a new socket is opened */
- }
- if (new) {
-
- /* create a new socket */
- backend->connection = NULL;
-
- /* see memory note above */
- if ((rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, c->pool)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "proxy: error creating socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-#if !defined(TPF) && !defined(BEOS)
- if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(sock, APR_SO_RCVBUF,
- conf->recv_buffer_size))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
- }
-#endif
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: socket has been created");
-
- /*
- * At this point we have a list of one or more IP addresses of
- * the machine to connect to. If configured, reorder this
- * list so that the "best candidate" is first try. "best
- * candidate" could mean the least loaded server, the fastest
- * responding server, whatever.
- *
- * For now we do nothing, ie we get DNS round robin.
- * XXX FIXME
- */
-
-
- /* try each IP address until we connect successfully */
- failed = 1;
- while (connect_addr) {
-
- /* make the connection out of the socket */
- rv = apr_connect(sock, connect_addr);
-
- /* if an error occurred, loop round and try again */
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "proxy: attempt to connect to %pI (%s) failed",
- connect_addr, connectname);
- connect_addr = connect_addr->next;
- continue;
- }
-
- /* if we get here, all is well */
- failed = 0;
- break;
- }
-
- /* handle a permanent error from the above loop */
- if (failed) {
- apr_socket_close(sock);
- if (proxyname) {
- return DECLINED;
- }
- else {
- return HTTP_BAD_GATEWAY;
- }
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: socket is connected");
-
- /* the socket is now open, create a new backend server connection */
- origin = ap_new_connection(c->pool, r->server, sock, r->connection->id);
- if (!origin) {
- /* the peer reset the connection already; ap_new_connection()
- * closed the socket */
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: an error occurred creating a new connection to %pI (%s)", connect_addr, connectname);
- apr_socket_close(sock);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- backend->connection = origin;
- backend->hostname = apr_pstrdup(c->pool, connectname);
- backend->port = connectport;
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: connection complete");
-
- /* set up the connection filters */
- ap_proxy_pre_http_connection(origin, NULL);
-
- }
-
-
- /*
- * Step Three: Send the Request
- *
- * Send the HTTP/1.1 request to the remote server
- */
-
-
- /* strip connection listed hop-by-hop headers from the request */
- /* even though in theory a connection: close coming from the client
- * should not affect the connection to the server, it's unlikely
- * that subsequent client requests will hit this thread/process, so
- * we cancel server keepalive if the client does.
- */
- close += ap_proxy_liststr(apr_table_get(r->headers_in, "Connection"), "close");
- ap_proxy_clear_connection(p, r->headers_in);
- if (close) {
- apr_table_mergen(r->headers_in, "Connection", "close");
- origin->keepalive = 0;
- }
-
- buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.1" CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- if (uri.port_str && uri.port != DEFAULT_HTTP_PORT) {
- buf = apr_pstrcat(p, "Host: ", uri.hostname, ":", uri.port_str, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- }
- else {
- buf = apr_pstrcat(p, "Host: ", uri.hostname, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- }
-
- /* handle Via */
- if (conf->viaopt == via_block) {
- /* Block all outgoing Via: headers */
- apr_table_unset(r->headers_in, "Via");
- } else if (conf->viaopt != via_off) {
- /* Create a "Via:" request header entry and merge it */
- /* Generate outgoing Via: header with/without server comment: */
- apr_table_mergen(r->headers_in, "Via",
- (conf->viaopt == via_full)
- ? apr_psprintf(p, "%d.%d %s%s (%s)",
- HTTP_VERSION_MAJOR(r->proto_num),
- HTTP_VERSION_MINOR(r->proto_num),
- ap_get_server_name(r), server_portstr,
- AP_SERVER_BASEVERSION)
- : apr_psprintf(p, "%d.%d %s%s",
- HTTP_VERSION_MAJOR(r->proto_num),
- HTTP_VERSION_MINOR(r->proto_num),
- ap_get_server_name(r), server_portstr)
- );
- }
-
- /* X-Forwarded-*: handling
- *
- * XXX Privacy Note:
- * -----------------
- *
- * These request headers are only really useful when the mod_proxy
- * is used in a reverse proxy configuration, so that useful info
- * about the client can be passed through the reverse proxy and on
- * to the backend server, which may require the information to
- * function properly.
- *
- * In a forward proxy situation, these options are a potential
- * privacy violation, as information about clients behind the proxy
- * are revealed to arbitrary servers out there on the internet.
- *
- * The HTTP/1.1 Via: header is designed for passing client
- * information through proxies to a server, and should be used in
- * a forward proxy configuation instead of X-Forwarded-*. See the
- * ProxyVia option for details.
- */
-
- if (PROXYREQ_REVERSE == r->proxyreq) {
- const char *buf;
-
- /* Add X-Forwarded-For: so that the upstream has a chance to
- * determine, where the original request came from.
- */
- apr_table_mergen(r->headers_in, "X-Forwarded-For", r->connection->remote_ip);
-
- /* Add X-Forwarded-Host: so that upstream knows what the
- * original request hostname was.
- */
- if ((buf = apr_table_get(r->headers_in, "Host"))) {
- apr_table_mergen(r->headers_in, "X-Forwarded-Host", buf);
- }
-
- /* Add X-Forwarded-Server: so that upstream knows what the
- * name of this proxy server is (if there are more than one)
- * XXX: This duplicates Via: - do we strictly need it?
- */
- apr_table_mergen(r->headers_in, "X-Forwarded-Server",
- r->server->server_hostname);
- }
-
- /* send request headers */
- headers_in_array = apr_table_elts(r->headers_in);
- headers_in = (apr_table_entry_t *) headers_in_array->elts;
- for (i = 0; i < headers_in_array->nelts; i++) {
- if (headers_in[i].key == NULL || headers_in[i].val == NULL
-
- /* Clear out hop-by-hop request headers not to send
- * RFC2616 13.5.1 says we should strip these headers
- */
- || !apr_strnatcasecmp(headers_in[i].key, "Host") /* Already sent */
- || !apr_strnatcasecmp(headers_in[i].key, "Keep-Alive")
- || !apr_strnatcasecmp(headers_in[i].key, "TE")
- || !apr_strnatcasecmp(headers_in[i].key, "Trailer")
- || !apr_strnatcasecmp(headers_in[i].key, "Transfer-Encoding")
- || !apr_strnatcasecmp(headers_in[i].key, "Upgrade")
-
- /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be
- * suppressed if THIS server requested the authentication,
- * not when a frontend proxy requested it!
- *
- * The solution to this problem is probably to strip out
- * the Proxy-Authorisation header in the authorisation
- * code itself, not here. This saves us having to signal
- * somehow whether this request was authenticated or not.
- */
- || !apr_strnatcasecmp(headers_in[i].key, "Proxy-Authorization")
- || !apr_strnatcasecmp(headers_in[i].key, "Proxy-Authenticate"))
- continue;
-
- buf = apr_pstrcat(p, headers_in[i].key, ": ", headers_in[i].val, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
-
- }
-
- /* add empty line at the end of the headers */
- e = apr_bucket_pool_create(CRLF, strlen(CRLF), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
-
- ap_pass_brigade(origin->output_filters, bb);
-
- /* send the request data, if any. */
- if (ap_should_client_block(r)) {
- while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) {
- e = apr_bucket_pool_create(buffer, i, p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- apr_brigade_cleanup(bb);
- }
- }
-
-
- /*
- * Step Four: Receive the Response
- *
- * Get response from the remote server, and pass it up the
- * filter chain
- */
-
- rp = make_fake_req(origin, r);
-
- apr_brigade_cleanup(bb);
-
- if (APR_SUCCESS != (rv = ap_proxy_string_read(origin, bb, buffer, sizeof(buffer), &eos))) {
- apr_socket_close(sock);
- backend->connection = NULL;
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: error reading status line from remote server %s",
- connectname);
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- len = strlen(buffer);
-
- /* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */
- if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
- int major, minor;
-
- if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {
- major = 1;
- minor = 1;
- }
-
- /* If not an HTTP/1 message or if the status line was > 8192 bytes */
- else if ((buffer[5] != '1') || (len >= sizeof(buffer)-1)) {
- apr_socket_close(sock);
- backend->connection = NULL;
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- apr_pstrcat(p, "Corrupt status line returned by remote server: ", buffer, NULL));
- }
- backasswards = 0;
- buffer[--len] = '\0';
-
- buffer[12] = '\0';
- r->status = atoi(&buffer[9]);
-
- buffer[12] = ' ';
- r->status_line = apr_pstrdup(p, &buffer[9]);
-
- /* read the headers. */
- /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */
- /* Also, take care with headers with multiple occurences. */
-
- r->headers_out = ap_proxy_read_headers(r, rp, buffer, sizeof(buffer), origin);
- if (r->headers_out == NULL) {
- ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
- "proxy: bad HTTP/%d.%d header returned by %s (%s)",
- major, minor, r->uri, r->method);
- close += 1;
- }
- else
- {
- /* strip connection listed hop-by-hop headers from response */
- const char *buf;
- close += ap_proxy_liststr(apr_table_get(r->headers_out, "Connection"), "close");
- ap_proxy_clear_connection(p, r->headers_out);
- if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
- r->content_type = apr_pstrdup(p, buf);
- }
- }
-
- /* handle Via header in response */
- if (conf->viaopt != via_off && conf->viaopt != via_block) {
- /* create a "Via:" response header entry and merge it */
- ap_table_mergen(r->headers_out, "Via",
- (conf->viaopt == via_full)
- ? apr_psprintf(p, "%d.%d %s%s (%s)",
- HTTP_VERSION_MAJOR(r->proto_num),
- HTTP_VERSION_MINOR(r->proto_num),
- ap_get_server_name(r), server_portstr,
- AP_SERVER_BASEVERSION)
- : apr_psprintf(p, "%d.%d %s%s",
- HTTP_VERSION_MAJOR(r->proto_num),
- HTTP_VERSION_MINOR(r->proto_num),
- ap_get_server_name(r), server_portstr)
- );
- }
-
- /* cancel keepalive if HTTP/1.0 or less */
- if ((major < 1) || (minor < 1)) {
- close += 1;
- origin->keepalive = 0;
- }
- }
- else {
- /* an http/0.9 response */
- backasswards = 1;
- r->status = 200;
- r->status_line = "200 OK";
- close += 1;
- }
-
- /* we must accept 3 kinds of date, but generate only 1 kind of date */
- {
- const char *buf;
- if ((buf = apr_table_get(r->headers_out, "Date")) != NULL) {
- apr_table_set(r->headers_out, "Date", ap_proxy_date_canon(p, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "Expires")) != NULL) {
- apr_table_set(r->headers_out, "Expires", ap_proxy_date_canon(p, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "Last-Modified")) != NULL) {
- apr_table_set(r->headers_out, "Last-Modified", ap_proxy_date_canon(p, buf));
- }
- }
-
- /* munge the Location and URI response headers according to ProxyPassReverse */
- {
- const char *buf;
- if ((buf = apr_table_get(r->headers_out, "Location")) != NULL) {
- apr_table_set(r->headers_out, "Location", ap_proxy_location_reverse_map(r, conf, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "Content-Location")) != NULL) {
- apr_table_set(r->headers_out, "Content-Location", ap_proxy_location_reverse_map(r, conf, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "URI")) != NULL) {
- apr_table_set(r->headers_out, "URI", ap_proxy_location_reverse_map(r, conf, buf));
- }
- }
-
- r->sent_bodyct = 1;
- /* Is it an HTTP/0.9 response? If so, send the extra data */
- if (backasswards) {
- apr_ssize_t cntr = len;
- e = apr_bucket_heap_create(buffer, cntr, 0, NULL);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- }
-
- /* send body - but only if a body is expected */
- if ((!r->header_only) && /* not HEAD request */
- (r->status > 199) && /* not any 1xx response */
- (r->status != HTTP_NO_CONTENT) && /* not 204 */
- (r->status != HTTP_RESET_CONTENT) && /* not 205 */
- (r->status != HTTP_NOT_MODIFIED)) { /* not 304 */
-
- const char *buf;
- apr_size_t readbytes;
-
- /* if chunked - insert DECHUNK filter */
- if (ap_proxy_liststr((buf = apr_table_get(r->headers_out, "Transfer-Encoding")), "chunked")) {
- rp->read_chunked = 1;
- apr_table_unset(r->headers_out, "Transfer-Encoding");
- if ((buf = ap_proxy_removestr(r->pool, buf, "chunked"))) {
- apr_table_set(r->headers_out, "Transfer-Encoding", buf);
- }
- ap_add_input_filter("DECHUNK", NULL, rp, origin);
- readbytes = -1;
- }
-
- /* if content length - set the length to read */
- else if ((buf = apr_table_get(r->headers_out, "Content-Length"))) {
- readbytes = atol(buf);
- }
-
- /* no chunked / no length therefore read till EOF and cancel keepalive */
- else {
- close += 1;
- }
-
- /* if keepalive cancelled, read to EOF */
- if (close) {
- readbytes = -1;
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: start body send");
-
- /* read the body, pass it to the output filters */
- while (ap_get_brigade(rp->input_filters, bb, AP_MODE_BLOCKING, &readbytes) == APR_SUCCESS) {
- if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(r->output_filters, bb);
- break;
- }
- if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS) {
- /* Ack! Phbtt! Die! User aborted! */
- close = 1; /* this causes socket close below */
- break;
- }
- apr_brigade_cleanup(bb);
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: end body send");
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: header only");
- }
-
-
- /*
- * Step Five: Clean Up
- *
- * If there are no KeepAlives, or if the connection has been signalled
- * to close, close the socket and clean up
- */
-
- /* if the connection is < HTTP/1.1, or Connection: close,
- * we close the socket, otherwise we leave it open for KeepAlive support
- */
- if (close || (r->proto_num < HTTP_VERSION(1,1))) {
- apr_socket_close(sock);
- backend->connection = NULL;
- }
-
- return OK;
-}
-
-static void ap_proxy_http_register_hook(apr_pool_t *p)
-{
- proxy_hook_scheme_handler(ap_proxy_http_handler, NULL, NULL, APR_HOOK_FIRST);
- proxy_hook_canon_handler(ap_proxy_http_canon, NULL, NULL, APR_HOOK_FIRST);
-}
-
-module AP_MODULE_DECLARE_DATA proxy_http_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- NULL, /* command apr_table_t */
- ap_proxy_http_register_hook /* register hooks */
-};
diff --git a/modules/proxy/proxy_http.dsp b/modules/proxy/proxy_http.dsp
deleted file mode 100644
index 1bd28615734..00000000000
--- a/modules/proxy/proxy_http.dsp
+++ /dev/null
@@ -1,107 +0,0 @@
-# Microsoft Developer Studio Project File - Name="proxy_http" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=proxy_http - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "proxy_http.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "proxy_http.mak" CFG="proxy_http - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "proxy_http - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "proxy_http - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "proxy_http - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I "..\..\include" /I "..\..\os\win32" /I "..\http" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\proxy_http" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /machine:I386 /out:"Release/proxy_http.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_http
-# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /machine:I386 /out:"Release/proxy_http.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_http
-
-!ELSEIF "$(CFG)" == "proxy_http - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I "..\..\include" /I "..\..\os\win32" /I "..\http" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\proxy_http" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"Debug/proxy_http.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_http
-# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"Debug/proxy_http.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_http
-
-!ENDIF
-
-# Begin Target
-
-# Name "proxy_http - Win32 Release"
-# Name "proxy_http - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
-# Begin Source File
-
-SOURCE=.\proxy_http.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter ".h"
-# Begin Source File
-
-SOURCE=.\mod_proxy.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
deleted file mode 100644
index b52f874fb35..00000000000
--- a/modules/proxy/proxy_util.c
+++ /dev/null
@@ -1,1189 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 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
- * the documentation and/or other materials provided with the
- * 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.
- */
-
-/* Utility routines for Apache proxy */
-#include "mod_proxy.h"
-
-
-static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
-static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
-static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r);
-static int proxy_match_word(struct dirconn_entry *This, request_rec *r);
-static struct per_thread_data *get_per_thread_data(void);
-
-/* already called in the knowledge that the characters are hex digits */
-PROXY_DECLARE(int) ap_proxy_hex2c(const char *x)
-{
- int i, ch;
-
-#if !APR_CHARSET_EBCDIC
- ch = x[0];
- if (apr_isdigit(ch))
- i = ch - '0';
- else if (apr_isupper(ch))
- i = ch - ('A' - 10);
- else
- i = ch - ('a' - 10);
- i <<= 4;
-
- ch = x[1];
- if (apr_isdigit(ch))
- i += ch - '0';
- else if (apr_isupper(ch))
- i += ch - ('A' - 10);
- else
- i += ch - ('a' - 10);
- return i;
-#else /*APR_CHARSET_EBCDIC*/
- return (1 == sscanf(x, "%2x", &i)) ? os_toebcdic[i&0xFF] : 0;
-#endif /*APR_CHARSET_EBCDIC*/
-}
-
-PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x)
-{
-#if !APR_CHARSET_EBCDIC
- int i;
-
- x[0] = '%';
- i = (ch & 0xF0) >> 4;
- if (i >= 10)
- x[1] = ('A' - 10) + i;
- else
- x[1] = '0' + i;
-
- i = ch & 0x0F;
- if (i >= 10)
- x[2] = ('A' - 10) + i;
- else
- x[2] = '0' + i;
-#else /*APR_CHARSET_EBCDIC*/
- static const char ntoa[] = { "0123456789ABCDEF" };
- ch &= 0xFF;
- x[0] = '%';
- x[1] = ntoa[(os_toascii[ch]>>4)&0x0F];
- x[2] = ntoa[os_toascii[ch]&0x0F];
- x[3] = '\0';
-#endif /*APR_CHARSET_EBCDIC*/
-}
-
-/*
- * canonicalise a URL-encoded string
- */
-
-/*
- * Convert a URL-encoded string to canonical form.
- * It decodes characters which need not be encoded,
- * and encodes those which must be encoded, and does not touch
- * those which must not be touched.
- */
-PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
- int isenc)
-{
- int i, j, ch;
- char *y;
- char *allowed; /* characters which should not be encoded */
- char *reserved; /* characters which much not be en/de-coded */
-
-/* N.B. in addition to :@&=, this allows ';' in an http path
- * and '?' in an ftp path -- this may be revised
- *
- * Also, it makes a '+' character in a search string reserved, as
- * it may be form-encoded. (Although RFC 1738 doesn't allow this -
- * it only permits ; / ? : @ = & as reserved chars.)
- */
- if (t == enc_path)
- allowed = "$-_.+!*'(),;:@&=";
- else if (t == enc_search)
- allowed = "$-_.!*'(),;:@&=";
- else if (t == enc_user)
- allowed = "$-_.+!*'(),;@&=";
- else if (t == enc_fpath)
- allowed = "$-_.+!*'(),?:@&=";
- else /* if (t == enc_parm) */
- allowed = "$-_.+!*'(),?/:@&=";
-
- if (t == enc_path)
- reserved = "/";
- else if (t == enc_search)
- reserved = "+";
- else
- reserved = "";
-
- y = apr_palloc(p, 3 * len + 1);
-
- for (i = 0, j = 0; i < len; i++, j++) {
-/* always handle '/' first */
- ch = x[i];
- if (strchr(reserved, ch)) {
- y[j] = ch;
- continue;
- }
-/* decode it if not already done */
- if (isenc && ch == '%') {
- if (!ap_isxdigit(x[i + 1]) || !ap_isxdigit(x[i + 2]))
- return NULL;
- ch = ap_proxy_hex2c(&x[i + 1]);
- i += 2;
- if (ch != 0 && strchr(reserved, ch)) { /* keep it encoded */
- ap_proxy_c2hex(ch, &y[j]);
- j += 2;
- continue;
- }
- }
-/* recode it, if necessary */
- if (!apr_isalnum(ch) && !strchr(allowed, ch)) {
- ap_proxy_c2hex(ch, &y[j]);
- j += 2;
- }
- else
- y[j] = ch;
- }
- y[j] = '\0';
- return y;
-}
-
-/*
- * Parses network-location.
- * urlp on input the URL; on output the path, after the leading /
- * user NULL if no user/password permitted
- * password holder for password
- * host holder for host
- * port port number; only set if one is supplied.
- *
- * Returns an error string.
- */
-PROXY_DECLARE(char *)
- ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
- char **passwordp, char **hostp, apr_port_t *port)
-{
- apr_port_t i;
- char *strp, *host, *url = *urlp;
- char *user = NULL, *password = NULL;
-
- if (url[0] != '/' || url[1] != '/')
- return "Malformed URL";
- host = url + 2;
- url = strchr(host, '/');
- if (url == NULL)
- url = "";
- else
- *(url++) = '\0'; /* skip seperating '/' */
-
- /* find _last_ '@' since it might occur in user/password part */
- strp = strrchr(host, '@');
-
- if (strp != NULL) {
- *strp = '\0';
- user = host;
- host = strp + 1;
-
-/* find password */
- strp = strchr(user, ':');
- if (strp != NULL) {
- *strp = '\0';
- password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1);
- if (password == NULL)
- return "Bad %-escape in URL (password)";
- }
-
- user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1);
- if (user == NULL)
- return "Bad %-escape in URL (username)";
- }
- if (userp != NULL) {
- *userp = user;
- }
- if (passwordp != NULL) {
- *passwordp = password;
- }
-
- strp = strrchr(host, ':');
- if (strp != NULL) {
- *(strp++) = '\0';
-
- for (i = 0; strp[i] != '\0'; i++)
- if (!apr_isdigit(strp[i]))
- break;
-
- /* if (i == 0) the no port was given; keep default */
- if (strp[i] != '\0') {
- return "Bad port number in URL";
- } else if (i > 0) {
- *port = atoi(strp);
- if (*port > 65535)
- return "Port number in URL > 65535";
- }
- }
- ap_str_tolower(host); /* DNS names are case-insensitive */
- if (*host == '\0')
- return "Missing host in URL";
-/* check hostname syntax */
- for (i = 0; host[i] != '\0'; i++)
- if (!apr_isdigit(host[i]) && host[i] != '.')
- break;
- /* must be an IP address */
-#if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS)
- if (host[i] == '\0' && (inet_addr(host) == -1))
-#else
- if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
-#endif
- {
- return "Bad IP address in URL";
- }
-
-/* if (strchr(host,'.') == NULL && domain != NULL)
- host = pstrcat(p, host, domain, NULL);
- */
- *urlp = url;
- *hostp = host;
-
- return NULL;
-}
-
-static const char * const lwday[7] =
-{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
-
-/*
- * If the date is a valid RFC 850 date or asctime() date, then it
- * is converted to the RFC 1123 format, otherwise it is not modified.
- * This routine is not very fast at doing conversions, as it uses
- * sscanf and sprintf. However, if the date is already correctly
- * formatted, then it exits very quickly.
- */
-PROXY_DECLARE(const char *)
- ap_proxy_date_canon(apr_pool_t *p, const char *x1)
-{
- char *x = apr_pstrdup(p, x1);
- int wk, mday, year, hour, min, sec, mon;
- char *q, month[4], zone[4], week[4];
-
- q = strchr(x, ',');
- /* check for RFC 850 date */
- if (q != NULL && q - x > 3 && q[1] == ' ') {
- *q = '\0';
- for (wk = 0; wk < 7; wk++)
- if (strcmp(x, lwday[wk]) == 0)
- break;
- *q = ',';
- if (wk == 7)
- return x; /* not a valid date */
- if (q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' ||
- q[17] != ':' || strcmp(&q[20], " GMT") != 0)
- return x;
- if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year,
- &hour, &min, &sec, zone) != 7)
- return x;
- if (year < 70)
- year += 2000;
- else
- year += 1900;
- }
- else {
-/* check for acstime() date */
- if (x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' ||
- x[16] != ':' || x[19] != ' ' || x[24] != '\0')
- return x;
- if (sscanf(x, "%3s %3s %u %u:%u:%u %u", week, month, &mday, &hour,
- &min, &sec, &year) != 7)
- return x;
- for (wk = 0; wk < 7; wk++)
- if (strcmp(week, ap_day_snames[wk]) == 0)
- break;
- if (wk == 7)
- return x;
- }
-
-/* check date */
- for (mon = 0; mon < 12; mon++)
- if (strcmp(month, ap_month_snames[mon]) == 0)
- break;
- if (mon == 12)
- return x;
-
- q = apr_palloc(p, 30);
- apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[wk],
- mday, ap_month_snames[mon], year, hour, min, sec);
- return q;
-}
-
-PROXY_DECLARE(request_rec *)make_fake_req(conn_rec *c, request_rec *r)
-{
- request_rec *rp = apr_pcalloc(c->pool, sizeof(*r));
- core_request_config *req_cfg;
-
- rp->pool = c->pool;
- rp->status = HTTP_OK;
-
- rp->headers_in = apr_table_make(c->pool, 50);
- rp->subprocess_env = apr_table_make(c->pool, 50);
- rp->headers_out = apr_table_make(c->pool, 12);
- rp->err_headers_out = apr_table_make(c->pool, 5);
- rp->notes = apr_table_make(c->pool, 5);
-
- rp->server = r->server;
- rp->request_time = r->request_time;
- rp->connection = c;
- rp->output_filters = c->output_filters;
- rp->input_filters = c->input_filters;
-
- rp->request_config = ap_create_request_config(c->pool);
- req_cfg = apr_pcalloc(rp->pool, sizeof(core_request_config));
- req_cfg->bb = apr_brigade_create(c->pool);
- ap_set_module_config(rp->request_config, &core_module, req_cfg);
-
- return rp;
-}
-
-/*
- * Reads headers from a buffer and returns an array of headers.
- * Returns NULL on file error
- * This routine tries to deal with too long lines and continuation lines.
- * @@@: XXX: FIXME: currently the headers are passed thru un-merged.
- * Is that okay, or should they be collapsed where possible?
- */
-PROXY_DECLARE(apr_table_t *)ap_proxy_read_headers(request_rec *r, request_rec *rr, char *buffer, int size, conn_rec *c)
-{
- apr_table_t *headers_out;
- int len;
- char *value, *end;
- char field[MAX_STRING_LEN];
-
- headers_out = ap_make_table(r->pool, 20);
-
- /*
- * Read header lines until we get the empty separator line, a read error,
- * the connection closes (EOF), or we timeout.
- */
- while ((len = ap_getline(buffer, size, rr, 1)) > 0) {
-
- if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */
-
- /* Buggy MS IIS servers sometimes return invalid headers
- * (an extra "HTTP/1.0 200, OK" line sprinkled in between
- * the usual MIME headers). Try to deal with it in a sensible
- * way, but log the fact.
- * XXX: The mask check is buggy if we ever see an HTTP/1.10 */
-
- if (!apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
- /* Nope, it wasn't even an extra HTTP header. Give up. */
- return NULL;
- }
-
- ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
- "proxy: Ignoring duplicate HTTP header "
- "returned by %s (%s)", r->uri, r->method);
- continue;
- }
-
- *value = '\0';
- ++value;
- /* XXX: RFC2068 defines only SP and HT as whitespace, this test is
- * wrong... and so are many others probably.
- */
- while (apr_isspace(*value))
- ++value; /* Skip to start of value */
-
- /* should strip trailing whitespace as well */
- for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
- *end = '\0';
-
- apr_table_add(headers_out, buffer, value);
-
- /* the header was too long; at the least we should skip extra data */
- if (len >= size - 1) {
- while ((len = ap_getline(field, MAX_STRING_LEN, rr, 1))
- >= MAX_STRING_LEN - 1) {
- /* soak up the extra data */
- }
- if (len == 0) /* time to exit the larger loop as well */
- break;
- }
- }
- return headers_out;
-}
-
-
-/*
- * list is a comma-separated list of case-insensitive tokens, with
- * optional whitespace around the tokens.
- * The return returns 1 if the token val is found in the list, or 0
- * otherwise.
- */
-PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val)
-{
- int len, i;
- const char *p;
-
- len = strlen(val);
-
- while (list != NULL) {
- p = ap_strchr_c(list, ',');
- if (p != NULL) {
- i = p - list;
- do
- p++;
- while (apr_isspace(*p));
- }
- else
- i = strlen(list);
-
- while (i > 0 && apr_isspace(list[i - 1]))
- i--;
- if (i == len && strncasecmp(list, val, len) == 0)
- return 1;
- list = p;
- }
- return 0;
-}
-
-/*
- * list is a comma-separated list of case-insensitive tokens, with
- * optional whitespace around the tokens.
- * The return returns 1 if the token val is found in the list, or 0
- * otherwise.
- */
-PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val)
-{
- int len, i;
- const char *p;
- char *new = NULL;
-
- len = strlen(val);
-
- while (list != NULL) {
- p = ap_strchr_c(list, ',');
- if (p != NULL) {
- i = p - list;
- do
- p++;
- while (apr_isspace(*p));
- }
- else
- i = strlen(list);
-
- while (i > 0 && apr_isspace(list[i - 1]))
- i--;
- if (i == len && strncasecmp(list, val, len) == 0) {
- /* do nothing */
- }
- else {
- if (new)
- new = apr_pstrcat(pool, new, ",", apr_pstrndup(pool, list, i), NULL);
- else
- new = apr_pstrndup(pool, list, i);
- }
- list = p;
- }
- return new;
-}
-
-/*
- * Converts 8 hex digits to a time integer
- */
-PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x)
-{
- int i, ch;
- unsigned int j;
-
- for (i = 0, j = 0; i < 8; i++) {
- ch = x[i];
- j <<= 4;
- if (apr_isdigit(ch))
- j |= ch - '0';
- else if (apr_isupper(ch))
- j |= ch - ('A' - 10);
- else
- j |= ch - ('a' - 10);
- }
- if (j == 0xffffffff)
- return -1; /* so that it works with 8-byte ints */
- else
- return j;
-}
-
-/*
- * Converts a time integer to 8 hex digits
- */
-PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y)
-{
- int i, ch;
- unsigned int j = t;
-
- for (i = 7; i >= 0; i--) {
- ch = j & 0xF;
- j >>= 4;
- if (ch >= 10)
- y[i] = ch + ('A' - 10);
- else
- y[i] = ch + '0';
- }
- y[8] = '\0';
-}
-
-PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message)
-{
- apr_table_setn(r->notes, "error-notes",
- apr_pstrcat(r->pool,
- "The proxy server could not handle the request "
- "pool, r->uri),
- "\">", ap_escape_html(r->pool, r->method),
- " ",
- ap_escape_html(r->pool, r->uri), ".\n"
- "Reason: ",
- ap_escape_html(r->pool, message),
- "", NULL));
-
- /* Allow "error-notes" string to be printed by ap_send_error_response() */
- apr_table_setn(r->notes, "verbose-error-to", apr_pstrdup(r->pool, "*"));
-
- r->status_line = apr_psprintf(r->pool, "%3.3u Proxy Error", statuscode);
- return statuscode;
-}
-
-/*
- * This routine returns its own error message
- */
-PROXY_DECLARE(const char *)ap_proxy_host2addr(const char *host, struct hostent *reqhp)
-{
- int i;
- struct hostent *hp;
- struct per_thread_data *ptd = get_per_thread_data();
-
- for (i = 0; host[i] != '\0'; i++)
- if (!apr_isdigit(host[i]) && host[i] != '.')
- break;
-
- if (host[i] != '\0') {
- hp = gethostbyname(host);
- if (hp == NULL)
- return "Host not found";
- }
- else {
- ptd->ipaddr = ap_inet_addr(host);
- hp = gethostbyaddr((char *) &ptd->ipaddr, sizeof(ptd->ipaddr), AF_INET);
- if (hp == NULL) {
- memset(&ptd->hpbuf, 0, sizeof(ptd->hpbuf));
- ptd->hpbuf.h_name = 0;
- ptd->hpbuf.h_addrtype = AF_INET;
- ptd->hpbuf.h_length = sizeof(ptd->ipaddr);
- ptd->hpbuf.h_addr_list = ptd->charpbuf;
- ptd->hpbuf.h_addr_list[0] = (char *) &ptd->ipaddr;
- ptd->hpbuf.h_addr_list[1] = 0;
- hp = &ptd->hpbuf;
- }
- }
- *reqhp = *hp;
- return NULL;
-}
-
-static const char *
- proxy_get_host_of_request(request_rec *r)
-{
- char *url, *user = NULL, *password = NULL, *err, *host;
- apr_port_t port = -1;
-
- if (r->hostname != NULL)
- return r->hostname;
-
- /* Set url to the first char after "scheme://" */
- if ((url = strchr(r->uri, ':')) == NULL
- || url[1] != '/' || url[2] != '/')
- return NULL;
-
- url = apr_pstrdup(r->pool, &url[1]); /* make it point to "//", which is what proxy_canon_netloc expects */
-
- err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port);
-
- if (err != NULL)
- ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
- "%s", err);
-
- r->hostname = host;
-
- return host; /* ought to return the port, too */
-}
-
-/* Return TRUE if addr represents an IP address (or an IP network address) */
-PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
-{
- const char *addr = This->name;
- long ip_addr[4];
- int i, quads;
- long bits;
-
- /* if the address is given with an explicit netmask, use that */
- /* Due to a deficiency in ap_inet_addr(), it is impossible to parse */
- /* "partial" addresses (with less than 4 quads) correctly, i.e. */
- /* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */
- /* I therefore have to parse the IP address manually: */
- /*if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr) == 0) */
- /* addr and mask were set by proxy_readmask() */
- /*return 1; */
-
- /* Parse IP addr manually, optionally allowing */
- /* abbreviated net addresses like 192.168. */
-
- /* Iterate over up to 4 (dotted) quads. */
- for (quads = 0; quads < 4 && *addr != '\0'; ++quads) {
- char *tmp;
-
- if (*addr == '/' && quads > 0) /* netmask starts here. */
- break;
-
- if (!apr_isdigit(*addr))
- return 0; /* no digit at start of quad */
-
- ip_addr[quads] = strtol(addr, &tmp, 0);
-
- if (tmp == addr) /* expected a digit, found something else */
- return 0;
-
- if (ip_addr[quads] < 0 || ip_addr[quads] > 255) {
- /* invalid octet */
- return 0;
- }
-
- addr = tmp;
-
- if (*addr == '.' && quads != 3)
- ++addr; /* after the 4th quad, a dot would be illegal */
- }
-
- for (This->addr.s_addr = 0, i = 0; i < quads; ++i)
- This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
-
- if (addr[0] == '/' && apr_isdigit(addr[1])) { /* net mask follows: */
- char *tmp;
-
- ++addr;
-
- bits = strtol(addr, &tmp, 0);
-
- if (tmp == addr) /* expected a digit, found something else */
- return 0;
-
- addr = tmp;
-
- if (bits < 0 || bits > 32) /* netmask must be between 0 and 32 */
- return 0;
-
- }
- else {
- /* Determine (i.e., "guess") netmask by counting the */
- /* number of trailing .0's; reduce #quads appropriately */
- /* (so that 192.168.0.0 is equivalent to 192.168.) */
- while (quads > 0 && ip_addr[quads - 1] == 0)
- --quads;
-
- /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */
- if (quads < 1)
- return 0;
-
- /* every zero-byte counts as 8 zero-bits */
- bits = 8 * quads;
-
- if (bits != 32) /* no warning for fully qualified IP address */
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld\n",
- inet_ntoa(This->addr), bits);
- }
-
- This->mask.s_addr = htonl(APR_INADDR_NONE << (32 - bits));
-
- if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Warning: NetMask and IP-Addr disagree in %s/%ld\n",
- inet_ntoa(This->addr), bits);
- This->addr.s_addr &= This->mask.s_addr;
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " Set to %s/%ld\n",
- inet_ntoa(This->addr), bits);
- }
-
- if (*addr == '\0') {
- This->matcher = proxy_match_ipaddr;
- return 1;
- }
- else
- return (*addr == '\0'); /* okay iff we've parsed the whole string */
-}
-
-/* Return TRUE if addr represents an IP address (or an IP network address) */
-static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r)
-{
- int i;
- int ip_addr[4];
- struct in_addr addr;
- struct in_addr *ip_list;
- char **ip_listptr;
- const char *found;
- const char *host = proxy_get_host_of_request(r);
-
- if (host == NULL) /* oops! */
- return 0;
-
- memset(&addr, '\0', sizeof addr);
- memset(ip_addr, '\0', sizeof ip_addr);
-
- if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
- for (addr.s_addr = 0, i = 0; i < 4; ++i)
- addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
-
- if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
-#if DEBUGGING
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "1)IP-Match: %s[%s] <-> ", host, inet_ntoa(addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s/", inet_ntoa(This->addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s", inet_ntoa(This->mask));
-#endif
- return 1;
- }
-#if DEBUGGING
- else {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "1)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s/", inet_ntoa(This->addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s", inet_ntoa(This->mask));
- }
-#endif
- }
- else {
- struct hostent the_host;
-
- memset(&the_host, '\0', sizeof the_host);
- found = ap_proxy_host2addr(host, &the_host);
-
- if (found != NULL) {
-#if DEBUGGING
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "2)IP-NoMatch: hostname=%s msg=%s", host, found);
-#endif
- return 0;
- }
-
- if (the_host.h_name != NULL)
- found = the_host.h_name;
- else
- found = host;
-
- /* Try to deal with multiple IP addr's for a host */
- for (ip_listptr = the_host.h_addr_list; *ip_listptr; ++ip_listptr) {
- ip_list = (struct in_addr *) *ip_listptr;
- if (This->addr.s_addr == (ip_list->s_addr & This->mask.s_addr)) {
-#if DEBUGGING
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "3)IP-Match: %s[%s] <-> ", found, inet_ntoa(*ip_list));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s/", inet_ntoa(This->addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s", inet_ntoa(This->mask));
-#endif
- return 1;
- }
-#if DEBUGGING
- else {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "3)IP-NoMatch: %s[%s] <-> ", found, inet_ntoa(*ip_list));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s/", inet_ntoa(This->addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s", inet_ntoa(This->mask));
- }
-#endif
- }
- }
-
- return 0;
-}
-
-/* Return TRUE if addr represents a domain name */
-PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p)
-{
- char *addr = This->name;
- int i;
-
- /* Domain name must start with a '.' */
- if (addr[0] != '.')
- return 0;
-
- /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
- for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i)
- continue;
-
-#if 0
- if (addr[i] == ':') {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "@@@@ handle optional port in proxy_is_domainname()");
- /* @@@@ handle optional port */
- }
-#endif
-
- if (addr[i] != '\0')
- return 0;
-
- /* Strip trailing dots */
- for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
- addr[i] = '\0';
-
- This->matcher = proxy_match_domainname;
- return 1;
-}
-
-/* Return TRUE if host "host" is in domain "domain" */
-static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r)
-{
- const char *host = proxy_get_host_of_request(r);
- int d_len = strlen(This->name), h_len;
-
- if (host == NULL) /* some error was logged already */
- return 0;
-
- h_len = strlen(host);
-
- /* @@@ do this within the setup? */
- /* Ignore trailing dots in domain comparison: */
- while (d_len > 0 && This->name[d_len - 1] == '.')
- --d_len;
- while (h_len > 0 && host[h_len - 1] == '.')
- --h_len;
- return h_len > d_len
- && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;
-}
-
-/* Create a copy of a "struct hostent" record; it was presumably returned
- * from a call to gethostbyname() and lives in static storage.
- * By creating a copy we can tuck it away for later use.
- */
-static struct hostent * pduphostent(apr_pool_t *p, const struct hostent *hp)
-{
- struct hostent *newent;
- char **ptrs;
- char **aliases;
- struct in_addr *addrs;
- int i = 0, j = 0;
-
- if (hp == NULL)
- return NULL;
-
- /* Count number of alias entries */
- if (hp->h_aliases != NULL)
- for (; hp->h_aliases[j] != NULL; ++j)
- continue;
-
- /* Count number of in_addr entries */
- if (hp->h_addr_list != NULL)
- for (; hp->h_addr_list[i] != NULL; ++i)
- continue;
-
- /* Allocate hostent structure, alias ptrs, addr ptrs, addrs */
- newent = (struct hostent *) apr_palloc(p, sizeof(*hp));
- aliases = (char **) apr_palloc(p, (j+1) * sizeof(char*));
- ptrs = (char **) apr_palloc(p, (i+1) * sizeof(char*));
- addrs = (struct in_addr *) apr_palloc(p, (i+1) * sizeof(struct in_addr));
-
- *newent = *hp;
- newent->h_name = apr_pstrdup(p, hp->h_name);
- newent->h_aliases = aliases;
- newent->h_addr_list = (char**) ptrs;
-
- /* Copy Alias Names: */
- for (j = 0; hp->h_aliases[j] != NULL; ++j) {
- aliases[j] = apr_pstrdup(p, hp->h_aliases[j]);
- }
- aliases[j] = NULL;
-
- /* Copy address entries */
- for (i = 0; hp->h_addr_list[i] != NULL; ++i) {
- ptrs[i] = (char*) &addrs[i];
- addrs[i] = *(struct in_addr *) hp->h_addr_list[i];
- }
- ptrs[i] = NULL;
-
- return newent;
-}
-
-/* Return TRUE if addr represents a host name */
-PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p)
-{
- struct hostent host;
- char *addr = This->name;
- int i;
-
- /* Host names must not start with a '.' */
- if (addr[0] == '.')
- return 0;
-
- /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
- for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i);
-
- if (addr[i] != '\0' || ap_proxy_host2addr(addr, &host) != NULL)
- return 0;
-
- This->hostentry = pduphostent (p, &host);
-
- /* Strip trailing dots */
- for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
- addr[i] = '\0';
-
- This->matcher = proxy_match_hostname;
- return 1;
-}
-
-/* Return TRUE if host "host" is equal to host2 "host2" */
-static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r)
-{
- char *host = This->name;
- const char *host2 = proxy_get_host_of_request(r);
- int h2_len;
- int h1_len;
-
- if (host == NULL || host2 == NULL)
- return 0; /* oops! */
-
- h2_len = strlen(host2);
- h1_len = strlen(host);
-
-#if 0
- unsigned long *ip_list;
-
- /* Try to deal with multiple IP addr's for a host */
- for (ip_list = *This->hostentry->h_addr_list; *ip_list != 0UL; ++ip_list)
- if (*ip_list == ? ? ? ? ? ? ? ? ? ? ? ? ?)
- return 1;
-#endif
-
- /* Ignore trailing dots in host2 comparison: */
- while (h2_len > 0 && host2[h2_len - 1] == '.')
- --h2_len;
- while (h1_len > 0 && host[h1_len - 1] == '.')
- --h1_len;
- return h1_len == h2_len
- && strncasecmp(host, host2, h1_len) == 0;
-}
-
-/* Return TRUE if addr is to be matched as a word */
-PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p)
-{
- This->matcher = proxy_match_word;
- return 1;
-}
-
-/* Return TRUE if string "str2" occurs literally in "str1" */
-static int proxy_match_word(struct dirconn_entry *This, request_rec *r)
-{
- const char *host = proxy_get_host_of_request(r);
- return host != NULL && ap_strstr_c(host, This->name) != NULL;
-}
-
-/* checks whether a host in uri_addr matches proxyblock */
-PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf,
- apr_sockaddr_t *uri_addr)
-{
- int j;
- /* XXX FIXME: conf->noproxies->elts is part of an opaque structure */
- for (j = 0; j < conf->noproxies->nelts; j++) {
- struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
- struct apr_sockaddr_t *conf_addr = npent[j].addr;
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: checking remote machine [%s] against [%s]", uri_addr->hostname, npent[j].name);
- if ((npent[j].name && ap_strstr_c(uri_addr->hostname, npent[j].name))
- || npent[j].name[0] == '*') {
- ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
- "proxy: connect to remote machine %s blocked: name %s matched", uri_addr->hostname, npent[j].name);
- return HTTP_FORBIDDEN;
- }
- while (conf_addr) {
- while (uri_addr) {
- char *conf_ip;
- char *uri_ip;
- apr_sockaddr_ip_get(&conf_ip, conf_addr);
- apr_sockaddr_ip_get(&uri_ip, uri_addr);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: ProxyBlock comparing %s and %s", conf_ip, uri_ip);
- if (!apr_strnatcasecmp(conf_ip, uri_ip)) {
- ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
- "proxy: connect to remote machine %s blocked: IP %s matched", uri_addr->hostname, conf_ip);
- return HTTP_FORBIDDEN;
- }
- uri_addr = uri_addr->next;
- }
- conf_addr = conf_addr->next;
- }
- }
- return OK;
-}
-
-/* set up the minimal filter set */
-PROXY_DECLARE(int) ap_proxy_pre_http_connection(conn_rec *c, request_rec *r)
-{
- ap_add_input_filter("HTTP_IN", NULL, r, c);
- ap_add_input_filter("CORE_IN", NULL, r, c);
- ap_add_output_filter("CORE", NULL, r, c);
- return OK;
-}
-
-/* converts a series of buckets into a string */
-PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb,
- char *buff, size_t bufflen, int *eos)
-{
- apr_bucket *e;
- apr_status_t rv;
- apr_size_t readbytes = 0; /* line-at-a-time */
- char *pos = buff;
- char *response;
- int found = 0;
- apr_size_t len;
-
- /* start with an empty string */
- buff[0] = 0;
- *eos = 0;
-
- /* loop through each brigade */
- while (!found) {
-
- /* get brigade from network one line at a time */
- if (APR_SUCCESS != (rv = ap_get_brigade(c->input_filters, bb, AP_MODE_BLOCKING, &readbytes))) {
- return rv;
- }
-
- /* loop through each bucket */
- while (!found && !APR_BRIGADE_EMPTY(bb)) {
- e = APR_BRIGADE_FIRST(bb);
- if (APR_BUCKET_IS_EOS(e)) {
- *eos = 1;
- }
- else {
- if (APR_SUCCESS != apr_bucket_read(e, (const char **)&response, &len, APR_BLOCK_READ)) {
- return rv;
- }
- /* is string LF terminated? */
- if (memchr(response, APR_ASCII_LF, len)) {
- found = 1;
- }
- /* concat strings until buff is full - then throw the data away */
- if (len > ((bufflen-1)-(pos-buff))) {
- len = (bufflen-1)-(pos-buff);
- }
- if (len > 0) {
- pos = apr_cpystrn(pos, response, len);
- }
- }
- APR_BUCKET_REMOVE(e);
- apr_bucket_destroy(e);
- }
- }
-
- return APR_SUCCESS;
-
-}
-
-/* remove other filters (like DECHUNK) from filter stack */
-PROXY_DECLARE(void) ap_proxy_reset_output_filters(conn_rec *c)
-{
- ap_filter_t *f = c->output_filters;
-
- while (f) {
- if (!strcasecmp(f->frec->name, "CORE") ||
- !strcasecmp(f->frec->name, "CONTENT_LENGTH") ||
- !strcasecmp(f->frec->name, "HTTP_HEADER")) {
- f = f->next;
- continue;
- }
- else {
- ap_remove_output_filter(f);
- f = f->next;
- }
- }
-}
-
-#if defined WIN32
-
-static DWORD tls_index;
-
-BOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
-{
- LPVOID memptr;
-
- switch (reason) {
- case DLL_PROCESS_ATTACH:
- tls_index = TlsAlloc();
- case DLL_THREAD_ATTACH: /* intentional no break */
- TlsSetValue (tls_index, malloc (sizeof (struct per_thread_data)));
- break;
- case DLL_THREAD_DETACH:
- memptr = TlsGetValue (tls_index);
- if (memptr) {
- free (memptr);
- TlsSetValue (tls_index, 0);
- }
- break;
- }
-
- return TRUE;
-}
-
-#endif
-
-static struct per_thread_data *get_per_thread_data(void)
-{
- return NULL;
-}
diff --git a/modules/test/mod_optional_fn_export.c b/modules/test/mod_optional_fn_export.c
deleted file mode 100644
index aea030e3fcd..00000000000
--- a/modules/test/mod_optional_fn_export.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 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
- * the documentation and/or other materials provided with the
- * 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
- * .
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "mod_optional_fn_export.h"
-
-/* The alert will note a strange mirror-image style resemblance to
- * mod_optional_hook_import.c. Yes, I _did_ mean import. Think about it.
- */
-
-static int TestOptionalFn(const char *szStr)
-{
- ap_log_error(APLOG_MARK,APLOG_ERR,OK,NULL,
- "Optional function test said: %s",szStr);
-
- return OK;
-}
-
-static void ExportRegisterHooks(apr_pool_t *p)
-{
- APR_REGISTER_OPTIONAL_FN(TestOptionalFn);
-}
-
-module optional_fn_export_module=
-{
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ExportRegisterHooks
-};
diff --git a/modules/test/mod_optional_fn_export.h b/modules/test/mod_optional_fn_export.h
deleted file mode 100644
index a1950f373bd..00000000000
--- a/modules/test/mod_optional_fn_export.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "apr_optional.h"
-
-APR_DECLARE_OPTIONAL_FN(int,TestOptionalFn,(const char *));
diff --git a/modules/test/mod_optional_fn_import.c b/modules/test/mod_optional_fn_import.c
deleted file mode 100644
index 72222105cbb..00000000000
--- a/modules/test/mod_optional_fn_import.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 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
- * the documentation and/or other materials provided with the
- * 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
- * .
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "mod_optional_fn_export.h"
-#include "http_protocol.h"
-
-/* The alert will note a strange mirror-image style resemblance to
- * mod_optional_hook_export.c. Yes, I _did_ mean export. Think about it.
- */
-
-static APR_OPTIONAL_FN_TYPE(TestOptionalFn) *pfn;
-
-static int ImportLogTransaction(request_rec *r)
-{
- if(pfn)
- return pfn(r->the_request);
- return DECLINED;
-}
-
-static void ImportFnRetrieve(void)
-{
- pfn=APR_RETRIEVE_OPTIONAL_FN(TestOptionalFn);
-}
-
-static void ImportRegisterHooks(apr_pool_t *p)
-{
- ap_hook_log_transaction(ImportLogTransaction,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_optional_fn_retrieve(ImportFnRetrieve,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module optional_fn_import_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ImportRegisterHooks
-};
diff --git a/modules/test/mod_optional_hook_export.c b/modules/test/mod_optional_hook_export.c
deleted file mode 100644
index e4e3c6493dd..00000000000
--- a/modules/test/mod_optional_hook_export.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 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
- * the documentation and/or other materials provided with the
- * 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
- * .
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "mod_optional_hook_export.h"
-#include "http_protocol.h"
-
-AP_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(int,optional_hook_test,(const char *szStr),
- (szStr),OK,DECLINED)
-
-static int ExportLogTransaction(request_rec *r)
-{
- return ap_run_optional_hook_test(r->the_request);
-}
-
-static void ExportRegisterHooks(apr_pool_t *p)
-{
- ap_hook_log_transaction(ExportLogTransaction,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module optional_hook_export_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ExportRegisterHooks
-};
diff --git a/modules/test/mod_optional_hook_export.h b/modules/test/mod_optional_hook_export.h
deleted file mode 100644
index e96418738b8..00000000000
--- a/modules/test/mod_optional_hook_export.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 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
- * the documentation and/or other materials provided with the
- * 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
- * .
- */
-
-#ifndef MOD_OPTIONAL_HOOK_EXPORT_H
-#define MOD_OPTOPNAL_HOOK_EXPORT_H
-
-#include "ap_config.h"
-
-AP_DECLARE_HOOK(int,optional_hook_test,(const char *))
-
-#endif /* def MOD_OPTIONAL_HOOK_EXPORT_H */
diff --git a/modules/test/mod_optional_hook_import.c b/modules/test/mod_optional_hook_import.c
deleted file mode 100644
index 3c5de7809d9..00000000000
--- a/modules/test/mod_optional_hook_import.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 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
- * the documentation and/or other materials provided with the
- * 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
- * .
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "mod_optional_hook_export.h"
-
-static int ImportOptionalHookTestHook(const char *szStr)
-{
- ap_log_error(APLOG_MARK,APLOG_ERR,OK,NULL,"Optional hook test said: %s",
- szStr);
-
- return OK;
-}
-
-static void ImportRegisterHooks(apr_pool_t *p)
-{
- AP_OPTIONAL_HOOK(optional_hook_test,ImportOptionalHookTestHook,NULL,
- NULL,APR_HOOK_MIDDLE);
-}
-
-module optional_hook_import_module=
-{
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ImportRegisterHooks
-};
diff --git a/server/mpm/experimental/perchild/.cvsignore b/server/mpm/experimental/perchild/.cvsignore
deleted file mode 100644
index 84df2572148..00000000000
--- a/server/mpm/experimental/perchild/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-.deps
-.libs
-*.lo
-*.la
-Makefile
diff --git a/server/mpm/experimental/perchild/Makefile.in b/server/mpm/experimental/perchild/Makefile.in
deleted file mode 100644
index 374f1306468..00000000000
--- a/server/mpm/experimental/perchild/Makefile.in
+++ /dev/null
@@ -1,5 +0,0 @@
-
-LTLIBRARY_NAME = libperchild.la
-LTLIBRARY_SOURCES = perchild.c
-
-include $(top_srcdir)/build/ltlib.mk
diff --git a/server/mpm/experimental/perchild/config5.m4 b/server/mpm/experimental/perchild/config5.m4
deleted file mode 100644
index bd179baed93..00000000000
--- a/server/mpm/experimental/perchild/config5.m4
+++ /dev/null
@@ -1,6 +0,0 @@
-dnl ## XXX - Need a more thorough check of the proper flags to use
-
-if test "$MPM_NAME" = "perchild" ; then
-
- APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile)
-fi
diff --git a/server/mpm/experimental/perchild/mpm.h b/server/mpm/experimental/perchild/mpm.h
deleted file mode 100644
index d24f8b4abaa..00000000000
--- a/server/mpm/experimental/perchild/mpm.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 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
- * the documentation and/or other materials provided with the
- * 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.
- */
-
-#include "httpd.h"
-#include "mpm_default.h"
-#include "unixd.h"
-
-#ifndef APACHE_MPM_PERCHILD_H
-#define APACHE_MPM_PERCHILD_H
-
-#define PERCHILD_MPM
-
-#define MPM_NAME "Perchild"
-
-#define AP_MPM_NEEDS_RECLAIM_CHILD_PROCESSES 1
-#define MPM_SYNC_CHILD_TABLE()
-#define MPM_CHILD_PID(i) (ap_child_table[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
-
-/* Table of child status */
-#define SERVER_DEAD 0
-#define SERVER_DYING 1
-#define SERVER_ALIVE 2
-
-typedef struct ap_ctable{
- pid_t pid;
- unsigned char status;
-} ap_ctable;
-
-extern int ap_threads_per_child;
-extern int ap_max_daemons_limit;
-extern ap_ctable ap_child_table[HARD_SERVER_LIMIT];
-extern server_rec *ap_server_conf;
-extern char ap_coredump_dir[MAX_STRING_LEN];
-
-#endif /* APACHE_MPM_PERCHILD_H */
diff --git a/server/mpm/experimental/perchild/mpm_default.h b/server/mpm/experimental/perchild/mpm_default.h
deleted file mode 100644
index f462ea8f901..00000000000
--- a/server/mpm/experimental/perchild/mpm_default.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 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
- * the documentation and/or other materials provided with the
- * 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.
- */
-
-#ifndef APACHE_MPM_DEFAULT_H
-#define APACHE_MPM_DEFAULT_H
-
-#define AP_ID_FROM_CHILD_THREAD(c, t) ((c * HARD_THREAD_LIMIT) + t)
-#define AP_CHILD_THREAD_FROM_ID(i) (i / HARD_THREAD_LIMIT), (i % HARD_THREAD_LIMIT)
-
-/* Number of threads to spawn off by default --- also, if fewer than
- * this free when the caretaker checks, it will spawn more.
- */
-#ifndef DEFAULT_START_THREAD
-#define DEFAULT_START_THREAD 5
-#endif
-
-/* Maximum number of *free* server threads --- more than this, and
- * they will die off.
- */
-
-#ifndef DEFAULT_MAX_SPARE_THREAD
-#define DEFAULT_MAX_SPARE_THREAD 10
-#endif
-
-/* Minimum --- fewer than this, and more will be created */
-
-#ifndef DEFAULT_MIN_SPARE_THREAD
-#define DEFAULT_MIN_SPARE_THREAD 5
-#endif
-
-/* Limit on the threads per process. Clients will be locked out if more than
- * this * HARD_SERVER_LIMIT are needed.
- *
- * We keep this for one reason it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifndef HARD_THREAD_LIMIT
-#define HARD_THREAD_LIMIT 64
-#endif
-
-/* Number of servers to spawn off by default
- */
-#ifndef DEFAULT_NUM_DAEMON
-#define DEFAULT_NUM_DAEMON 2
-#endif
-
-/* Limit on the total --- clients will be locked out if more servers than
- * this are needed. It is intended solely to keep the server from crashing
- * when things get out of hand.
- *
- * We keep a hard maximum number of servers, for two reasons --- first off,
- * in case something goes seriously wrong, we want to stop the fork bomb
- * short of actually crashing the machine we're running on by filling some
- * kernel table. Secondly, it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifndef HARD_SERVER_LIMIT
-#define HARD_SERVER_LIMIT 8
-#endif
-
-/* File used for accept locking, when we use a file */
-#ifndef DEFAULT_LOCKFILE
-#define DEFAULT_LOCKFILE "logs/accept.lock"
-#endif
-
-/* Scoreboard file, if there is one */
-#ifndef DEFAULT_SCOREBOARD
-#define DEFAULT_SCOREBOARD "logs/apache_runtime_status"
-#endif
-
-/* Where the main/parent process's pid is logged */
-#ifndef DEFAULT_PIDLOG
-#define DEFAULT_PIDLOG "logs/httpd.pid"
-#endif
-
-/*
- * Interval, in microseconds, between scoreboard maintenance.
- */
-#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
-#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
-#endif
-
-/* Number of requests to try to handle in a single process. If <= 0,
- * the children don't die off.
- */
-#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
-#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
-#endif
-
-#endif /* AP_MPM_DEFAULT_H */
diff --git a/server/mpm/experimental/perchild/perchild.c b/server/mpm/experimental/perchild/perchild.c
deleted file mode 100644
index c33cf6e6a99..00000000000
--- a/server/mpm/experimental/perchild/perchild.c
+++ /dev/null
@@ -1,1903 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 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
- * the documentation and/or other materials provided with the
- * 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.
- */
-
-#include "apr_hash.h"
-#include "apr_strings.h"
-#include "apr_pools.h"
-#include "apr_portable.h"
-#include "apr_file_io.h"
-#include "apr_signal.h"
-
-#define APR_WANT_IOVEC
-#include "apr_want.h"
-
-#if APR_HAVE_UNISTD_H
-#include
-#endif
-#if APR_HAVE_SYS_SOCKET_H
-#include
-#endif
-
-#if !APR_HAS_THREADS
-#error The perchild MPM requires APR threads, but they are unavailable.
-#endif
-
-#define CORE_PRIVATE
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_config.h" /* for read_config */
-#include "http_core.h" /* for get_remote_host */
-#include "http_protocol.h"
-#include "http_connection.h"
-#include "ap_mpm.h"
-#include "unixd.h"
-#include "mpm_common.h"
-#include "ap_listen.h"
-#include "mpm_default.h"
-#include "mpm.h"
-#include "scoreboard.h"
-#include "util_filter.h"
-
-/* ### should be APR-ized */
-#include
-#include
-#include
-#include
-#include
-#include
-#ifdef HAVE_SYS_PROCESSOR_H
-#include /* for bindprocessor() */
-#endif
-
-/*
- * Actual definitions of config globals
- */
-
-static int threads_to_start = 0; /* Worker threads per child */
-static int min_spare_threads = 0;
-static int max_spare_threads = 0;
-static int max_threads = 0;
-static int max_requests_per_child = 0;
-static const char *ap_pid_fname=NULL;
-static int num_daemons=0;
-static int curr_child_num=0;
-static int workers_may_exit = 0;
-static int requests_this_child;
-static int num_listenfds = 0;
-static apr_socket_t **listenfds;
-static jmp_buf jmpbuffer;
-
-struct child_info_t {
- uid_t uid;
- gid_t gid;
- int sd;
-};
-
-typedef struct {
- const char *sockname; /* The base name for the socket */
- const char *fullsockname; /* socket base name + extension */
- int sd; /* The socket descriptor */
- int sd2; /* The socket descriptor */
-} perchild_server_conf;
-
-typedef struct child_info_t child_info_t;
-
-/* Tables used to determine the user and group each child process should
- * run as. The hash table is used to correlate a server name with a child
- * process.
- */
-static child_info_t child_info_table[HARD_SERVER_LIMIT];
-static int thread_socket_table[HARD_THREAD_LIMIT];
-
-
-struct ap_ctable ap_child_table[HARD_SERVER_LIMIT];
-
-/*
- * The max child slot ever assigned, preserved across restarts. Necessary
- * to deal with NumServers changes across SIGWINCH restarts. We use this
- * value to optimize routines that have to scan the entire child table.
- *
- * XXX - It might not be worth keeping this code in. There aren't very
- * many child processes in this MPM.
- */
-int ap_max_daemons_limit = -1;
-int ap_threads_per_child = HARD_THREAD_LIMIT;
-
-char ap_coredump_dir[MAX_STRING_LEN];
-
-module AP_MODULE_DECLARE_DATA mpm_perchild_module;
-
-static apr_file_t *pipe_of_death_in = NULL;
-static apr_file_t *pipe_of_death_out = NULL;
-static apr_lock_t *pipe_of_death_mutex;
-
-/* *Non*-shared http_main globals... */
-
-server_rec *ap_server_conf;
-
-/* one_process --- debugging mode variable; can be set from the command line
- * with the -X flag. If set, this gets you the child_main loop running
- * in the process which originally started up (no detach, no make_child),
- * which is a pretty nice debugging environment. (You'll get a SIGHUP
- * early in standalone_main; just continue through. This is the server
- * trying to kill off any child processes which it might have lying
- * around --- Apache doesn't keep track of their pids, it just sends
- * SIGHUP to the process group, ignoring it in the root process.
- * Continue through and you'll be fine.).
- */
-
-static int one_process = 0;
-
-#ifdef DEBUG_SIGSTOP
-int raise_sigstop_flags;
-#endif
-
-static apr_pool_t *pconf; /* Pool for config stuff */
-static apr_pool_t *pchild; /* Pool for httpd child stuff */
-static apr_pool_t *thread_pool_parent; /* Parent of per-thread pools */
-static apr_lock_t *thread_pool_parent_mutex;
-
-static int child_num;
-static unsigned int my_pid; /* Linux getpid() doesn't work except in
- main thread. Use this instead */
-/* Keep track of the number of worker threads currently active */
-static int worker_thread_count;
-static apr_lock_t *worker_thread_count_mutex;
-static int worker_thread_free_ids[HARD_THREAD_LIMIT];
-static apr_threadattr_t *worker_thread_attr;
-
-/* Keep track of the number of idle worker threads */
-static int idle_thread_count;
-static apr_lock_t *idle_thread_count_mutex;
-
-/* Locks for accept serialization */
-#ifdef NO_SERIALIZED_ACCEPT
-#define SAFE_ACCEPT(stmt) APR_SUCCESS
-#else
-#define SAFE_ACCEPT(stmt) (stmt)
-static apr_lock_t *process_accept_mutex;
-static apr_lockmech_e_np accept_lock_mech = APR_LOCK_DEFAULT;
-#endif /* NO_SERIALIZED_ACCEPT */
-static const char *lock_fname;
-static apr_lock_t *thread_accept_mutex;
-
-AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
-{
- switch(query_code){
- case AP_MPMQ_MAX_DAEMONS:
- *result = ap_max_daemons_limit;
- return APR_SUCCESS;
- case AP_MPMQ_IS_THREADED:
- *result = AP_MPMQ_DYNAMIC;
- return APR_SUCCESS;
- case AP_MPMQ_IS_FORKED:
- *result = AP_MPMQ_STATIC;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_DAEMONS:
- *result = HARD_SERVER_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_THREADS:
- *result = HARD_THREAD_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_MAX_THREADS:
- *result = max_threads;
- return APR_SUCCESS;
- case AP_MPMQ_MIN_SPARE_DEAMONS:
- *result = 0;
- return APR_SUCCESS;
- case AP_MPMQ_MIN_SPARE_THREADS:
- *result = min_spare_threads;
- return APR_SUCCESS;
- case AP_MPMQ_MAX_SPARE_DAEMONS:
- *result = 0;
- return APR_SUCCESS;
- case AP_MPMQ_MAX_SPARE_THREADS:
- *result = max_spare_threads;
- return APR_SUCCESS;
- case AP_MPMQ_MAX_REQUESTS_DEAMON:
- *result = max_requests_per_child;
- return APR_SUCCESS;
- }
- return APR_ENOTIMPL;
-}
-
-/* a clean exit from a child with proper cleanup */
-static void clean_child_exit(int code)
-{
- if (pchild) {
- apr_pool_destroy(pchild);
- }
- exit(code);
-}
-
-/* handle all varieties of core dumping signals */
-static void sig_coredump(int sig)
-{
- chdir(ap_coredump_dir);
- apr_signal(sig, SIG_DFL);
- kill(getpid(), sig);
- /* At this point we've got sig blocked, because we're still inside
- * the signal handler. When we leave the signal handler it will
- * be unblocked, and we'll take the signal... and coredump or whatever
- * is appropriate for this particular Unix. In addition the parent
- * will see the real signal we received -- whereas if we called
- * abort() here, the parent would only see SIGABRT.
- */
-}
-
-static void just_die(int sig)
-{
- clean_child_exit(0);
-}
-
-/*****************************************************************
- * Connection structures and accounting...
- */
-
-/* volatile just in case */
-static int volatile shutdown_pending;
-static int volatile restart_pending;
-static int volatile is_graceful;
-/* we don't currently track ap_my_generation, but mod_status
- * references it so it must be defined */
-ap_generation_t volatile ap_my_generation=0;
-
-/*
- * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
- * functions to initiate shutdown or restart without relying on signals.
- * Previously this was initiated in sig_term() and restart() signal handlers,
- * but we want to be able to start a shutdown/restart from other sources --
- * e.g. on Win32, from the service manager. Now the service manager can
- * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
- * these functions can also be called by the child processes, since global
- * variables are no longer used to pass on the required action to the parent.
- *
- * These should only be called from the parent process itself, since the
- * parent process will use the shutdown_pending and restart_pending variables
- * to determine whether to shutdown or restart. The child process should
- * call signal_parent() directly to tell the parent to die -- this will
- * cause neither of those variable to be set, which the parent will
- * assume means something serious is wrong (which it will be, for the
- * child to force an exit) and so do an exit anyway.
- */
-
-static void ap_start_shutdown(void)
-{
- if (shutdown_pending == 1) {
- /* Um, is this _probably_ not an error, if the user has
- * tried to do a shutdown twice quickly, so we won't
- * worry about reporting it.
- */
- return;
- }
- shutdown_pending = 1;
-}
-
-/* do a graceful restart if graceful == 1 */
-static void ap_start_restart(int graceful)
-{
-
- if (restart_pending == 1) {
- /* Probably not an error - don't bother reporting it */
- return;
- }
- restart_pending = 1;
- is_graceful = graceful;
- if (is_graceful) {
- apr_pool_cleanup_kill(pconf, NULL, ap_cleanup_scoreboard);
- }
-}
-
-static void sig_term(int sig)
-{
- ap_start_shutdown();
-}
-
-static void restart(int sig)
-{
-#ifndef WIN32
- ap_start_restart(sig == SIGWINCH);
-#else
- ap_start_restart(1);
-#endif
-}
-
-static void set_signals(void)
-{
-#ifndef NO_USE_SIGACTION
- struct sigaction sa;
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
-
- if (!one_process) {
- sa.sa_handler = sig_coredump;
-#if defined(SA_ONESHOT)
- sa.sa_flags = SA_ONESHOT;
-#elif defined(SA_RESETHAND)
- sa.sa_flags = SA_RESETHAND;
-#endif
- if (sigaction(SIGSEGV, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");
-#ifdef SIGBUS
- if (sigaction(SIGBUS, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");
-#endif
-#ifdef SIGABORT
- if (sigaction(SIGABORT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");
-#endif
-#ifdef SIGABRT
- if (sigaction(SIGABRT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");
-#endif
-#ifdef SIGILL
- if (sigaction(SIGILL, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");
-#endif
- sa.sa_flags = 0;
- }
- sa.sa_handler = sig_term;
- if (sigaction(SIGTERM, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
-#ifdef SIGINT
- if (sigaction(SIGINT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
-#endif
-#ifdef SIGXCPU
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXCPU, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
-#endif
-#ifdef SIGXFSZ
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXFSZ, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
-#endif
-#ifdef SIGPIPE
- sa.sa_handler = SIG_IGN;
- if (sigaction(SIGPIPE, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
-#endif
-
- /* we want to ignore HUPs and WINCH while we're busy processing one */
- sigaddset(&sa.sa_mask, SIGHUP);
- sigaddset(&sa.sa_mask, SIGWINCH);
- sa.sa_handler = restart;
- if (sigaction(SIGHUP, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
- if (sigaction(SIGWINCH, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGWINCH)");
-#else
- if (!one_process) {
- apr_signal(SIGSEGV, sig_coredump);
-#ifdef SIGBUS
- apr_signal(SIGBUS, sig_coredump);
-#endif /* SIGBUS */
-#ifdef SIGABORT
- apr_signal(SIGABORT, sig_coredump);
-#endif /* SIGABORT */
-#ifdef SIGABRT
- apr_signal(SIGABRT, sig_coredump);
-#endif /* SIGABRT */
-#ifdef SIGILL
- apr_signal(SIGILL, sig_coredump);
-#endif /* SIGILL */
-#ifdef SIGXCPU
- apr_signal(SIGXCPU, SIG_DFL);
-#endif /* SIGXCPU */
-#ifdef SIGXFSZ
- apr_signal(SIGXFSZ, SIG_DFL);
-#endif /* SIGXFSZ */
- }
-
- apr_signal(SIGTERM, sig_term);
-#ifdef SIGHUP
- apr_signal(SIGHUP, restart);
-#endif /* SIGHUP */
-#ifdef SIGWINCH
- apr_signal(SIGWINCH, restart);
-#endif /* SIGWINCH */
-#ifdef SIGPIPE
- apr_signal(SIGPIPE, SIG_IGN);
-#endif /* SIGPIPE */
-
-#endif
-}
-
-/*****************************************************************
- * Here follows a long bunch of generic server bookkeeping stuff...
- */
-
-int ap_graceful_stop_signalled(void)
-{
- /* XXX - Does this really work? - Manoj */
- return is_graceful;
-}
-
-/*****************************************************************
- * Child process main loop.
- */
-
-static void process_socket(apr_pool_t *p, apr_socket_t *sock, long conn_id)
-{
- conn_rec *current_conn;
- int csd;
- apr_status_t rv;
- int thread_num = conn_id % HARD_THREAD_LIMIT;
-
- if ((rv = apr_os_sock_get(&csd, sock)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, "apr_os_sock_get");
- }
-
- if (csd >= FD_SETSIZE) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
- "new file descriptor %d is too large; you probably need "
- "to rebuild Apache with a larger FD_SETSIZE "
- "(currently %d)",
- csd, FD_SETSIZE);
- apr_socket_close(sock);
- return;
- }
-
- if (thread_socket_table[thread_num] < 0) {
- ap_sock_disable_nagle(sock);
- }
-
- current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id);
- if (current_conn) {
- ap_process_connection(current_conn);
- ap_lingering_close(current_conn);
- }
-}
-
-static void *worker_thread(void *);
-
-/* Starts a thread as long as we're below max_threads */
-static int start_thread(void)
-{
- apr_thread_t *thread;
- int rc;
-
- apr_lock_acquire(worker_thread_count_mutex);
- if (worker_thread_count < max_threads - 1) {
- if ((rc = apr_thread_create(&thread, worker_thread_attr, worker_thread,
- &worker_thread_free_ids[worker_thread_count], pchild))) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, rc, ap_server_conf,
- "apr_thread_create: unable to create worker thread");
- /* In case system resources are maxxed out, we don't want
- Apache running away with the CPU trying to fork over and
- over and over again if we exit. */
- sleep(10);
- workers_may_exit = 1;
- apr_lock_release(worker_thread_count_mutex);
- return 0;
- }
- else {
- worker_thread_count++;
- }
- }
- else {
- static int reported = 0;
-
- if (!reported) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
- "server reached MaxThreadsPerChild setting, consider raising the"
- " MaxThreadsPerChild or NumServers settings");
- reported = 1;
- }
- apr_lock_release(worker_thread_count_mutex);
- return 0;
- }
- apr_lock_release(worker_thread_count_mutex);
- return 1;
-
-}
-/* Sets workers_may_exit if we received a character on the pipe_of_death */
-static void check_pipe_of_death(void)
-{
- apr_lock_acquire(pipe_of_death_mutex);
- if (!workers_may_exit) {
- int ret;
- char pipe_read_char;
- apr_size_t n = 1;
-
- ret = apr_recv(listenfds[0], &pipe_read_char, &n);
- if (APR_STATUS_IS_EAGAIN(ret)) {
- /* It lost the lottery. It must continue to suffer
- * through a life of servitude. */
- }
- else {
- /* It won the lottery (or something else is very
- * wrong). Embrace death with open arms. */
- workers_may_exit = 1;
- }
- }
- apr_lock_release(pipe_of_death_mutex);
-}
-
-/* idle_thread_count should be incremented before starting a worker_thread */
-
-static void *worker_thread(void *arg)
-{
- apr_socket_t *csd = NULL;
- apr_pool_t *tpool; /* Pool for this thread */
- apr_pool_t *ptrans; /* Pool for per-transaction stuff */
- apr_socket_t *sd = NULL;
- int srv;
- int curr_pollfd, last_pollfd = 0;
- int thread_just_started = 1;
- int thread_num = *((int *) arg);
- long conn_id = child_num * HARD_THREAD_LIMIT + thread_num;
- apr_pollfd_t *pollset;
- int n;
- apr_status_t rv;
-
- apr_lock_acquire(thread_pool_parent_mutex);
- apr_pool_create(&tpool, thread_pool_parent);
- apr_lock_release(thread_pool_parent_mutex);
- apr_pool_create(&ptrans, tpool);
-
- (void) ap_update_child_status(child_num, thread_num, SERVER_STARTING,
- (request_rec *) NULL);
-
- apr_poll_setup(&pollset, num_listenfds+1, tpool);
- for(n=0 ; n <= num_listenfds ; ++n) {
- apr_poll_socket_add(pollset, listenfds[n], APR_POLLIN);
- }
-
- while (!workers_may_exit) {
- workers_may_exit |= (max_requests_per_child != 0) && (requests_this_child <= 0);
- if (workers_may_exit) break;
- if (!thread_just_started) {
- apr_lock_acquire(idle_thread_count_mutex);
- if (idle_thread_count < max_spare_threads) {
- idle_thread_count++;
- apr_lock_release(idle_thread_count_mutex);
- }
- else {
- apr_lock_release(idle_thread_count_mutex);
- break;
- }
- }
- else {
- thread_just_started = 0;
- }
-
- (void) ap_update_child_status(child_num, thread_num, SERVER_READY,
- (request_rec *) NULL);
-
- apr_lock_acquire(thread_accept_mutex);
- if (workers_may_exit) {
- apr_lock_release(thread_accept_mutex);
- break;
- }
- if ((rv = SAFE_ACCEPT(apr_lock_acquire(process_accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_acquire failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
-
- while (!workers_may_exit) {
- apr_int16_t event;
- srv = apr_poll(pollset, &n, -1);
-
- if (srv != APR_SUCCESS) {
- if (APR_STATUS_IS_EINTR(srv)) {
- continue;
- }
-
- /* apr_poll() will only return errors in catastrophic
- * circumstances. Let's try exiting gracefully, for now. */
- ap_log_error(APLOG_MARK, APLOG_ERR, srv, (const server_rec *)
- ap_server_conf, "apr_poll: (listen)");
- workers_may_exit = 1;
- }
- if (workers_may_exit) break;
-
- apr_poll_revents_get(&event, listenfds[0], pollset);
- if (event & APR_POLLIN) {
- /* A process got a signal on the shutdown pipe. Check if we're
- * the lucky process to die. */
- check_pipe_of_death();
- continue;
- }
-
- apr_poll_revents_get(&event, listenfds[1], pollset);
- if (event & APR_POLLIN || event & APR_POLLOUT) {
- /* This request is from another child in our current process.
- * We should set a flag here, and then below we will read
- * two bytes (the socket number and the NULL byte.
- */
- thread_socket_table[thread_num] = -2;
- goto got_from_other_child;
- }
-
- if (num_listenfds == 1) {
- sd = ap_listeners->sd;
- goto got_fd;
- }
- else {
- /* find a listener */
- curr_pollfd = last_pollfd;
- do {
- curr_pollfd++;
- if (curr_pollfd > num_listenfds) {
- curr_pollfd = 1;
- }
- /* XXX: Should we check for POLLERR? */
- apr_poll_revents_get(&event, listenfds[curr_pollfd], pollset);
- if (event & APR_POLLIN) {
- last_pollfd = curr_pollfd;
- sd = listenfds[curr_pollfd];
- goto got_fd;
- }
- } while (curr_pollfd != last_pollfd);
- }
- }
- got_fd:
- if (!workers_may_exit) {
- if ((rv = apr_accept(&csd, sd, ptrans)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "apr_accept");
- }
- if ((rv = SAFE_ACCEPT(apr_lock_release(process_accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_release failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
- apr_lock_release(thread_accept_mutex);
- apr_lock_acquire(idle_thread_count_mutex);
- if (idle_thread_count > min_spare_threads) {
- idle_thread_count--;
- }
- else {
- if (!start_thread()) {
- idle_thread_count--;
- }
- }
- apr_lock_release(idle_thread_count_mutex);
- got_from_other_child:
- if (thread_socket_table[thread_num] == -2) {
- struct msghdr msg;
- struct cmsghdr *cmsg;
- char sockname[80];
- struct iovec iov;
- int ret, sd, dp;
-
- iov.iov_base = sockname;
- iov.iov_len = 80;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- cmsg = apr_palloc(ptrans, sizeof(*cmsg) + sizeof(sd));
- cmsg->cmsg_len = sizeof(*cmsg) + sizeof(sd);
- msg.msg_control = (caddr_t)cmsg;
- msg.msg_controllen = cmsg->cmsg_len;
- msg.msg_flags = 0;
-
- ret = recvmsg(child_info_table[child_num].sd, &msg, 0);
-
- memcpy(&dp, CMSG_DATA(cmsg), sizeof(dp));
-
- thread_socket_table[thread_num] = dp;
- apr_os_sock_put(&csd, &child_info_table[child_num].sd, ptrans);
- }
- if (setjmp(jmpbuffer) != 1) {
- process_socket(ptrans, csd, conn_id);
- }
- else {
- thread_socket_table[thread_num] = -1;
- }
- requests_this_child--;
- } else {
- if ((rv = SAFE_ACCEPT(apr_lock_release(process_accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_release failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
- apr_lock_release(thread_accept_mutex);
- apr_lock_acquire(idle_thread_count_mutex);
- idle_thread_count--;
- apr_lock_release(idle_thread_count_mutex);
- break;
- }
- apr_pool_clear(ptrans);
- }
-
- apr_lock_acquire(thread_pool_parent_mutex);
- ap_update_child_status(child_num, thread_num, SERVER_DEAD,
- (request_rec *) NULL);
- apr_pool_destroy(tpool);
- apr_lock_release(thread_pool_parent_mutex);
- apr_lock_acquire(worker_thread_count_mutex);
- worker_thread_count--;
- worker_thread_free_ids[worker_thread_count] = thread_num;
- if (worker_thread_count == 0) {
- /* All the threads have exited, now finish the shutdown process
- * by signalling the sigwait thread */
- kill(my_pid, SIGTERM);
- }
- apr_lock_release(worker_thread_count_mutex);
-
- return NULL;
-}
-
-/* Set group privileges.
- *
- * Note that we use the username as set in the config files, rather than
- * the lookup of to uid --- the same uid may have multiple passwd entries,
- * with different sets of groups for each.
- */
-
-static int set_group_privs(uid_t uid, gid_t gid)
-{
- if (!geteuid()) {
- const char *name;
-
- /* Get username if passed as a uid */
-
- struct passwd *ent;
-
- if ((ent = getpwuid(uid)) == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "getpwuid: couldn't determine user name from uid %u, "
- "you probably need to modify the User directive",
- (unsigned)uid);
- return -1;
- }
-
- name = ent->pw_name;
-
- /*
- * Set the GID before initgroups(), since on some platforms
- * setgid() is known to zap the group list.
- */
- if (setgid(gid) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "setgid: unable to set group id to Group %u",
- (unsigned)gid);
- return -1;
- }
-
- /* Reset `groups' attributes. */
-
- if (initgroups(name, gid) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "initgroups: unable to set groups for User %s "
- "and Group %u", name, (unsigned)gid);
- return -1;
- }
- }
- return 0;
-}
-
-
-static int perchild_setup_child(int childnum)
-{
- child_info_t *ug = &child_info_table[childnum];
-
- if (ug->uid == -1 && ug->gid == -1) {
- return unixd_setup_child();
- }
- if (set_group_privs(ug->uid, ug->gid)) {
- return -1;
- }
- /* Only try to switch if we're running as root */
- if (!geteuid() && (
-#ifdef _OSD_POSIX
- os_init_job_environment(server_conf, unixd_config.user_name, one_process) != 0 ||
-#endif
- setuid(ug->uid) == -1)) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "setuid: unable to change to uid: %ld",
- (long) ug->uid);
- return -1;
- }
- return 0;
-}
-
-static int check_signal(int signum)
-{
- switch (signum) {
- case SIGTERM:
- case SIGINT:
- just_die(signum);
- return 1;
- }
- return 0;
-}
-
-static void child_main(int child_num_arg)
-{
- int i;
- ap_listen_rec *lr;
- apr_status_t rv;
- apr_thread_t *thread;
-
- my_pid = getpid();
- child_num = child_num_arg;
- apr_pool_create(&pchild, pconf);
-
- /*stuff to do before we switch id's, so we have permissions.*/
-
- rv = SAFE_ACCEPT(apr_lock_child_init(&process_accept_mutex, lock_fname,
- pchild));
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "Couldn't initialize cross-process lock in child");
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-
- if (perchild_setup_child(child_num)) {
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-
- ap_run_child_init(pchild, ap_server_conf);
-
- /*done with init critical section */
-
- apr_setup_signal_thread();
-
- requests_this_child = max_requests_per_child;
-
- /* Set up the pollfd array, num_listenfds + 1 for the pipe and 1 for
- * the child socket.
- */
- listenfds = apr_pcalloc(pchild, sizeof(*listenfds) * (num_listenfds + 2));
-#if APR_FILES_AS_SOCKETS
- apr_socket_from_file(&listenfds[0], pipe_of_death_in);
-#endif
-
- /* The child socket */
- apr_os_sock_put(&listenfds[1], &child_info_table[child_num].sd, pchild);
-
- num_listenfds++;
- for (lr = ap_listeners, i = 2; i <= num_listenfds; lr = lr->next, ++i)
- listenfds[i]=lr->sd;
-
- /* Setup worker threads */
-
- if (threads_to_start > max_threads) {
- threads_to_start = max_threads;
- }
- idle_thread_count = threads_to_start;
- worker_thread_count = 0;
- for (i = 0; i < max_threads; i++) {
- worker_thread_free_ids[i] = i;
- }
- apr_pool_create(&thread_pool_parent, pchild);
- apr_lock_create(&thread_pool_parent_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&idle_thread_count_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&worker_thread_count_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&pipe_of_death_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&thread_accept_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
-
- apr_threadattr_create(&worker_thread_attr, pchild);
- apr_threadattr_detach_set(worker_thread_attr, 1);
-
- /* We are creating worker threads right now */
- for (i=0; i < threads_to_start; i++) {
- /* start_thread shouldn't fail here */
- if (!start_thread()) {
- break;
- }
- }
-
- apr_signal_thread(check_signal);
-}
-
-static int make_child(server_rec *s, int slot)
-{
- int pid;
-
- if (slot + 1 > ap_max_daemons_limit) {
- ap_max_daemons_limit = slot + 1;
- }
-
- if (one_process) {
- set_signals();
- ap_child_table[slot].pid = getpid();
- ap_child_table[slot].status = SERVER_ALIVE;
- child_main(slot);
- }
- (void) ap_update_child_status(slot, 0, SERVER_STARTING, (request_rec *) NULL);
-
- if ((pid = fork()) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
- "fork: Unable to fork new process");
- /* In case system resources are maxxed out, we don't want
- Apache running away with the CPU trying to fork over and
- over and over again. */
- sleep(10);
-
- return -1;
- }
-
- if (!pid) {
-#ifdef HAVE_BINDPROCESSOR
- /* By default, AIX binds to a single processor. This bit unbinds
- * children which will then bind to another CPU.
- */
- int status = bindprocessor(BINDPROCESS, (int)getpid(),
- PROCESSOR_CLASS_ANY);
- if (status != OK)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, errno,
- ap_server_conf, "processor unbind failed %d", status);
-#endif
-
- RAISE_SIGSTOP(MAKE_CHILD);
-
- /* XXX - For an unthreaded server, a signal handler will be necessary
- apr_signal(SIGTERM, just_die);
- */
- child_main(slot);
- clean_child_exit(0);
- }
- /* else */
- ap_child_table[slot].pid = pid;
- ap_child_table[slot].status = SERVER_ALIVE;
-
- return 0;
-}
-
-/* start up a bunch of children */
-static int startup_children(int number_to_start)
-{
- int i;
-
- for (i = 0; number_to_start && i < num_daemons; ++i) {
- if (ap_child_table[i].pid) {
- continue;
- }
- if (make_child(ap_server_conf, i) < 0) {
- break;
- }
- --number_to_start;
- }
- return number_to_start;
-}
-
-
-/*
- * spawn_rate is the number of children that will be spawned on the
- * next maintenance cycle if there aren't enough servers. It is
- * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
- * without the need to spawn.
- */
-static int spawn_rate = 1;
-#ifndef MAX_SPAWN_RATE
-#define MAX_SPAWN_RATE (32)
-#endif
-static int hold_off_on_exponential_spawning;
-
-static void perform_child_maintenance(void)
-{
- int i;
- int free_length;
- int free_slots[MAX_SPAWN_RATE];
- int last_non_dead = -1;
-
- /* initialize the free_list */
- free_length = 0;
-
- for (i = 0; i < num_daemons; ++i) {
- if (ap_child_table[i].pid == 0) {
- if (free_length < spawn_rate) {
- free_slots[free_length] = i;
- ++free_length;
- }
- }
- else {
- last_non_dead = i;
- }
-
- if (i >= ap_max_daemons_limit && free_length >= spawn_rate) {
- break;
- }
- }
- ap_max_daemons_limit = last_non_dead + 1;
-
- if (free_length > 0) {
- for (i = 0; i < free_length; ++i) {
- make_child(ap_server_conf, free_slots[i]);
- }
- /* the next time around we want to spawn twice as many if this
- * wasn't good enough, but not if we've just done a graceful
- */
- if (hold_off_on_exponential_spawning) {
- --hold_off_on_exponential_spawning;
- }
- else if (spawn_rate < MAX_SPAWN_RATE) {
- spawn_rate *= 2;
- }
- }
- else {
- spawn_rate = 1;
- }
-}
-
-static void server_main_loop(int remaining_children_to_start)
-{
- int child_slot;
- apr_wait_t status;
- apr_proc_t pid;
- int i;
-
- while (!restart_pending && !shutdown_pending) {
- ap_wait_or_timeout(&status, &pid, pconf);
-
- if (pid.pid != -1) {
- ap_process_child_status(&pid, status);
- /* non-fatal death... note that it's gone in the child table and
- * clean out the status table. */
- child_slot = -1;
- for (i = 0; i < ap_max_daemons_limit; ++i) {
- if (ap_child_table[i].pid == pid.pid) {
- child_slot = i;
- break;
- }
- }
- if (child_slot >= 0) {
- ap_child_table[child_slot].pid = 0;
- ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
-
-
- if (remaining_children_to_start
- && child_slot < num_daemons) {
- /* we're still doing a 1-for-1 replacement of dead
- * children with new children
- */
- make_child(ap_server_conf, child_slot);
- --remaining_children_to_start;
- }
-#if APR_HAS_OTHER_CHILD
- }
- else if (apr_proc_other_child_read(&pid, status) == 0) {
- /* handled */
-#endif
- }
- else if (is_graceful) {
- /* Great, we've probably just lost a slot in the
- * child table. Somehow we don't know about this
- * child.
- */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0,
- ap_server_conf,
- "long lost child came home! (pid %ld)",
- (long)pid.pid);
- }
- /* Don't perform idle maintenance when a child dies,
- * only do it when there's a timeout. Remember only a
- * finite number of children can die, and it's pretty
- * pathological for a lot to die suddenly.
- */
- continue;
- }
- else if (remaining_children_to_start) {
- /* we hit a 1 second timeout in which none of the previous
- * generation of children needed to be reaped... so assume
- * they're all done, and pick up the slack if any is left.
- */
- remaining_children_to_start = \
- startup_children(remaining_children_to_start);
- /* In any event we really shouldn't do the code below because
- * few of the servers we just started are in the IDLE state
- * yet, so we'd mistakenly create an extra server.
- */
- continue;
- }
-
- perform_child_maintenance();
- }
-}
-
-int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
-{
- int remaining_children_to_start;
- int i;
- apr_status_t rv;
- apr_size_t one = 1;
-
- pconf = _pconf;
- ap_server_conf = s;
- if ((rv = apr_file_pipe_create(&pipe_of_death_in, &pipe_of_death_out, pconf))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv,
- (const server_rec*) ap_server_conf,
- "apr_file_pipe_create (pipe_of_death)");
- exit(1);
- }
- if ((rv = apr_file_pipe_timeout_set(pipe_of_death_in, 0)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv,
- (const server_rec*) ap_server_conf,
- "apr_file_pipe_timeout_set (pipe_of_death)");
- exit(1);
- }
- ap_server_conf = s;
- if ((num_listenfds = ap_setup_listeners(ap_server_conf)) < 1) {
- /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
- "no listening sockets available, shutting down");
- return 1;
- }
- ap_log_pid(pconf, ap_pid_fname);
-
- /* Initialize cross-process accept lock */
- lock_fname = apr_psprintf(_pconf, "%s.%u",
- ap_server_root_relative(_pconf, lock_fname),
- my_pid);
- rv = SAFE_ACCEPT(apr_lock_create_np(&process_accept_mutex, APR_MUTEX,
- APR_CROSS_PROCESS, accept_lock_mech,
- lock_fname, _pconf));
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
- "Couldn't create cross-process lock");
- return 1;
- }
-
- if (!is_graceful) {
- ap_create_scoreboard(pconf, SB_SHARED);
- }
- /* Initialize the child table */
- if (!is_graceful) {
- for (i = 0; i < HARD_SERVER_LIMIT; i++) {
- ap_child_table[i].pid = 0;
- }
- }
-
- set_signals();
-
- /* If we're doing a graceful_restart then we're going to see a lot
- * of children exiting immediately when we get into the main loop
- * below (because we just sent them SIGWINCH). This happens pretty
- * rapidly... and for each one that exits we'll start a new one until
- * we reach at least daemons_min_free. But we may be permitted to
- * start more than that, so we'll just keep track of how many we're
- * supposed to start up without the 1 second penalty between each fork.
- */
- remaining_children_to_start = num_daemons;
- if (!is_graceful) {
- remaining_children_to_start = \
- startup_children(remaining_children_to_start);
- }
- else {
- /* give the system some time to recover before kicking into
- * exponential mode */
- hold_off_on_exponential_spawning = 10;
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "%s configured -- resuming normal operations",
- ap_get_server_version());
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
- "Server built: %s", ap_get_server_built());
- restart_pending = shutdown_pending = 0;
-
- server_main_loop(remaining_children_to_start);
-
- if (shutdown_pending) {
- /* Time to gracefully shut down:
- * Kill child processes, tell them to call child_exit, etc...
- */
- if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
- "killpg SIGTERM");
- }
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
-
- /* cleanup pid file on normal shutdown */
- {
- const char *pidfile = NULL;
- pidfile = ap_server_root_relative (pconf, ap_pid_fname);
- if ( pidfile != NULL && unlink(pidfile) == 0)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0,
- ap_server_conf,
- "removed PID file %s (pid=%ld)",
- pidfile, (long)getpid());
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0,
- ap_server_conf, "caught SIGTERM, shutting down");
-
- return 1;
- }
-
- /* we've been told to restart */
- apr_signal(SIGHUP, SIG_IGN);
-
- if (one_process) {
- /* not worth thinking about */
- return 1;
- }
-
- if (is_graceful) {
- char char_of_death = '!';
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "SIGWINCH received. Doing graceful restart");
-
- /* This is mostly for debugging... so that we know what is still
- * gracefully dealing with existing request.
- */
-
- for (i = 0; i < num_daemons; ++i) {
- if (ap_child_table[i].pid) {
- ap_child_table[i].status = SERVER_DYING;
- }
- }
- /* give the children the signal to die */
- for (i = 0; i < num_daemons;) {
- if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one)) != APR_SUCCESS) {
- if (APR_STATUS_IS_EINTR(rv)) continue;
- ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
- "write pipe_of_death");
- }
- i++;
- }
- }
- else {
- /* Kill 'em all. Since the child acts the same on the parents SIGTERM
- * and a SIGHUP, we may as well use the same signal, because some user
- * pthreads are stealing signals from us left and right.
- */
- if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
- "killpg SIGTERM");
- }
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0,
- ap_server_conf, "SIGHUP received. Attempting to restart");
- }
- return 0;
-}
-
-static void perchild_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
-{
- static int restart_num = 0;
- int no_detach = 0;
- int i;
-
- one_process = !!ap_exists_config_define("ONE_PROCESS");
- no_detach = !!ap_exists_config_define("NO_DETACH");
-
- /* sigh, want this only the second time around */
- if (restart_num++ == 1) {
- is_graceful = 0;
-
- if (!one_process && !no_detach) {
- apr_proc_detach();
- }
-
- my_pid = getpid();
- }
-
- unixd_pre_config(ptemp);
- ap_listen_pre_config();
- num_daemons = DEFAULT_NUM_DAEMON;
- threads_to_start = DEFAULT_START_THREAD;
- min_spare_threads = DEFAULT_MIN_SPARE_THREAD;
- max_spare_threads = DEFAULT_MAX_SPARE_THREAD;
- max_threads = HARD_THREAD_LIMIT;
- ap_pid_fname = DEFAULT_PIDLOG;
- ap_scoreboard_fname = DEFAULT_SCOREBOARD;
- lock_fname = DEFAULT_LOCKFILE;
- max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
- curr_child_num = 0;
-
- apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
-
- for (i = 0; i < HARD_SERVER_LIMIT; i++) {
- child_info_table[i].uid = -1;
- child_info_table[i].gid = -1;
- child_info_table[i].sd = -1;
- }
- for (i = 0; i < HARD_THREAD_LIMIT; i++) {
- thread_socket_table[i] = -1;
- }
-}
-
-static int pass_request(request_rec *r)
-{
- apr_socket_t *thesock = r->connection->client_socket;
- struct msghdr msg;
- struct cmsghdr *cmsg;
- int sfd;
- struct iovec iov;
- apr_bucket_brigade *bb = apr_brigade_create(r->pool);
- perchild_server_conf *sconf = (perchild_server_conf *)
- ap_get_module_config(r->server->module_config,
- &mpm_perchild_module);
- char *foo;
- apr_size_t len;
- int zero = 0;
-
- apr_pool_userdata_get((void **)&foo, "PERCHILD_BUFFER", r->connection->pool);
- len = strlen(foo);
-
- apr_pool_userdata_set(NULL, "PERCHILD_BUFFER", apr_pool_cleanup_null,
- r->connection->pool);
-
- apr_os_sock_get(&sfd, thesock);
-
- iov.iov_base = NULL;
- iov.iov_len = 0;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- cmsg = apr_palloc(r->pool, sizeof(*cmsg) + sizeof(sfd));
- cmsg->cmsg_len = sizeof(*cmsg) + sizeof(int);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
-
- memcpy(CMSG_DATA(cmsg), &sfd, sizeof(sfd));
-
- msg.msg_control = (caddr_t)cmsg;
- msg.msg_controllen = cmsg->cmsg_len;
- msg.msg_flags=0;
-
- if (sendmsg(sconf->sd2, &msg, 0) == -1) {
- apr_pool_destroy(r->pool);
- return -1;
- }
-
- write(sconf->sd2, foo, len);
-
- /* ### this "read one line" doesn't seem right... shouldn't we be
- ### reading large chunks of data or something?
- */
- while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING,
- &zero /* read one line */) == APR_SUCCESS) {
- apr_bucket *e;
- APR_BRIGADE_FOREACH(e, bb) {
- const char *str;
-
- apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
- write(sconf->sd2, str, len);
- }
- }
-
- apr_pool_destroy(r->pool);
- return 1;
-}
-
-static char *make_perchild_socket(const char *fullsockname, int sd[2])
-{
- socketpair(PF_UNIX, SOCK_STREAM, 0, sd);
- return NULL;
-}
-
-
-static void perchild_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
-{
- int i;
- server_rec *sr;
- perchild_server_conf *sconf;
- int def_sd[2];
-
- def_sd[0] = -1;
- def_sd[1] = -1;
-
- for (sr = s; sr; sr = sr->next) {
- sconf = (perchild_server_conf *)ap_get_module_config(sr->module_config,
- &mpm_perchild_module);
-
- if (sconf->sd == -1) {
- sconf->fullsockname = apr_pstrcat(sr->process->pool,
- sconf->sockname, ".DEFAULT", NULL);
- if (def_sd[0] == -1) {
- if (!make_perchild_socket(sconf->fullsockname, def_sd)) {
- /* log error */
- }
- }
- sconf->sd = def_sd[0];
- sconf->sd2 = def_sd[1];
- }
- }
-
- for (i = 0; i < num_daemons; i++) {
- if (child_info_table[i].uid == -1) {
- child_info_table[i].sd = def_sd[0];
- }
- }
-}
-
-static int perchild_post_read(request_rec *r)
-{
- ap_filter_t *f = r->connection->input_filters;
- int thread_num = r->connection->id % HARD_THREAD_LIMIT;
- perchild_server_conf *sconf = (perchild_server_conf *)
- ap_get_module_config(r->server->module_config,
- &mpm_perchild_module);
-
- while (f) {
- if (!strcmp("PERCHILD_BUFFER", f->frec->name)) {
- ap_remove_output_filter(f);
- break;
- }
- f = f->next;
- }
-
- if (thread_socket_table[thread_num] != -1) {
- apr_socket_t *csd = NULL;
-
- apr_os_sock_put(&csd, &thread_socket_table[thread_num],
- r->connection->pool);
- ap_sock_disable_nagle(csd);
- r->connection->client_socket = csd;
- return OK;
- }
- else {
- if (sconf->sd != child_info_table[child_num].sd) {
- if (pass_request(r) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0,
- ap_server_conf, "Could not pass request to proper "
- "child, request will not be honored.");
- }
- longjmp(jmpbuffer, 1);
- }
- return OK;
- }
- return OK;
-}
-
-static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes)
-{
- apr_bucket *e;
- apr_status_t rv;
- char *buffer = NULL;
- const char *str;
- apr_size_t len;
-
- if ((rv = ap_get_brigade(f->next, b, mode, readbytes)) != APR_SUCCESS) {
- return rv;
- }
-
- apr_pool_userdata_get((void **)&buffer, "PERCHILD_BUFFER", f->c->pool);
-
- APR_BRIGADE_FOREACH(e, b) {
- if (e->length != 0) {
- apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
-
- if (buffer == NULL) {
- buffer = apr_pstrndup(f->c->pool, str, len);
- }
- else {
- buffer = apr_pstrcat(f->c->pool, buffer,
- apr_pstrndup(f->c->pool, str, len), NULL);
- }
- }
- }
- apr_pool_userdata_set(buffer, "PERCHILD_BUFFER", apr_pool_cleanup_null, f->c->pool);
-
- return APR_SUCCESS;
-}
-
-static int perchild_pre_connection(conn_rec *c)
-{
- ap_add_input_filter("PERCHILD_BUFFER", NULL, NULL, c);
- return OK;
-}
-
-static void perchild_hooks(apr_pool_t *p)
-{
- one_process = 0;
-
- ap_hook_pre_config(perchild_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_config(perchild_post_config, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_pre_connection(perchild_pre_connection,NULL,NULL, APR_HOOK_MIDDLE);
-
- /* This must be run absolutely first. If this request isn't for this
- * server then we need to forward it to the proper child. No sense
- * tying up this server running more post_read request hooks if it is
- * just going to be forwarded along.
- */
- ap_hook_post_read_request(perchild_post_read, NULL, NULL, APR_HOOK_REALLY_FIRST);
- ap_register_input_filter("PERCHILD_BUFFER", perchild_buffer, AP_FTYPE_CONTENT);
-}
-
-static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- if (cmd->server->is_virtual) {
- return "PidFile directive not allowed in ";
- }
- ap_pid_fname = arg;
- return NULL;
-}
-
-static const char *set_scoreboard(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_scoreboard_fname = arg;
- return NULL;
-}
-
-static const char *set_lockfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- lock_fname = arg;
- return NULL;
-}
-static const char *set_num_daemons (cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- num_daemons = atoi(arg);
- if (num_daemons > HARD_SERVER_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: NumServers of %d exceeds compile time limit "
- "of %d servers,", num_daemons, HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering NumServers to %d. To increase, please "
- "see the", HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_SERVER_LIMIT define in %s.",
- AP_MPM_HARD_LIMITS_FILE);
- num_daemons = HARD_SERVER_LIMIT;
- }
- else if (num_daemons < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require NumServers > 0, setting to 1");
- num_daemons = 1;
- }
- return NULL;
-}
-
-static const char *set_threads_to_start (cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- threads_to_start = atoi(arg);
- if (threads_to_start > HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: StartThreads of %d exceeds compile time"
- " limit of %d threads,", threads_to_start,
- HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering StartThreads to %d. To increase, please"
- " see the", HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_THREAD_LIMIT define in %s.",
- AP_MPM_HARD_LIMITS_FILE);
- }
- else if (threads_to_start < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require StartThreads > 0, setting to 1");
- threads_to_start = 1;
- }
- return NULL;
-}
-
-static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- min_spare_threads = atoi(arg);
- if (min_spare_threads <= 0) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MinSpareThreads set to non-positive.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Resetting to 1 to avoid almost certain Apache failure.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Please read the documentation.");
- min_spare_threads = 1;
- }
-
- return NULL;
-}
-
-static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- max_spare_threads = atoi(arg);
- if (max_spare_threads >= HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MinSpareThreads set higher than");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT);
- max_spare_threads = HARD_THREAD_LIMIT;
- }
- return NULL;
-}
-
-static const char *set_max_threads(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- max_threads = atoi(arg);
- if (max_threads > HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MaxThreadsPerChild set higher than");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT);
- max_threads = HARD_THREAD_LIMIT;
- }
- return NULL;
-}
-
-static const char *set_max_requests(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- max_requests_per_child = atoi(arg);
-
- return NULL;
-}
-
-static const char *set_coredumpdir (cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- apr_finfo_t finfo;
- const char *fname;
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- fname = ap_server_root_relative(cmd->pool, arg);
- if ((apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool) != APR_SUCCESS)
- || (finfo.filetype != APR_DIR)) {
- return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
- " does not exist or is not a directory", NULL);
- }
- apr_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
- return NULL;
-}
-
-static const char *set_child_per_uid(cmd_parms *cmd, void *dummy, const char *u,
- const char *g, const char *num)
-{
- int i;
- int max_this_time = atoi(num) + curr_child_num;
- for (i = curr_child_num; i < max_this_time; i++, curr_child_num++); {
- child_info_t *ug = &child_info_table[i - 1];
-
- if (i > num_daemons) {
- return "Trying to use more child ID's than NumServers. Increase "
- "NumServers in your config file.";
- }
-
- ug->uid = atoi(u);
- ug->gid = atoi(g);
- }
- return NULL;
-}
-
-static const char *assign_childuid(cmd_parms *cmd, void *dummy, const char *uid,
- const char *gid)
-{
- int i;
- int u = atoi(uid);
- int g = atoi(gid);
- const char *errstr;
- int socks[2];
- perchild_server_conf *sconf = (perchild_server_conf *)
- ap_get_module_config(cmd->server->module_config,
- &mpm_perchild_module);
-
- sconf->fullsockname = apr_pstrcat(cmd->pool, sconf->sockname, ".", uid, ":", gid, NULL);
-
- if ((errstr = make_perchild_socket(sconf->fullsockname, socks))) {
- return errstr;
- }
-
- sconf->sd = socks[0];
- sconf->sd2 = socks[1];
-
- for (i = 0; i < num_daemons; i++) {
- if (u == child_info_table[i].uid && g == child_info_table[i].gid) {
- child_info_table[i].sd = sconf->sd;
- }
- }
-
- return NULL;
-}
-
-static const char *set_accept_lock_mech(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, "default")) {
- accept_lock_mech = APR_LOCK_DEFAULT;
- }
-#if APR_HAS_FLOCK_SERIALIZE
- else if (!strcasecmp(arg, "flock")) {
- accept_lock_mech = APR_LOCK_FLOCK;
- }
-#endif
-#if APR_HAS_FCNTL_SERIALIZE
- else if (!strcasecmp(arg, "fcntl")) {
- accept_lock_mech = APR_LOCK_FCNTL;
- }
-#endif
-#if APR_HAS_SYSVSEM_SERIALIZE
- else if (!strcasecmp(arg, "sysvsem")) {
- accept_lock_mech = APR_LOCK_SYSVSEM;
- }
-#endif
-#if APR_HAS_PROC_PTHREAD_SERIALIZE
- else if (!strcasecmp(arg, "proc_pthread")) {
- accept_lock_mech = APR_LOCK_PROC_PTHREAD;
- }
-#endif
- else {
- return apr_pstrcat(cmd->pool, arg, " is an invalid mutex mechanism; valid "
- "ones for this platform are: default"
-#if APR_HAS_FLOCK_SERIALIZE
- ", flock"
-#endif
-#if APR_HAS_FCNTL_SERIALIZE
- ", fcntl"
-#endif
-#if APR_HAS_SYSVSEM_SERIALIZE
- ", sysvsem"
-#endif
-#if APR_HAS_PROC_PTHREAD_SERIALIZE
- ", proc_pthread"
-#endif
- , NULL);
- }
- return NULL;
-}
-
-static const command_rec perchild_cmds[] = {
-UNIX_DAEMON_COMMANDS
-LISTEN_COMMANDS
-AP_INIT_TAKE1("PidFile", set_pidfile, NULL, RSRC_CONF,
- "A file for logging the server process ID"),
-AP_INIT_TAKE1("ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF,
- "A file for Apache to maintain runtime process management information"),
-AP_INIT_TAKE1("LockFile", set_lockfile, NULL, RSRC_CONF,
- "The lockfile used when Apache needs to lock the accept() call"),
-AP_INIT_TAKE1("NumServers", set_num_daemons, NULL, RSRC_CONF,
- "Number of children alive at the same time"),
-AP_INIT_TAKE1("StartThreads", set_threads_to_start, NULL, RSRC_CONF,
- "Number of threads each child creates"),
-AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
- "Minimum number of idle threads per child, to handle request spikes"),
-AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
- "Maximum number of idle threads per child"),
-AP_INIT_TAKE1("MaxThreadsPerChild", set_max_threads, NULL, RSRC_CONF,
- "Maximum number of threads per child"),
-AP_INIT_TAKE1("MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF,
- "Maximum number of requests a particular child serves before dying."),
-AP_INIT_TAKE1("CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF,
- "The location of the directory Apache changes to before dumping core"),
-AP_INIT_TAKE3("ChildperUserID", set_child_per_uid, NULL, RSRC_CONF,
- "Specify a User and Group for a specific child process."),
-AP_INIT_TAKE2("AssignUserID", assign_childuid, NULL, RSRC_CONF,
- "Tie a virtual host to a specific child process."),
-AP_INIT_TAKE1("AcceptMutex", set_accept_lock_mech, NULL, RSRC_CONF,
- "The system mutex implementation to use for the accept mutex"),
-{ NULL }
-};
-
-static void *perchild_create_config(apr_pool_t *p, server_rec *s)
-{
- perchild_server_conf *c =
- (perchild_server_conf *) apr_pcalloc(p, sizeof(perchild_server_conf));
-
- c->sd = -1;
- return c;
-}
-
-module AP_MODULE_DECLARE_DATA mpm_perchild_module = {
- MPM20_MODULE_STUFF,
- NULL, /* hook to run before apache parses args */
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- perchild_create_config, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- perchild_cmds, /* command apr_table_t */
- perchild_hooks /* register_hooks */
-};
-
diff --git a/server/mpm/winnt/Win9xConHook.c b/server/mpm/winnt/Win9xConHook.c
deleted file mode 100644
index a285329b43e..00000000000
--- a/server/mpm/winnt/Win9xConHook.c
+++ /dev/null
@@ -1,739 +0,0 @@
-/* ====================================================================
- * 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
- * the documentation and/or other materials provided with the
- * 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.
- */
-
-#ifdef WIN32
-
-/*
- * Win9xConHook.dll - a hook proc to clean up Win95/98 console behavior.
- *
- * It is well(?) documented by Microsoft that the Win9x HandlerRoutine
- * hooked by the SetConsoleCtrlHandler never receives the CTRL_CLOSE_EVENT,
- * CTRL_LOGOFF_EVENT or CTRL_SHUTDOWN_EVENT signals.
- *
- * It is possible to have a second window to monitor the WM_ENDSESSION
- * message, but the close button still fails..
- *
- * There is a 16bit polling method for the close window option, but this
- * is CPU intensive and requires thunking.
- *
- * Attempts to subclass the 'tty' console fail, since that message thread
- * is actually owned by the 16 bit winoldap.mod process, although the
- * window reports it is owned by the process/thread of the console app.
- *
- * Win9xConHook is thunks the WM_CLOSE and WM_ENDSESSION messages,
- * first through a window hook procedure in the winoldap context, into
- * a subclass WndProc, and on to a second hidden monitor window in the
- * console application's context that dispatches them to the console app's
- * registered HandlerRoutine.
- */
-
-/* This debugging define turns on output to COM1, although you better init
- * the port first (even using hyperterm). It's the only way to catch the
- * goings on within system logoff/shutdown.
- * #define DBG 1
- */
-
-#include
-
-/* Variables used within any process context:
- * hookwndmsg is a shared message to send Win9xConHook signals
- * origwndprop is a wndprop atom to store the orig wndproc of the tty
- * hookwndprop is a wndprop atom to store the hwnd of the hidden child
- * is_service reminds us to unmark this process on the way out
- */
-static UINT hookwndmsg = 0;
-static LPCTSTR origwndprop;
-static LPCTSTR hookwndprop;
-static BOOL is_service = 0;
-//static HMODULE hmodThis = NULL;
-
-/* Variables used within the tty processes' context:
- * is_tty flags this process; -1 == unknown, 1 == if tty, 0 == if not
- * hw_tty is the handle of the top level tty in this process context
- * is_subclassed is toggled to assure DllMain removes the subclass on unload
- * hmodLock is there to try and prevent this dll from being unloaded if the
- * hook is removed while we are subclassed
- */
-static int is_tty = -1;
-static HWND hwtty = NULL;
-static BOOL is_subclassed = 0;
-
-// This simply causes a gpfault the moment it tries to FreeLibrary within
-// the subclass procedure ... not good.
-//static HMODULE hmodLock = NULL;
-
-/* Variables used within the service or console app's context:
- * hmodHook is the instance handle of this module for registering the hooks
- * hhkGetMessage is the hook handle for catching Posted messages
- * hhkGetMessage is the hook handle for catching Sent messages
- * monitor_hwnd is the invisible window that handles our tty messages
- * the tty_info strucure is used to pass args into the hidden window's thread
- */
-static HMODULE hmodHook = NULL;
-static HHOOK hhkGetMessage;
-//static HHOOK hhkCallWndProc;
-static HWND monitor_hwnd = NULL;
-
-typedef struct {
- PHANDLER_ROUTINE phandler;
- HINSTANCE instance;
- HWND parent;
- INT type;
- LPCSTR name;
-} tty_info;
-
-/* These are the GetWindowLong offsets for the hidden window's internal info
- * gwltty_phandler is the address of the app's HandlerRoutine
- * gwltty_ttywnd is the tty this hidden window will handle messages from
- */
-#define gwltty_phandler 0
-#define gwltty_ttywnd 4
-
-/* Forward declaration prototypes for internal functions
- */
-static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd);
-static LRESULT WINAPI RegisterWindows9xService(BOOL set_service);
-static LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam);
-static DWORD WINAPI ttyConsoleCtrlThread(LPVOID tty);
-static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam);
-static int HookProc(int hc, HWND *hwnd, UINT *msg,
- WPARAM *wParam, LPARAM *lParam);
-#ifdef DBG
-static VOID DbgPrintf(LPTSTR fmt, ...);
-#endif
-
-
-/* DllMain is invoked by every process in the entire system that is hooked
- * by our window hooks, notably the tty processes' context, and by the user
- * who wants tty messages (the app). Keep it light and simple.
- */
-BOOL __declspec(dllexport) APIENTRY DllMain(HINSTANCE hModule, ULONG ulReason,
- LPVOID pctx)
-{
- if (ulReason == DLL_PROCESS_ATTACH)
- {
- //hmodThis = hModule;
- if (!hookwndmsg) {
- origwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookOrigProc"));
- hookwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookThunkWnd"));
- hookwndmsg = RegisterWindowMessage("Win9xConHookMsg");
- }
-#ifdef DBG
-// DbgPrintf("H ProcessAttach:%8.8x\r\n",
-// GetCurrentProcessId());
-#endif
- }
- else if ( ulReason == DLL_PROCESS_DETACH )
- {
-#ifdef DBG
-// DbgPrintf("H ProcessDetach:%8.8x\r\n", GetCurrentProcessId());
-#endif
- if (monitor_hwnd)
- SendMessage(monitor_hwnd, WM_DESTROY, 0, 0);
- if (is_subclassed)
- SendMessage(hwtty, hookwndmsg, 0, (LPARAM)hwtty);
- if (hmodHook)
- {
- if (hhkGetMessage) {
- UnhookWindowsHookEx(hhkGetMessage);
- hhkGetMessage = NULL;
- }
- //if (hhkCallWndProc) {
- // UnhookWindowsHookEx(hhkCallWndProc);
- // hhkCallWndProc = NULL;
- //}
- FreeLibrary(hmodHook);
- hmodHook = NULL;
- }
- if (is_service)
- RegisterWindows9xService(FALSE);
- if (hookwndmsg) {
- GlobalDeleteAtom((ATOM)origwndprop);
- GlobalDeleteAtom((ATOM)hookwndprop);
- hookwndmsg = 0;
- }
- }
- return TRUE;
-}
-
-
-/* This group of functions are provided for the service/console app
- * to register itself a HandlerRoutine to accept tty or service messages
- */
-
-
-/* Exported function that creates a Win9x 'service' via a hidden window,
- * that notifies the process via the HandlerRoutine messages.
- */
-BOOL __declspec(dllexport) WINAPI Windows9xServiceCtrlHandler(
- PHANDLER_ROUTINE phandler,
- LPCSTR name)
-{
- /* If we have not yet done so */
- FreeConsole();
-
- if (name)
- {
- DWORD tid;
- HANDLE hThread;
- /* NOTE: this is static so the module can continue to
- * access these args while we go on to other things
- */
- static tty_info tty;
- tty.instance = GetModuleHandle(NULL);
- tty.phandler = phandler;
- tty.parent = NULL;
- tty.name = name;
- tty.type = 2;
- RegisterWindows9xService(TRUE);
- hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread,
- (LPVOID)&tty, 0, &tid);
- if (hThread)
- {
- CloseHandle(hThread);
- return TRUE;
- }
- }
- else /* remove */
- {
- if (monitor_hwnd)
- SendMessage(monitor_hwnd, WM_DESTROY, 0, 0);
- RegisterWindows9xService(FALSE);
- return TRUE;
- }
- return FALSE;
-}
-
-
-/* Exported function that registers a HandlerRoutine to accept missing
- * Win9x CTRL_EVENTs from the tty window, as NT does without a hassle.
- * If add is 1 or 2, register the handler, if 2 also mark it as a service.
- * If add is 0 deregister the handler, and unmark if a service
- */
-BOOL __declspec(dllexport) WINAPI FixConsoleCtrlHandler(
- PHANDLER_ROUTINE phandler,
- INT add)
-{
- HWND parent;
-
- if (add)
- {
- HANDLE hThread;
- DWORD tid;
- /* NOTE: this is static so the module can continue to
- * access these args while we go on to other things
- */
- static tty_info tty;
- EnumWindows(EnumttyWindow, (LPARAM)&parent);
- if (!parent) {
-#ifdef DBG
- DbgPrintf("A EnumttyWindow failed (%d)\r\n", GetLastError());
-#endif
- return FALSE;
- }
- tty.instance = GetModuleHandle(NULL);
- tty.phandler = phandler;
- tty.parent = parent;
- tty.type = add;
- if (add == 2) {
- tty.name = "ttyService";
- RegisterWindows9xService(TRUE);
- }
- else
- tty.name = "ttyMonitor";
- hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread,
- (LPVOID)&tty, 0, &tid);
- if (!hThread)
- return FALSE;
- CloseHandle(hThread);
- hmodHook = LoadLibrary("Win9xConHook.dll");
- if (hmodHook)
- {
- hhkGetMessage = SetWindowsHookEx(WH_GETMESSAGE,
- (HOOKPROC)GetProcAddress(hmodHook, "GetMsgProc"), hmodHook, 0);
- //hhkCallWndProc = SetWindowsHookEx(WH_CALLWNDPROC,
- // (HOOKPROC)GetProcAddress(hmodHook, "CallWndProc"), hmodHook, 0);
- }
- return TRUE;
- }
- else /* remove */
- {
- if (monitor_hwnd) {
- SendMessage(monitor_hwnd, WM_DESTROY, 0, 0);
- }
- if (hmodHook)
- {
- if (hhkGetMessage) {
- UnhookWindowsHookEx(hhkGetMessage);
- hhkGetMessage = NULL;
- }
- //if (hhkCallWndProc) {
- // UnhookWindowsHookEx(hhkCallWndProc);
- // hhkCallWndProc = NULL;
- //}
- FreeLibrary(hmodHook);
- hmodHook = NULL;
- }
- if (is_service)
- RegisterWindows9xService(FALSE);
- return TRUE;
- }
- return FALSE;
-}
-
-
-/* The following internal helpers are only used within the app's context
- */
-
-/* ttyConsoleCreateThread is the process that runs within the user app's
- * context. It creates and pumps the messages of a hidden monitor window,
- * watching for messages from the system, or the associated subclassed tty
- * window. Things can happen in our context that can't be done from the
- * tty's context, and visa versa, so the subclass procedure and this hidden
- * window work together to make it all happen.
- */
-static DWORD WINAPI ttyConsoleCtrlThread(LPVOID tty)
-{
- WNDCLASS wc;
- MSG msg;
- wc.style = CS_GLOBALCLASS;
- wc.lpfnWndProc = ttyConsoleCtrlWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 8;
- wc.hInstance = NULL;
- wc.hIcon = NULL;
- wc.hCursor = NULL;
- wc.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
- if (((tty_info*)tty)->parent)
- wc.lpszClassName = "ttyConHookChild";
- else
- wc.lpszClassName = "ApacheWin95ServiceMonitor";
-
- if (!RegisterClass(&wc)) {
-#ifdef DBG
- DbgPrintf("A proc %8.8x Error creating class %s (%d)\r\n",
- GetCurrentProcessId(), wc.lpszClassName, GetLastError());
-#endif
- return 0;
- }
-
- /* Create an invisible window */
- monitor_hwnd = CreateWindow(wc.lpszClassName, ((tty_info*)tty)->name,
- WS_OVERLAPPED & ~WS_VISIBLE,
- CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT,
- NULL, NULL,
- ((tty_info*)tty)->instance, tty);
-
- if (!monitor_hwnd) {
-#ifdef DBG
- DbgPrintf("A proc %8.8x Error creating window %s %s (%d)\r\n",
- GetCurrentProcessId(), wc.lpszClassName,
- ((tty_info*)tty)->name, GetLastError());
-#endif
- return 0;
- }
-
- while (GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- /* Tag again as deleted, just in case we missed WM_DESTROY */
- monitor_hwnd = NULL;
- return 0;
-}
-
-
-/* This is the WndProc procedure for our invisible window.
- * When our subclasssed tty window receives the WM_CLOSE, WM_ENDSESSION,
- * or WM_QUERYENDSESSION messages, the message is dispatched to our hidden
- * window (this message process), and we call the installed HandlerRoutine
- * that was registered by the app.
- */
-static LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam)
-{
- if (msg == WM_CREATE)
- {
- tty_info *tty = (tty_info*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
- SetWindowLong(hwnd, gwltty_phandler, (LONG)tty->phandler);
- SetWindowLong(hwnd, gwltty_ttywnd, (LONG)tty->parent);
-#ifdef DBG
- DbgPrintf("A proc %8.8x created %8.8x %s for tty wnd %8.8x\r\n",
- GetCurrentProcessId(), hwnd,
- tty->name, tty->parent);
-#endif
- if (tty->parent) {
- SetProp(tty->parent, hookwndprop, hwnd);
- PostMessage(tty->parent, hookwndmsg,
- tty->type, (LPARAM)tty->parent);
- }
- return 0;
- }
- else if (msg == WM_DESTROY)
- {
- HWND parent = (HWND)GetWindowLong(hwnd, gwltty_ttywnd);
-#ifdef DBG
- DbgPrintf("A proc %8.8x destroyed %8.8x ttyConHookChild\r\n",
- GetCurrentProcessId(), hwnd);
-#endif
- if (parent) {
- RemoveProp(parent, hookwndprop);
- SendMessage(parent, hookwndmsg, 0, (LPARAM)parent);
- }
- monitor_hwnd = NULL;
- }
- else if (msg == WM_CLOSE)
- {
- PHANDLER_ROUTINE phandler =
- (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler);
- LRESULT rv = phandler(CTRL_CLOSE_EVENT);
-#ifdef DBG
- DbgPrintf("A proc %8.8x invoked CTRL_CLOSE_EVENT "
- "returning %d\r\n",
- GetCurrentProcessId(), rv);
-#endif
- if (rv)
- return !rv;
- }
- else if ((msg == WM_QUERYENDSESSION) || (msg == WM_ENDSESSION))
- {
- if (lParam & ENDSESSION_LOGOFF)
- {
- PHANDLER_ROUTINE phandler =
- (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler);
- LRESULT rv = phandler(CTRL_LOGOFF_EVENT);
-#ifdef DBG
- DbgPrintf("A proc %8.8x invoked CTRL_LOGOFF_EVENT "
- "returning %d\r\n",
- GetCurrentProcessId(), rv);
-#endif
- if (rv)
- return ((msg == WM_QUERYENDSESSION) ? rv : !rv);
- }
- else
- {
- PHANDLER_ROUTINE phandler =
- (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler);
- LRESULT rv = phandler(CTRL_SHUTDOWN_EVENT);
-#ifdef DBG
- DbgPrintf("A proc %8.8x invoked CTRL_SHUTDOWN_EVENT "
- "returning %d\r\n", GetCurrentProcessId(), rv);
-#endif
- if (rv)
- return ((msg == WM_QUERYENDSESSION) ? rv : !rv);
- }
- }
- return (DefWindowProc(hwnd, msg, wParam, lParam));
-}
-
-
-/* The following internal helpers are invoked by the hooked tty and our app
- */
-
-
-/* Register or deregister the current process as a Windows9x style service.
- * Experience shows this call is ignored across processes, so the second
- * arg to RegisterServiceProcess (process group id) is effectively useless.
- */
-static LRESULT WINAPI RegisterWindows9xService(BOOL set_service)
-{
- static HINSTANCE hkernel;
- static DWORD (WINAPI *register_service_process)(DWORD, DWORD) = NULL;
- BOOL rv;
-
- if (set_service == is_service)
- return 1;
-
-#ifdef DBG
- DbgPrintf("R %s proc %8.8x as a service\r\n",
- set_service ? "installing" : "removing",
- GetCurrentProcessId());
-#endif
-
- if (!register_service_process)
- {
- /* Obtain a handle to the kernel library */
- hkernel = LoadLibrary("KERNEL32.DLL");
- if (!hkernel)
- return 0;
-
- /* Find the RegisterServiceProcess function */
- register_service_process = (DWORD (WINAPI *)(DWORD, DWORD))
- GetProcAddress(hkernel, "RegisterServiceProcess");
- if (register_service_process == NULL) {
- FreeLibrary(hkernel);
- return 0;
- }
- }
-
- /* Register this process as a service */
- rv = register_service_process(0, set_service != FALSE);
- if (rv)
- is_service = set_service;
-
- if (!is_service)
- {
- /* Unload the kernel library */
- FreeLibrary(hkernel);
- register_service_process = NULL;
- }
- return rv;
-}
-
-
-/*
- * This function only works when this process is the active process
- * (e.g. once it is running a child process, it can no longer determine
- * which console window is its own.)
- */
-static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd)
-{
- char tmp[8];
- if (GetClassName(wnd, tmp, sizeof(tmp)) && !strcmp(tmp, "tty"))
- {
- DWORD wndproc, thisproc = GetCurrentProcessId();
- GetWindowThreadProcessId(wnd, &wndproc);
- if (wndproc == thisproc) {
- *((HWND*)retwnd) = wnd;
- return FALSE;
- }
- }
- return TRUE;
-}
-
-
-/* The remaining code all executes --in the tty's own process context--
- *
- * That means special attention must be paid to what it's doing...
- */
-
-/* Subclass message process for the tty window
- *
- * This code -handles- WM_CLOSE, WM_ENDSESSION and WM_QUERYENDSESSION
- * by dispatching them to the window identified by the hookwndprop
- * property atom set against our window. Messages are then dispatched
- * to origwndprop property atom we set against the window when we
- * injected this subclass. This trick did not work with simply a hook.
- */
-static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam)
-{
- WNDPROC origproc = (WNDPROC) GetProp(hwnd, origwndprop);
- if (!origproc)
- return 0;
-
- if (msg == WM_NCDESTROY
- || (msg == hookwndmsg && !LOWORD(wParam) && (HWND)lParam == hwnd))
- {
- if (is_subclassed) {
-#ifdef DBG
- DbgPrintf("W proc %08x hwnd:%08x Subclass removed\r\n",
- GetCurrentProcessId(), hwnd);
-#endif
- if (is_service)
- RegisterWindows9xService(FALSE);
- SetWindowLong(hwnd, GWL_WNDPROC, (LONG)origproc);
- RemoveProp(hwnd, origwndprop);
- RemoveProp(hwnd, hookwndprop);
- is_subclassed = FALSE;
- //if (hmodLock)
- // FreeLibrary(hmodLock);
- //hmodLock = NULL;
- }
- }
- else if (msg == WM_CLOSE || msg == WM_ENDSESSION
- || msg == WM_QUERYENDSESSION)
- {
- HWND child = (HWND)GetProp(hwnd, hookwndprop);
- if (child) {
-#ifdef DBG
- DbgPrintf("W proc %08x hwnd:%08x forwarded msg:%d\r\n",
- GetCurrentProcessId(), hwnd, msg);
-#endif
- return SendMessage(child, msg, wParam, lParam);
- }
- }
- return CallWindowProc(origproc, hwnd, msg, wParam, lParam);
-}
-
-
-/* HookProc, once installed, is responsible for subclassing the system
- * tty windows. It generally does nothing special itself, since
- * research indicates that it cannot deal well with the messages we are
- * interested in, that is, WM_CLOSE, WM_QUERYSHUTDOWN and WM_SHUTDOWN
- * of the tty process.
- *
- * Respond and subclass only when a WM_NULL is received by the window.
- */
-int HookProc(int hc, HWND *hwnd, UINT *msg, WPARAM *wParam, LPARAM *lParam)
-{
- if (is_tty == -1 && *hwnd)
- {
- char ttybuf[8];
- HWND htty;
- hwtty = *hwnd;
- while (htty = GetParent(hwtty))
- hwtty = htty;
- is_tty = (GetClassName(hwtty, ttybuf, sizeof(ttybuf))
- && !strcmp(ttybuf, "tty"));
-#ifdef DBG
- if (is_tty)
- DbgPrintf("H proc %08x tracking hwnd %08x\r\n",
- GetCurrentProcessId(), hwtty);
-#endif
- }
-
- if (*msg == hookwndmsg && *wParam && *lParam == (LPARAM)hwtty && is_tty)
- {
- WNDPROC origproc = (WNDPROC)GetWindowLong(hwtty, GWL_WNDPROC);
- //char myname[MAX_PATH];
- //if (GetModuleFileName(hmodThis, myname, sizeof(myname)))
- // hmodLock = LoadLibrary(myname);
- SetProp(hwtty, origwndprop, origproc);
- SetWindowLong(hwtty, GWL_WNDPROC, (LONG)WndProc);
- is_subclassed = TRUE;
-#ifdef DBG
- DbgPrintf("H proc %08x hwnd:%08x Subclassed\r\n",
- GetCurrentProcessId(), hwtty);
-#endif
- if (LOWORD(*wParam) == 2)
- RegisterWindows9xService(TRUE);
- }
-
- return -1;
-}
-
-
-/*
- * PostMessage Hook:
- */
-LRESULT __declspec(dllexport) CALLBACK GetMsgProc(INT hc, WPARAM wParam,
- LPARAM lParam)
-{
- PMSG pmsg;
-
- pmsg = (PMSG)lParam;
-
- if (pmsg) {
- int rv = HookProc(hc, &pmsg->hwnd, &pmsg->message,
- &pmsg->wParam, &pmsg->lParam);
- if (rv != -1)
- return rv;
- }
- /*
- * CallNextHookEx apparently ignores the hhook argument, so pass NULL
- */
- return CallNextHookEx(NULL, hc, wParam, lParam);
-}
-
-
-/*
- * SendMessage Hook:
- */
-LRESULT __declspec(dllexport) CALLBACK CallWndProc(INT hc, WPARAM wParam,
- LPARAM lParam)
-{
- PCWPSTRUCT pcwps = (PCWPSTRUCT)lParam;
-
- if (pcwps) {
- int rv = HookProc(hc, &pcwps->hwnd, &pcwps->message,
- &pcwps->wParam, &pcwps->lParam);
- if (rv != -1)
- return rv;
- }
- /*
- * CallNextHookEx apparently ignores the hhook argument, so pass NULL
- */
- return CallNextHookEx(NULL, hc, wParam, lParam);
-}
-
-
-#ifdef DBG
-VOID DbgPrintf(
- LPTSTR fmt,
- ...
- )
-{
- static HANDLE mutex;
- va_list marker;
- TCHAR szBuf[256];
- DWORD t;
- HANDLE gDbgOut;
-
- va_start(marker, fmt);
- wvsprintf(szBuf, fmt, marker);
- va_end(marker);
-
- if (!mutex)
- mutex = CreateMutex(NULL, FALSE, "Win9xConHookDbgOut");
- WaitForSingleObject(mutex, INFINITE);
- gDbgOut = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0,
- NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
- WriteFile(gDbgOut, szBuf, strlen(szBuf), &t, NULL);
- CloseHandle(gDbgOut);
- ReleaseMutex(mutex);
-}
-#endif
-
-#endif /* WIN32 */
diff --git a/server/mpm/winnt/Win9xConHook.def b/server/mpm/winnt/Win9xConHook.def
deleted file mode 100644
index 85ec166404e..00000000000
--- a/server/mpm/winnt/Win9xConHook.def
+++ /dev/null
@@ -1,10 +0,0 @@
-LIBRARY Win9xConHook
-
-EXETYPE WINDOWS
-
-EXPORTS
- DllMain
- GetMsgProc
- CallWndProc
- FixConsoleCtrlHandler
- Windows9xServiceCtrlHandler
diff --git a/server/mpm/winnt/Win9xConHook.dsp b/server/mpm/winnt/Win9xConHook.dsp
deleted file mode 100644
index 56ad1180a9d..00000000000
--- a/server/mpm/winnt/Win9xConHook.dsp
+++ /dev/null
@@ -1,103 +0,0 @@
-# Microsoft Developer Studio Project File - Name="Win9xConHook" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=Win9xConHook - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "Win9xConHook.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "Win9xConHook.mak" CFG="Win9xConHook - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "Win9xConHook - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "Win9xConHook - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "Win9xConHook - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir ".\Release"
-# PROP BASE Intermediate_Dir ".\Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\Win9xConHook" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /map /machine:I386 /base:"0x1c0f0000"
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /map /machine:I386 /base:"0x1c0f0000"
-
-!ELSEIF "$(CFG)" == "Win9xConHook - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\Win9xConHook" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /base:"0x1c0f0000"
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /base:"0x1c0f0000"
-
-!ENDIF
-
-# Begin Target
-
-# Name "Win9xConHook - Win32 Release"
-# Name "Win9xConHook - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\Win9xConHook.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\Win9xConHook.def
-# End Source File
-# Begin Source File
-
-SOURCE=.\Win9xConHook.h
-# End Source File
-# End Target
-# End Project
diff --git a/server/mpm/winnt/Win9xConHook.h b/server/mpm/winnt/Win9xConHook.h
deleted file mode 100644
index 312e82cd2de..00000000000
--- a/server/mpm/winnt/Win9xConHook.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* ====================================================================
- * 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
- * the documentation and/or other materials provided with the
- * 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.
- */
-
-#ifndef AP_WIN9XCONHOOK_H
-#define AP_WIN9XCONHOOK_H
-
-#ifdef WIN32
-
-/* Windows9xServiceCtrlHandler registers a handler routine, frees the
- * console window, and registers this process as a service in Win9x.
- * It creats a hidden window of class "ApacheWin95ServiceMonitor"
- * and titled by the name passed, which passes the WM_SHUTDOWN message
- * through the given HandlerRoutine's CTRL_SHUTDOWN event.
- * Call with name of NULL to remove the Service handler.
- */
-BOOL WINAPI Windows9xServiceCtrlHandler(PHANDLER_ROUTINE phandler, LPCSTR name);
-
-
-/* FixConsoleControlHandler registers a handler routine with the
- * Win9xConHook.dll, creating a hidden window and forwarding the
- * WM_ENDSESSION and WM_CLOSE messages to the given HandlerRoutine
- * as CTRL_SHUTDOWN_EVENT, CTRL_LOGOFF_EVENT and CTRL_CLOSE_EVENT.
- * The application should still use SetConsoleCtrlHandler to grab
- * the CTRL_BREAK_EVENT and CTRL_C_EVENT, if desired.
- */
-BOOL WINAPI FixConsoleCtrlHandler(PHANDLER_ROUTINE phandler, BOOL add);
-
-
-/*
- * Exported PostMessage Hook, never use this directly:
- *
- * LRESULT CALLBACK GetMsgProc(INT hc, WPARAM wParam, LPARAM lParam);
- */
-
-
-/*
- * Exported SendMessage Hook, never use this directly:
- *
- * LRESULT CALLBACK CallWndProc(INT hc, WPARAM wParam, LPARAM lParam);
- */
-
-#endif /* WIN32 */
-
-#endif AP_WIN9XCONHOOK_H
\ No newline at end of file
diff --git a/support/dbmmanage b/support/dbmmanage
deleted file mode 100644
index ad9a4aca761..00000000000
--- a/support/dbmmanage
+++ /dev/null
@@ -1,350 +0,0 @@
-#!/usr/bin/perl
-# ====================================================================
-# The Apache Software License, Version 1.1
-#
-# Copyright (c) 2000-2001 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
-# the documentation and/or other materials provided with the
-# 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
-# .
-#
-
-#for more functionality see the HTTPD::UserAdmin module:
-# http://www.perl.com/CPAN/modules/by-module/HTTPD/HTTPD-Tools-x.xx.tar.gz
-#
-# usage: dbmmanage
-
-package dbmmanage;
-# -ldb -lndbm -lgdbm -lsdbm
-BEGIN { @AnyDBM_File::ISA = qw(DB_File NDBM_File GDBM_File SDBM_File) }
-use strict;
-use Fcntl;
-use AnyDBM_File ();
-
-sub usage {
- my $cmds = join "|", sort keys %dbmc::;
- die <$command();
-untie %DB;
-
-
-my $x;
-sub genseed {
- my $psf;
- if ($not_unix) {
- srand (time ^ $$ or time ^ ($$ + ($$ << 15)));
- }
- else {
- for (qw(-xlwwa -le)) {
- `ps $_ 2>/dev/null`;
- $psf = $_, last unless $?;
- }
- srand (time ^ $$ ^ unpack("%L*", `ps $psf | gzip -f`));
- }
- @range = (qw(. /), '0'..'9','a'..'z','A'..'Z');
- $x = int scalar @range;
-}
-
-sub randchar {
- join '', map $range[rand $x], 1..shift||1;
-}
-
-sub saltpw_crypt {
- genseed() unless @range;
- return $newstyle_salt ?
- join '', "_", randchar, "a..", randchar(4) :
- randchar(2);
-}
-
-sub cryptpw_crypt {
- my ($pw, $salt) = @_;
- $salt = saltpw_crypt unless $salt;
- crypt $pw, $salt;
-}
-
-sub saltpw_md5 {
- genseed() unless @range;
- randchar(8);
-}
-
-sub cryptpw_md5 {
- my($pw, $salt) = @_;
- $salt = saltpw_md5 unless $salt;
- Crypt::PasswdMD5::apache_md5_crypt($pw, $salt);
-}
-
-sub cryptpw_sha1 {
- my($pw, $salt) = @_;
- '{SHA}' . Digest::SHA1::sha1_base64($pw) . "=";
-}
-
-sub cryptpw {
- if ($crypt_method eq "md5") {
- return cryptpw_md5(@_);
- } elsif ($crypt_method eq "sha1") {
- return cryptpw_sha1(@_);
- } elsif ($crypt_method eq "crypt") {
- return cryptpw_crypt(@_);
- }
- @_[0]; # otherwise return plaintext
-}
-
-sub getpass {
- my $prompt = shift || "Enter password:";
-
- unless($not_unix) {
- open STDIN, "/dev/tty" or warn "couldn't open /dev/tty $!\n";
- system "stty -echo;";
- }
-
- my($c,$pwd);
- print STDERR $prompt;
- while (($c = getc(STDIN)) ne '' and $c ne "\n" and $c ne "\r") {
- $pwd .= $c;
- }
-
- system "stty echo" unless $not_unix;
- print STDERR "\n";
- die "Can't use empty password!\n" unless length $pwd;
- return $pwd;
-}
-
-sub dbmc::update {
- die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key};
- $crypted_pwd = (split /:/, $DB{$key}, 3)[0] if $crypted_pwd eq '.';
- $groups = (split /:/, $DB{$key}, 3)[1] if !$groups || $groups eq '.';
- $comment = (split /:/, $DB{$key}, 3)[2] if !$comment || $comment eq '.';
- if (!$crypted_pwd || $crypted_pwd eq '-') {
- dbmc->adduser;
- }
- else {
- dbmc->add;
- }
-}
-
-sub dbmc::add {
- die "Can't use empty password!\n" unless $crypted_pwd;
- unless($is_update) {
- die "Sorry, user `$key' already exists!\n" if $DB{$key};
- }
- $groups = '' if $groups eq '-';
- $comment = '' if $comment eq '-';
- $groups .= ":" . $comment if $comment;
- $crypted_pwd .= ":" . $groups if $groups;
- $DB{$key} = $crypted_pwd;
- my $action = $is_update ? "updated" : "added";
- print "User $key $action with password encrypted to $DB{$key} using $crypt_method\n";
-}
-
-sub dbmc::adduser {
- my $value = getpass "New password:";
- die "They don't match, sorry.\n" unless getpass("Re-type new password:") eq $value;
- $crypted_pwd = cryptpw $value;
- dbmc->add;
-}
-
-sub dbmc::delete {
- die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key};
- delete $DB{$key}, print "`$key' deleted\n";
-}
-
-sub dbmc::view {
- print $key ? "$key:$DB{$key}\n" : map { "$_:$DB{$_}\n" if $DB{$_} } keys %DB;
-}
-
-sub dbmc::check {
- die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key};
- my $chkpass = (split /:/, $DB{$key}, 3)[0];
- my $testpass = getpass();
- if (substr($chkpass, 0, 6) eq '$apr1$') {
- need_md5_crypt;
- $crypt_method = "md5";
- } elsif (substr($chkpass, 0, 5) eq '{SHA}') {
- need_sha1_crypt;
- $crypt_method = "sha1";
- } elsif (length($chkpass) == 13 && $chkpass ne $testpass) {
- $crypt_method = "crypt";
- } else {
- $crypt_method = "plain";
- }
- print $crypt_method . (cryptpw($testpass, $chkpass) eq $chkpass
- ? " password ok\n" : " password mismatch\n");
-}
-
-sub dbmc::import {
- while(defined($_ = ) and chomp) {
- ($key,$crypted_pwd,$groups,$comment) = split /:/, $_, 4;
- dbmc->add;
- }
-}
-
diff --git a/support/log_server_status b/support/log_server_status
deleted file mode 100644
index e32280c9127..00000000000
--- a/support/log_server_status
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/perl
-# ====================================================================
-# The Apache Software License, Version 1.1
-#
-# Copyright (c) 2000-2001 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
-# the documentation and/or other materials provided with the
-# 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
-# .
-#
-# Log Server Status
-# Mark J Cox, UK Web Ltd 1996, mark@ukweb.com
-#
-# This script is designed to be run at a frequent interval by something
-# like cron. It connects to the server and downloads the status
-# information. It reformats the information to a single line and logs
-# it to a file. Make sure the directory $wherelog is writable by the
-# user who runs this script.
-#
-require 'sys/socket.ph';
-
-$wherelog = "/var/log/graph/"; # Logs will be like "/var/log/graph/19960312"
-$server = "localhost"; # Name of server, could be "www.foo.com"
-$port = "80"; # Port on server
-$request = "/status/?auto"; # Request to send
-
-sub tcp_connect
-{
- local($host,$port) =@_;
- $sockaddr='S n a4 x8';
- chop($hostname=`hostname`);
- $port=(getservbyname($port, 'tcp'))[2] unless $port =~ /^\d+$/;
- $me=pack($sockaddr,&AF_INET,0,(gethostbyname($hostname))[4]);
- $them=pack($sockaddr,&AF_INET,$port,(gethostbyname($host))[4]);
- socket(S,&PF_INET,&SOCK_STREAM,(getprotobyname('tcp'))[2]) ||
- die "socket: $!";
- bind(S,$me) || return "bind: $!";
- connect(S,$them) || return "connect: $!";
- select(S);
- $| = 1;
- select(stdout);
- return "";
-}
-
-### Main
-
-{
- $year=`date +%y`;
- chomp($year);
- $year += ($year < 70) ? 2000 : 1900;
- $date = $year . `date +%m%d:%H%M%S`;
- chomp($date);
- ($day,$time)=split(/:/,$date);
- $res=&tcp_connect($server,$port);
- open(OUT,">>$wherelog$day");
- if ($res) {
- print OUT "$time:-1:-1:-1:-1:$res\n";
- exit 1;
- }
- print S "GET $request\n";
- while () {
- $requests=$1 if ( m|^BusyServers:\ (\S+)|);
- $idle=$1 if ( m|^IdleServers:\ (\S+)|);
- $number=$1 if ( m|sses:\ (\S+)|);
- $cpu=$1 if (m|^CPULoad:\ (\S+)|);
- }
- print OUT "$time:$requests:$idle:$number:$cpu\n";
-}
-
-
diff --git a/support/logresolve.pl b/support/logresolve.pl
deleted file mode 100644
index ab5a7322ab2..00000000000
--- a/support/logresolve.pl
+++ /dev/null
@@ -1,261 +0,0 @@
-#!/usr/bin/perl
-# ====================================================================
-# The Apache Software License, Version 1.1
-#
-# Copyright (c) 2000-2001 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
-# the documentation and/or other materials provided with the
-# 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
-# .
-#
-# logresolve.pl
-#
-# v 1.2 by robh @ imdb.com
-#
-# usage: logresolve.pl outfile
-#
-# input = Apache/NCSA/.. logfile with IP numbers at start of lines
-# output = same logfile with IP addresses resolved to hostnames where
-# name lookups succeeded.
-#
-# this differs from the C based 'logresolve' in that this script
-# spawns a number ($CHILDREN) of subprocesses to resolve addresses
-# concurrently and sets a short timeout ($TIMEOUT) for each lookup in
-# order to keep things moving quickly.
-#
-# the parent process handles caching of IP->hostnames using a Perl hash
-# it also avoids sending the same IP to multiple child processes to be
-# resolved multiple times concurrently.
-#
-# Depending on the settings of $CHILDREN and $TIMEOUT you should see
-# significant reductions in the overall time taken to resolve your
-# logfiles. With $CHILDREN=40 and $TIMEOUT=5 I've seen 200,000 - 300,000
-# logfile lines processed per hour compared to ~45,000 per hour
-# with 'logresolve'.
-#
-# I haven't yet seen any noticable reduction in the percentage of IPs
-# that fail to get resolved. Your mileage will no doubt vary. 5s is long
-# enough to wait IMO.
-#
-# Known to work with FreeBSD 2.2
-# Known to have problems with Solaris
-#
-# 980417 - use 'sockaddr_un' for bind/connect to make the script work
-# with linux. Fix from Luuk de Boer
-
-require 5.004;
-
-$|=1;
-
-use FileHandle;
-use Socket;
-
-use strict;
-no strict 'refs';
-
-use vars qw($PROTOCOL);
-$PROTOCOL = 0;
-
-my $CHILDREN = 40;
-my $TIMEOUT = 5;
-
-my $filename;
-my %hash = ();
-my $parent = $$;
-
-my @children = ();
-for (my $child = 1; $child <=$CHILDREN; $child++) {
- my $f = fork();
- if (!$f) {
- $filename = "./.socket.$parent.$child";
- if (-e $filename) { unlink($filename) || warn "$filename .. $!\n";}
- &child($child);
- exit(0);
- }
- push(@children, $f);
-}
-
-&parent;
-&cleanup;
-
-## remove all temporary files before shutting down
-sub cleanup {
- # die kiddies, die
- kill(15, @children);
- for (my $child = 1; $child <=$CHILDREN; $child++) {
- if (-e "./.socket.$parent.$child") {
- unlink("./.socket.$parent.$child")
- || warn ".socket.$parent.$child $!";
- }
- }
-}
-
-sub parent {
- # Trap some possible signals to trigger temp file cleanup
- $SIG{'KILL'} = $SIG{'INT'} = $SIG{'PIPE'} = \&cleanup;
-
- my %CHILDSOCK;
- my $filename;
-
- ## fork child processes. Each child will create a socket connection
- ## to this parent and use an unique temp filename to do so.
- for (my $child = 1; $child <=$CHILDREN; $child++) {
- $CHILDSOCK{$child}= FileHandle->new;
-
- if (!socket($CHILDSOCK{$child}, AF_UNIX, SOCK_STREAM, $PROTOCOL)) {
- warn "parent socket to child failed $!";
- }
- $filename = "./.socket.$parent.$child";
- my $response;
- do {
- $response = connect($CHILDSOCK{$child}, sockaddr_un($filename));
- if ($response != 1) {
- sleep(1);
- }
- } while ($response != 1);
- $CHILDSOCK{$child}->autoflush;
- }
- ## All child processes should now be ready or at worst warming up
-
- my (@buffer, $child, $ip, $rest, $hostname, $response);
- ## read the logfile lines from STDIN
- while() {
- @buffer = (); # empty the logfile line buffer array.
- $child = 1; # children are numbered 1..N, start with #1
-
- # while we have a child to talk to and data to give it..
- do {
- push(@buffer, $_); # buffer the line
- ($ip, $rest) = split(/ /, $_, 2); # separate IP form rest
-
- unless ($hash{$ip}) { # resolve if unseen IP
- $CHILDSOCK{$child}->print("$ip\n"); # pass IP to next child
- $hash{$ip} = $ip; # don't look it up again.
- $child++;
- }
- } while (($child < ($CHILDREN-1)) and ($_ = ));
-
- ## now poll each child for a response
- while (--$child > 0) {
- $response = $CHILDSOCK{$child}->getline;
- chomp($response);
- # child sends us back both the IP and HOSTNAME, no need for us
- # to remember what child received any given IP, and no worries
- # what order we talk to the children
- ($ip, $hostname) = split(/\|/, $response, 2);
- $hash{$ip} = $hostname;
- }
-
- # resolve all the logfiles lines held in the log buffer array..
- for (my $line = 0; $line <=$#buffer; $line++) {
- # get next buffered line
- ($ip, $rest) = split(/ /, $buffer[$line], 2);
- # separate IP from rest and replace with cached hostname
- printf STDOUT ("%s %s", $hash{$ip}, $rest);
- }
- }
-}
-
-########################################
-
-sub child {
- # arg = numeric ID - how the parent refers to me
- my $me = shift;
-
- # add trap for alarm signals.
- $SIG{'ALRM'} = sub { die "alarmed"; };
-
- # create a socket to communicate with parent
- socket(INBOUND, AF_UNIX, SOCK_STREAM, $PROTOCOL)
- || die "Error with Socket: !$\n";
- $filename = "./.socket.$parent.$me";
- bind(INBOUND, sockaddr_un($filename))
- || die "Error Binding $filename: $!\n";
- listen(INBOUND, 5) || die "Error Listening: $!\n";
-
- my ($ip, $send_back);
- my $talk = FileHandle->new;
-
- # accept a connection from the parent process. We only ever have
- # have one connection where we exchange 1 line of info with the
- # parent.. 1 line in (IP address), 1 line out (IP + hostname).
- accept($talk, INBOUND) || die "Error Accepting: $!\n";
- # disable I/O buffering just in case
- $talk->autoflush;
- # while the parent keeps sending data, we keep responding..
- while(($ip = $talk->getline)) {
- chomp($ip);
- # resolve the IP if time permits and send back what we found..
- $send_back = sprintf("%s|%s", $ip, &nslookup($ip));
- $talk->print($send_back."\n");
- }
-}
-
-# perform a time restricted hostname lookup.
-sub nslookup {
- # get the IP as an arg
- my $ip = shift;
- my $hostname = undef;
-
- # do the hostname lookup inside an eval. The eval will use the
- # already configured SIGnal handler and drop out of the {} block
- # regardless of whether the alarm occured or not.
- eval {
- alarm($TIMEOUT);
- $hostname = gethostbyaddr(gethostbyname($ip), AF_INET);
- alarm(0);
- };
- if ($@ =~ /alarm/) {
- # useful for debugging perhaps..
- # print "alarming, isn't it? ($ip)";
- }
-
- # return the hostname or the IP address itself if there is no hostname
- $hostname ne "" ? $hostname : $ip;
-}
-
-
diff --git a/support/phf_abuse_log.cgi b/support/phf_abuse_log.cgi
deleted file mode 100644
index 87543ce5f48..00000000000
--- a/support/phf_abuse_log.cgi
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/perl
-
-# This script is used to detect people trying to abuse the security hole which
-# existed in A CGI script direstributed with Apache 1.0.3 and earlier versions.
-# You can redirect them to here using the "" suggestion
-# in httpd.conf.
-#
-# The format logged to is
-# "[date] remote_addr remote_host [date] referrer user_agent".
-
-$LOG = "/var/log/phf_log";
-
-require "ctime.pl";
-$when = &ctime(time);
-$when =~ s/\n//go;
-$ENV{HTTP_USER_AGENT} .= " via $ENV{HTTP_VIA}" if($ENV{HTTP_VIA});
-
-open(LOG, ">>$LOG") || die "boo hoo, phf_log $!";
-print LOG "[$when] $ENV{REMOTE_ADDR} $ENV{REMOTE_HOST} $ENV{$HTTP_REFERER} $ENV{HTTP_USER_AGENT}\n";
-close(LOG);
-
-print "Content-type: text/html\r\n\r\n\n";
diff --git a/support/split-logfile b/support/split-logfile
deleted file mode 100644
index c0f34861aab..00000000000
--- a/support/split-logfile
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/perl
-# ====================================================================
-# The Apache Software License, Version 1.1
-#
-# Copyright (c) 2000-2001 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
-# the documentation and/or other materials provided with the
-# 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
-# .
-
-# This script will take a combined Web server access
-# log file and break its contents into separate files.
-# It assumes that the first field of each line is the
-# virtual host identity (put there by "%v"), and that
-# the logfiles should be named that+".log" in the current
-# directory.
-#
-# The combined log file is read from stdin. Records read
-# will be appended to any existing log files.
-#
-%is_open = ();
-
-while ($log_line = ) {
- #
- # Get the first token from the log record; it's the
- # identity of the virtual host to which the record
- # applies.
- #
- ($vhost) = split (/\s/, $log_line);
- #
- # Normalize the virtual host name to all lowercase.
- # If it's blank, the request was handled by the default
- # server, so supply a default name. This shouldn't
- # happen, but caution rocks.
- #
- $vhost = lc ($vhost) or "access";
- #
- # If the log file for this virtual host isn't opened
- # yet, do it now.
- #
- if (! $is_open{$vhost}) {
- open $vhost, ">>${vhost}.log"
- or die ("Can't open ${vhost}.log");
- $is_open{$vhost} = 1;
- }
- #
- # Strip off the first token (which may be null in the
- # case of the default server), and write the edited
- # record to the current log file.
- #
- $log_line =~ s/^\S*\s+//;
- printf $vhost "%s", $log_line;
-}
-exit 0;