diff options
55 files changed, 0 insertions, 15989 deletions
diff --git a/docs/manual/bind.html.en b/docs/manual/bind.html.en deleted file mode 100644 index 208c6c54a2..0000000000 --- a/docs/manual/bind.html.en +++ /dev/null @@ -1,78 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML><HEAD> -<TITLE>Setting which addresses and ports Apache uses</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<H1 ALIGN="CENTER">Setting which addresses and ports Apache uses</H1> - -<p>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 <code>Port</code> 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.</p> - -<p>The <code>Listen</code> 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 -<code>Listen</code> directive, the server listens to the given port on -all interfaces, instead of the port given by the <code>Port</code> -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.</P> - -<p>For example, to make the server accept connections on both port -80 and port 8000, use: -<PRE> - Listen 80 - Listen 8000 -</PRE> - -To make the server accept connections on two specified -interfaces and port numbers, use -<PRE> - Listen 192.170.2.1:80 - Listen 192.170.2.5:8000 -</PRE> - -<H2>How this works with Virtual Hosts</H2> - -<p>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. - -<H2>See also</H2> - -See also the documentation on -<a href="mod/mpm_common.html#listen">Listen directive</a>, -<A HREF="vhosts/">Virtual Hosts</A>, -<A HREF="mod/core.html#port">Port directive</A>, -<A HREF="dns-caveats.html">DNS Issues</A> -and -<A HREF="mod/core.html#virtualhost"><VirtualHost> section</A>. - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> - diff --git a/docs/manual/cgi_path.html.en b/docs/manual/cgi_path.html.en deleted file mode 100644 index 2b7bd963b1..0000000000 --- a/docs/manual/cgi_path.html.en +++ /dev/null @@ -1,93 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML><HEAD> -<TITLE>PATH_INFO Changes in the CGI Environment</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<H1 ALIGN="CENTER">PATH_INFO Changes in the CGI Environment</H1> - -<HR> - -<H2><A NAME="over">Overview</A></H2> - -<P>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 (<A -HREF="#compat">see below</A>). - -<H2><A NAME="prob">The Problem</A></H2> - -<P>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: -<PRE> - Alias /cgi-ralph /usr/local/httpd/cgi-bin/user.cgi/ralph -</PRE> -<P>In this case, <CODE>user.cgi</CODE> 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 "<CODE>/cgi-ralph/script/</CODE>", the -code would set PATH_INFO to "<CODE>/ralph/script</CODE>", and -SCRIPT_NAME to "<CODE>/cgi-</CODE>". Obviously, the latter is -incorrect. In certain cases, this could even cause the server to -crash.</P> - -<H2><A NAME="solution">The Solution</A></H2> - -<P>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 "<CODE>/script</CODE>", and -SCRIPT_NAME to "<CODE>/cgi-ralph</CODE>". This makes sense and results -in no server behavior problems. It also permits the script to be -guaranteed that -"<CODE>http://$SERVER_NAME:$SERVER_PORT$SCRIPT_NAME$PATH_INFO</CODE>" -will always be an accessible URL that points to the current script, -something which was not necessarily true with previous versions of -Apache. - -<P>However, the "<CODE>/ralph</CODE>" -information from the <CODE>Alias</CODE> 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 HREF="#compat">a workaround.</A> - -<H2><A NAME="compat">Compatibility with Previous Servers</A></H2> - -<P>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.</P> - -<P>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: -<PRE> - $path_info = $ENV{'FILEPATH_INFO'} || $ENV{'PATH_INFO'}; -</PRE> - -<P>By doing this, a script can work with all servers supporting the -CGI/1.1 specification, including all versions of Apache.</P> - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> - diff --git a/docs/manual/content-negotiation.html.en b/docs/manual/content-negotiation.html.en deleted file mode 100644 index d1b4ab20ab..0000000000 --- a/docs/manual/content-negotiation.html.en +++ /dev/null @@ -1,590 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Apache Content Negotiation</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<H1 ALIGN="CENTER">Content Negotiation</H1> - -<P> -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. <P> - -Content negotiation is provided by the -<A HREF="mod/mod_negotiation.html">mod_negotiation</A> module, -which is compiled in by default. - -<HR> - -<H2>About Content Negotiation</H2> - -<P> -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 - -<PRE> - Accept-Language: fr -</PRE> - -<P> -Note that this preference will only be applied when there is a choice -of representations and they vary by language. -<P> - -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: - -<PRE> - 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 -</PRE> - -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. -<P> - -A <STRONG>resource</STRONG> is a conceptual entity identified by a URI -(RFC 2396). An HTTP server like Apache provides access to -<STRONG>representations</STRONG> 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 <STRONG>negotiable</STRONG> and each of its -representations is termed a <STRONG>variant</STRONG>. The ways in which the -variants for a negotiable resource vary are called the -<STRONG>dimensions</STRONG> of negotiation. - -<H2>Negotiation in Apache</H2> - -<P> -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: - -<UL> - <LI> Using a type map (<EM>i.e.</EM>, a <CODE>*.var</CODE> file) which - names the files containing the variants explicitly, or - <LI> Using a 'MultiViews' search, where the server does an implicit - filename pattern match and chooses from among the results. -</UL> - -<H3>Using a type-map file</H3> - -<P> -A type map is a document which is associated with the handler -named <CODE>type-map</CODE> (or, for backwards-compatibility with -older Apache configurations, the mime type -<CODE>application/x-type-map</CODE>). Note that to use this feature, -you must have a handler set in the configuration that defines a -file suffix as <CODE>type-map</CODE>; this is best done with a - -<PRE> - AddHandler type-map .var -</PRE> - -in the server configuration file. See the comments in the sample config -file for more details. <P> - -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: - -<PRE> - 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 -</PRE> - -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): - -<PRE> - 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 -</PRE> -<P> - -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. - -<P> -The full list of headers recognized is: - -<DL> - <DT> <CODE>URI:</CODE> - <DD> uri of the file containing the variant (of the given media - type, encoded with the given content encoding). These are - interpreted as URLs relative to the map file; they must be on - the same server (!), and they must refer to files to which the - client would be granted access if they were to be requested - directly. - <DT> <CODE>Content-Type:</CODE> - <DD> media type --- charset, level and "qs" parameters may be given. These - are often referred to as MIME types; typical media types are - <CODE>image/gif</CODE>, <CODE>text/plain</CODE>, or - <CODE>text/html; level=3</CODE>. - <DT> <CODE>Content-Language:</CODE> - <DD> The languages of the variant, specified as an Internet standard - language tag from RFC 1766 (<EM>e.g.</EM>, <CODE>en</CODE> for English, - <CODE>kr</CODE> for Korean, <EM>etc.</EM>). - <DT> <CODE>Content-Encoding:</CODE> - <DD> If the file is compressed, or otherwise encoded, rather than - containing the actual raw data, this says how that was done. - Apache only recognizes encodings that are defined by an - <A HREF="mod/mod_mime.html#addencoding">AddEncoding</A> directive. - This normally includes the encodings <CODE>x-compress</CODE> - for compress'd files, and <CODE>x-gzip</CODE> for gzip'd files. - The <CODE>x-</CODE> prefix is ignored for encoding comparisons. - <DT> <CODE>Content-Length:</CODE> - <DD> The size of the file. Specifying content - lengths in the type-map allows the server to compare file sizes - without checking the actual files. - <DT> <CODE>Description:</CODE> - <DD> A human-readable textual description of the variant. If Apache cannot - find any appropriate variant to return, it will return an error - response which lists all available variants instead. Such a variant - list will include the human-readable variant descriptions. -</DL> - -<H3>Multiviews</H3> - -<P> -<CODE>MultiViews</CODE> is a per-directory option, meaning it can be set with -an <CODE>Options</CODE> directive within a <CODE><Directory></CODE>, -<CODE><Location></CODE> or <CODE><Files></CODE> -section in <CODE>access.conf</CODE>, or (if <CODE>AllowOverride</CODE> -is properly set) in <CODE>.htaccess</CODE> files. Note that -<CODE>Options All</CODE> does not set <CODE>MultiViews</CODE>; you -have to ask for it by name. - -<P> -The effect of <CODE>MultiViews</CODE> is as follows: if the server -receives a request for <CODE>/some/dir/foo</CODE>, if -<CODE>/some/dir</CODE> has <CODE>MultiViews</CODE> enabled, and -<CODE>/some/dir/foo</CODE> does <EM>not</EM> 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. - -<P> -<CODE>MultiViews</CODE> may also apply to searches for the file named by the -<CODE>DirectoryIndex</CODE> directive, if the server is trying to -index a directory. If the configuration files specify - -<PRE> - DirectoryIndex index -</PRE> - -then the server will arbitrate between <CODE>index.html</CODE> -and <CODE>index.html3</CODE> if both are present. If neither are -present, and <CODE>index.cgi</CODE> is there, the server will run it. - -<P> -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. - -<H2>The Negotiation Methods</H2> - -After Apache has obtained a list of the variants for a given resource, -either from a type-map file or from the filenames in the directory, it -invokes one of two methods to decide on the 'best' variant to -return, if any. It is not necessary to know any of the details of how -negotiation actually takes place in order to use Apache's content -negotiation features. However the rest of this document explains the -methods used for those interested. -<P> - -There are two negotiation methods: - -<OL> - -<LI><STRONG>Server driven negotiation with the Apache -algorithm</STRONG> is used in the normal case. The Apache algorithm is -explained in more detail below. When this algorithm is used, Apache -can sometimes 'fiddle' the quality factor of a particular dimension to -achieve a better result. The ways Apache can fiddle quality factors is -explained in more detail below. - -<LI><STRONG>Transparent content negotiation</STRONG> is used when the -browser specifically requests this through the mechanism defined in RFC -2295. This negotiation method gives the browser full control over -deciding on the 'best' variant, the result is therefore dependent on -the specific algorithms used by the browser. As part of the -transparent negotiation process, the browser can ask Apache to run the -'remote variant selection algorithm' defined in RFC 2296. - -</OL> - - -<H3>Dimensions of Negotiation</H3> - -<TABLE> -<TR valign="top"> -<TH>Dimension -<TH>Notes -<TR valign="top"> -<TD>Media Type -<TD>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). -<TR valign="top"> -<TD>Language -<TD>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. -<TR valign="top"> -<TD>Encoding -<TD>Browser indicates preference with the Accept-Encoding header field. -Each item can have a quality factor. -<TR valign="top"> -<TD>Charset -<TD>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. -</TABLE> - -<H3>Apache Negotiation Algorithm</H3> - -<P> -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: - -<OL> -<LI>First, for each dimension of the negotiation, check the appropriate -<EM>Accept*</EM> header field and assign a quality to each -variant. If the <EM>Accept*</EM> header for any dimension implies that this -variant is not acceptable, eliminate it. If no variants remain, go -to step 4. - -<LI>Select the 'best' variant by a process of elimination. Each of the -following tests is applied in order. Any variants not selected at each -test are eliminated. After each test, if only one variant remains, -select it as the best match and proceed to step 3. If more than one -variant remains, move on to the next test. - -<OL> -<LI>Multiply the quality factor from the Accept header with the - quality-of-source factor for this variant's media type, and select - the variants with the highest value. - -<LI>Select the variants with the highest language quality factor. - -<LI>Select the variants with the best language match, using either the - order of languages in the Accept-Language header (if present), or else - the order of languages in the <CODE>LanguagePriority</CODE> - directive (if present). - -<LI>Select the variants with the highest 'level' media parameter - (used to give the version of text/html media types). - -<LI>Select variants with the best charset media parameters, - as given on the Accept-Charset header line. Charset ISO-8859-1 - is acceptable unless explicitly excluded. Variants with a - <CODE>text/*</CODE> media type but not explicitly associated - with a particular charset are assumed to be in ISO-8859-1. - -<LI>Select those variants which have associated - charset media parameters that are <EM>not</EM> ISO-8859-1. - If there are no such variants, select all variants instead. - -<LI>Select the variants with the best encoding. If there are - variants with an encoding that is acceptable to the user-agent, - select only these variants. Otherwise if there is a mix of encoded - and non-encoded variants, select only the unencoded variants. - If either all variants are encoded or all variants are not encoded, - select all variants. - -<LI>Select the variants with the smallest content length. - -<LI>Select the first variant of those remaining. This will be either the - first listed in the type-map file, or when variants are read from - the directory, the one whose file name comes first when sorted using - ASCII code order. - -</OL> - -<LI>The algorithm has now selected one 'best' variant, so return - it as the response. The HTTP response header Vary is set to indicate the - dimensions of negotiation (browsers and caches can use this - information when caching the resource). End. - -<LI>To get here means no variant was selected (because none are acceptable - to the browser). Return a 406 status (meaning "No acceptable representation") - with a response body consisting of an HTML document listing the - available variants. Also set the HTTP Vary header to indicate the - dimensions of variance. - -</OL> - -<H2><A NAME="better">Fiddling with Quality Values</A></H2> - -<P> -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. -<P> - -<H3>Media Types and Wildcards</H3> - -<P> -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: -<PRE> - Accept: image/*, */* -</PRE> - -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: -<PRE> - Accept: text/html, text/plain, image/gif, image/jpeg, */* -</PRE> - -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: -<PRE> - Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01 -</PRE> - -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. -<P> - -If the Accept: header contains <EM>no</EM> 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 <EM>not</EM> applied, so requests from browsers -which send the correct information to start with work as expected. - -<H3>Variants with no Language</H3> - -<P> -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.<P> - -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: - -<UL> -<LI>foo.en.html, language en -<LI>foo.fr.html, language en -<LI>foo.html, no language -</UL> - -<P> -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. - -<H2>Extensions to Transparent Content Negotiation</H2> - -Apache extends the transparent content negotiation protocol (RFC 2295) -as follows. A new <CODE> {encoding ..}</CODE> 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. - -<H2>Note on hyperlinks and naming conventions</H2> - -<P> -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 <A HREF="mod/mod_mime.html">mod_mime</A> documentation for details). -<P> -A typical file has a MIME-type extension (<EM>e.g.</EM>, <SAMP>html</SAMP>), -maybe an encoding extension (<EM>e.g.</EM>, <SAMP>gz</SAMP>), and of course a -language extension (<EM>e.g.</EM>, <SAMP>en</SAMP>) when we have different -language variants of this file. - -<P> -Examples: -<UL> -<LI>foo.en.html -<LI>foo.html.en -<LI>foo.en.html.gz -</UL> - -<P> -Here some more examples of filenames together with valid and invalid -hyperlinks: -</P> - -<TABLE BORDER=1 CELLPADDING=8 CELLSPACING=0> -<TR> - <TH>Filename</TH> - <TH>Valid hyperlink</TH> - <TH>Invalid hyperlink</TH> -</TR> -<TR> - <TD><EM>foo.html.en</EM></TD> - <TD>foo<BR> - foo.html</TD> - <TD>-</TD> -</TR> -<TR> - <TD><EM>foo.en.html</EM></TD> - <TD>foo</TD> - <TD>foo.html</TD> -</TR> -<TR> - <TD><EM>foo.html.en.gz</EM></TD> - <TD>foo<BR> - foo.html</TD> - <TD>foo.gz<BR> - foo.html.gz</TD> -</TR> -<TR> - <TD><EM>foo.en.html.gz</EM></TD> - <TD>foo</TD> - <TD>foo.html<BR> - foo.html.gz<BR> - foo.gz</TD> -</TR> -<TR> - <TD><EM>foo.gz.html.en</EM></TD> - <TD>foo<BR> - foo.gz<BR> - foo.gz.html</TD> - <TD>foo.html</TD> -</TR> -<TR> - <TD><EM>foo.html.gz.en</EM></TD> - <TD>foo<BR> - foo.html<BR> - foo.html.gz</TD> - <TD>foo.gz</TD> -</TR> -</TABLE> - -<P> -Looking at the table above you will notice that it is always possible to -use the name without any extensions in an hyperlink (<EM>e.g.</EM>, <SAMP>foo</SAMP>). -The advantage is that you can hide the actual type of a -document rsp. file and can change it later, <EM>e.g.</EM>, from <SAMP>html</SAMP> -to <SAMP>shtml</SAMP> or <SAMP>cgi</SAMP> without changing any -hyperlink references. - -<P> -If you want to continue to use a MIME-type in your hyperlinks (<EM>e.g.</EM> -<SAMP>foo.html</SAMP>) the language extension (including an encoding extension -if there is one) must be on the right hand side of the MIME-type extension -(<EM>e.g.</EM>, <SAMP>foo.html.en</SAMP>). - - -<H2>Note on Caching</H2> - -<P> -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. <P> - -For requests which come from a HTTP/1.0 compliant client (either a -browser or a cache), the directive <TT>CacheNegotiatedDocs</TT> 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. - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/docs/manual/custom-error.html.en b/docs/manual/custom-error.html.en deleted file mode 100644 index 09604ea972..0000000000 --- a/docs/manual/custom-error.html.en +++ /dev/null @@ -1,177 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Custom error responses</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<H1 ALIGN="CENTER">Custom error responses</H1> - -<DL> - -<DT>Purpose - - <DD>Additional functionality. Allows webmasters to configure the response of - Apache to some error or problem. - - <P>Customizable responses can be defined to be activated in the - event of a server detected error or problem. - - <P>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). - <P> - -<DT>Old behavior - - <DD>NCSA httpd 1.3 would return some boring old error/problem message - which would often be meaningless to the user, and would provide no - means of logging the symptoms which caused it.<BR> - - <P> - -<DT>New behavior - - <DD>The server can be asked to; - <OL> - <LI>Display some other text, instead of the NCSA hard coded messages, or - <LI>redirect to a local URL, or - <LI>redirect to an external URL. - </OL> - - <P>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. - - <P>To achieve this, Apache will define new CGI-like environment - variables, <EM>e.g.</EM> - - <BLOCKQUOTE><CODE> -REDIRECT_HTTP_ACCEPT=*/*, image/gif, image/x-xbitmap, image/jpeg <BR> -REDIRECT_HTTP_USER_AGENT=Mozilla/1.1b2 (X11; I; HP-UX A.09.05 9000/712) <BR> -REDIRECT_PATH=.:/bin:/usr/local/bin:/etc <BR> -REDIRECT_QUERY_STRING= <BR> -REDIRECT_REMOTE_ADDR=121.345.78.123 <BR> -REDIRECT_REMOTE_HOST=ooh.ahhh.com <BR> -REDIRECT_SERVER_NAME=crash.bang.edu <BR> -REDIRECT_SERVER_PORT=80 <BR> -REDIRECT_SERVER_SOFTWARE=Apache/0.8.15 <BR> -REDIRECT_URL=/cgi-bin/buggy.pl <BR> - </CODE></BLOCKQUOTE> - - <P>note the <CODE>REDIRECT_</CODE> prefix. - - <P>At least <CODE>REDIRECT_URL</CODE> and <CODE>REDIRECT_QUERY_STRING</CODE> - 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. - <STRONG>None</STRONG> of these will be set if your ErrorDocument is an - <EM>external</EM> redirect (<EM>i.e.</EM>, anything starting with a - scheme name - like <CODE>http:</CODE>, even if it refers to the same host as the - server).<P> - -<DT>Configuration - - <DD> Use of "ErrorDocument" is enabled for .htaccess files when the - <A HREF="mod/core.html#allowoverride">"FileInfo" override</A> is - allowed. - - <P>Here are some examples... - - <BLOCKQUOTE><CODE> -ErrorDocument 500 /cgi-bin/crash-recover <BR> -ErrorDocument 500 "Sorry, our script crashed. Oh dear<BR> -ErrorDocument 500 http://xxx/ <BR> -ErrorDocument 404 /Lame_excuses/not_found.html <BR> -ErrorDocument 401 /Subscription/how_to_subscribe.html - </CODE></BLOCKQUOTE> - - <P>The syntax is, - - <P><CODE><A HREF="mod/core.html#errordocument">ErrorDocument</A></CODE> -<3-digit-code> action - - <P>where the action can be, - - <OL> - <LI>Text to be displayed. Prefix the text with a quote ("). Whatever - follows the quote is displayed. <EM>Note: the (") prefix isn't - displayed.</EM> - - <LI>An external URL to redirect to. - - <LI>A local URL to redirect to. - - </OL> -</DL> - -<P><HR><P> - -<H2>Custom error responses and redirects</H2> - -<DL> - -<DT>Purpose - - <DD>Apache's behavior to redirected URLs has been modified so that additional - environment variables are available to a script/server-include.<P> - -<DT>Old behavior - - <DD>Standard CGI vars were made available to a script which has been - redirected to. No indication of where the redirection came from was - provided. - - <P> - -<DT>New behavior - <DD> - -A new batch of environment variables will be initialized for use by a -script which has been redirected to. Each new variable will have the -prefix <CODE>REDIRECT_</CODE>. <CODE>REDIRECT_</CODE> environment -variables are created from the CGI environment variables which existed -prior to the redirect, they are renamed with a <CODE>REDIRECT_</CODE> -prefix, <EM>i.e.</EM>, <CODE>HTTP_USER_AGENT</CODE> becomes -<CODE>REDIRECT_HTTP_USER_AGENT</CODE>. In addition to these new -variables, Apache will define <CODE>REDIRECT_URL</CODE> and -<CODE>REDIRECT_STATUS</CODE> to help the script trace its origin. -Both the original URL and the URL being redirected to can be logged in -the access log. - -</DL> -<P> -If the ErrorDocument specifies a local redirect to a CGI script, the script -should include a "<SAMP>Status:</SAMP>" 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: -</P> -<PRE> - : - print "Content-type: text/html\n"; - printf "Status: %s Condition Intercepted\n", $ENV{"REDIRECT_STATUS"}; - : -</PRE> -<P> -If the script is dedicated to handling a particular error condition, such as -<SAMP>404 Not Found</SAMP>, it can use the specific code and -error text instead. -</P> - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/docs/manual/developer/API.html b/docs/manual/developer/API.html deleted file mode 100644 index 496be760c9..0000000000 --- a/docs/manual/developer/API.html +++ /dev/null @@ -1,1161 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML><HEAD> -<TITLE>Apache API notes</TITLE> -</HEAD> -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> - -<blockquote><strong>Warning:</strong> -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. -</blockquote> - -<H1 ALIGN="CENTER">Apache API notes</H1> - -These are some notes on the Apache API and the data structures you -have to deal with, <EM>etc.</EM> They are not yet nearly complete, but -hopefully, they will help you get your bearings. Keep in mind that -the API is still subject to change as we gain experience with it. -(See the TODO file for what <EM>might</EM> be coming). However, -it will be easy to adapt modules to any changes that are made. -(We have more modules to adapt than you do). -<P> - -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.<P> - -Finally, here's an outline, to give you some bare idea of what's -coming up, and in what order: - -<UL> -<LI> <A HREF="#basics">Basic concepts.</A> -<MENU> - <LI> <A HREF="#HMR">Handlers, Modules, and Requests</A> - <LI> <A HREF="#moduletour">A brief tour of a module</A> -</MENU> -<LI> <A HREF="#handlers">How handlers work</A> -<MENU> - <LI> <A HREF="#req_tour">A brief tour of the <CODE>request_rec</CODE></A> - <LI> <A HREF="#req_orig">Where request_rec structures come from</A> - <LI> <A HREF="#req_return">Handling requests, declining, and returning error - codes</A> - <LI> <A HREF="#resp_handlers">Special considerations for response handlers</A> - <LI> <A HREF="#auth_handlers">Special considerations for authentication - handlers</A> - <LI> <A HREF="#log_handlers">Special considerations for logging handlers</A> -</MENU> -<LI> <A HREF="#pools">Resource allocation and resource pools</A> -<LI> <A HREF="#config">Configuration, commands and the like</A> -<MENU> - <LI> <A HREF="#per-dir">Per-directory configuration structures</A> - <LI> <A HREF="#commands">Command handling</A> - <LI> <A HREF="#servconf">Side notes --- per-server configuration, - virtual servers, <EM>etc</EM>.</A> -</MENU> -</UL> - -<H2><A NAME="basics">Basic concepts.</A></H2> - -We begin with an overview of the basic concepts behind the -API, and how they are manifested in the code. - -<H3><A NAME="HMR">Handlers, Modules, and Requests</A></H3> - -Apache breaks down request handling into a series of steps, more or -less the same way the Netscape server API does (although this API has -a few more stages than NetSite does, as hooks for stuff I thought -might be useful in the future). These are: - -<UL> - <LI> URI -> Filename translation - <LI> Auth ID checking [is the user who they say they are?] - <LI> Auth access checking [is the user authorized <EM>here</EM>?] - <LI> Access checking other than auth - <LI> Determining MIME type of the object requested - <LI> `Fixups' --- there aren't any of these yet, but the phase is - intended as a hook for possible extensions like - <CODE>SetEnv</CODE>, which don't really fit well elsewhere. - <LI> Actually sending a response back to the client. - <LI> Logging the request -</UL> - -These phases are handled by looking at each of a succession of -<EM>modules</EM>, looking to see if each of them has a handler for the -phase, and attempting invoking it if so. The handler can typically do -one of three things: - -<UL> - <LI> <EM>Handle</EM> the request, and indicate that it has done so - by returning the magic constant <CODE>OK</CODE>. - <LI> <EM>Decline</EM> to handle the request, by returning the magic - integer constant <CODE>DECLINED</CODE>. In this case, the - server behaves in all respects as if the handler simply hadn't - been there. - <LI> Signal an error, by returning one of the HTTP error codes. - This terminates normal handling of the request, although an - ErrorDocument may be invoked to try to mop up, and it will be - logged in any case. -</UL> - -Most phases are terminated by the first module that handles them; -however, for logging, `fixups', and non-access authentication -checking, all handlers always run (barring an error). Also, the -response phase is unique in that modules may declare multiple handlers -for it, via a dispatch table keyed on the MIME type of the requested -object. Modules may declare a response-phase handler which can handle -<EM>any</EM> request, by giving it the key <CODE>*/*</CODE> (<EM>i.e.</EM>, 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).<P> - -The handlers themselves are functions of one argument (a -<CODE>request_rec</CODE> structure. vide infra), which returns an -integer, as above.<P> - -<H3><A NAME="moduletour">A brief tour of a module</A></H3> - -At this point, we need to explain the structure of a module. Our -candidate will be one of the messier ones, the CGI module --- this -handles both CGI scripts and the <CODE>ScriptAlias</CODE> 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.<P> - -Let's begin with handlers. In order to handle the CGI scripts, the -module declares a response handler for them. Because of -<CODE>ScriptAlias</CODE>, it also has handlers for the name -translation phase (to recognize <CODE>ScriptAlias</CODE>ed URIs), the -type-checking phase (any <CODE>ScriptAlias</CODE>ed request is typed -as a CGI script).<P> - -The module needs to maintain some per (virtual) -server information, namely, the <CODE>ScriptAlias</CODE>es 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 -<CODE>ScriptAlias</CODE>es declared).<P> - -Finally, this module contains code to handle the -<CODE>ScriptAlias</CODE> command itself. This particular module only -declares one command, but there could be more, so modules have -<EM>command tables</EM> which declare their commands, and describe -where they are permitted, and how they are to be invoked. <P> - -A final note on the declared types of the arguments of some of these -commands: a <CODE>pool</CODE> is a pointer to a <EM>resource pool</EM> -structure; these are used by the server to keep track of the memory -which has been allocated, files opened, <EM>etc.</EM>, 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, <EM>en masse</EM>, without anyone having to write explicit code to -track them all down and dispose of them. Also, a -<CODE>cmd_parms</CODE> 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 <CODE>ScriptAlias</CODE>). - -With no further ado, the module itself: - -<PRE> -/* 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 */ -}; -</PRE> - -<H2><A NAME="handlers">How handlers work</A></H2> - -The sole argument to handlers is a <CODE>request_rec</CODE> 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 <CODE>request_rec</CODE> structure.<P> - -<H3><A NAME="req_tour">A brief tour of the <CODE>request_rec</CODE></A></H3> - -The <CODE>request_rec</CODE> 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.<P> - -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). <P> - -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 -<CODE>ap_table_get</CODE> and <CODE>ap_table_set</CODE> routines. <P> -<BLOCKQUOTE> - Note that the <SAMP>Content-type</SAMP> header value <EM>cannot</EM> be - set by module content-handlers using the <SAMP>ap_table_*()</SAMP> - routines. Rather, it is set by pointing the <SAMP>content_type</SAMP> - field in the <SAMP>request_rec</SAMP> structure to an appropriate - string. <EM>E.g.</EM>, - <PRE> - r->content_type = "text/html"; - </PRE> -</BLOCKQUOTE> -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 <CODE>.htaccess</CODE> files or -<CODE><Directory></CODE> 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 <CODE>server_rec</CODE> -data structure pointed to by the <CODE>request_rec</CODE>, which -contains per (virtual) server configuration data.<P> - -Here is an abridged declaration, giving the fields most commonly used:<P> - -<PRE> -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, <EM>etc.</EM> */ - int method_number; /* M_GET, M_POST, <EM>etc.</EM> */ - - /* 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, <EM>etc.</EM> */ - void *request_config; /* Notes on *this* request */ - -}; - -</PRE> - -<H3><A NAME="req_orig">Where request_rec structures come from</A></H3> - -Most <CODE>request_rec</CODE> structures are built by reading an HTTP -request from a client, and filling in the fields. However, there are -a few exceptions: - -<UL> - <LI> If the request is to an imagemap, a type map (<EM>i.e.</EM>, a - <CODE>*.var</CODE> 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 <EM>internal redirect</EM>, constructing a new - <CODE>request_rec</CODE> for the new URI, and processing it - almost exactly as if the client had requested the new URI - directly. <P> - - <LI> If some handler signaled an error, and an - <CODE>ErrorDocument</CODE> is in scope, the same internal - redirect machinery comes into play.<P> - - <LI> Finally, a handler occasionally needs to investigate `what - would happen if' some other request were run. For instance, - the directory indexing module needs to know what MIME type - would be assigned to a request for each directory entry, in - order to figure out what icon to use.<P> - - Such handlers can construct a <EM>sub-request</EM>, using the - functions <CODE>ap_sub_req_lookup_file</CODE>, - <CODE>ap_sub_req_lookup_uri</CODE>, and - <CODE>ap_sub_req_method_uri</CODE>; these construct a new - <CODE>request_rec</CODE> 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).<P> - - (Server-side includes work by building sub-requests and then - actually invoking the response handler for them, via the - function <CODE>ap_run_sub_req</CODE>). -</UL> - -<H3><A NAME="req_return">Handling requests, declining, and returning error - codes</A></H3> - -As discussed above, each handler, when invoked to handle a particular -<CODE>request_rec</CODE>, has to return an <CODE>int</CODE> to -indicate what happened. That can either be - -<UL> - <LI> OK --- the request was handled successfully. This may or may - not terminate the phase. - <LI> DECLINED --- no erroneous condition exists, but the module - declines to handle the phase; the server tries to find another. - <LI> an HTTP error code, which aborts handling of the request. -</UL> - -Note that if the error code returned is <CODE>REDIRECT</CODE>, then -the module should put a <CODE>Location</CODE> in the request's -<CODE>headers_out</CODE>, to indicate where the client should be -redirected <EM>to</EM>. <P> - -<H3><A NAME="resp_handlers">Special considerations for response - handlers</A></H3> - -Handlers for most phases do their work by simply setting a few fields -in the <CODE>request_rec</CODE> 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. <P> - -They should begin by sending an HTTP response header, using the -function <CODE>ap_send_http_header</CODE>. (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 <CODE>header_only</CODE>, that's all they should -do; they should return after that, without attempting any further -output. <P> - -Otherwise, they should produce a request body which responds to the -client as appropriate. The primitives for this are <CODE>ap_rputc</CODE> -and <CODE>ap_rprintf</CODE>, for internally generated output, and -<CODE>ap_send_fd</CODE>, to copy the contents of some <CODE>FILE *</CODE> -straight to the client. <P> - -At this point, you should more or less understand the following piece -of code, which is the handler which handles <CODE>GET</CODE> requests -which have no more specific handler; it also shows how conditional -<CODE>GET</CODE>s can be handled, if it's desirable to do so in a -particular response handler --- <CODE>ap_set_last_modified</CODE> checks -against the <CODE>If-modified-since</CODE> 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 -<CODE>ap_set_content_length</CODE>, but it returns an error code for -symmetry.<P> - -<PRE> -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; -} -</PRE> - -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 -<CODE>ap_internal_redirect</CODE>, which is how the internal redirection -machinery discussed above is invoked. A response handler which has -internally redirected should always return <CODE>OK</CODE>. <P> - -(Invoking <CODE>ap_internal_redirect</CODE> from handlers which are -<EM>not</EM> response handlers will lead to serious confusion). - -<H3><A NAME="auth_handlers">Special considerations for authentication - handlers</A></H3> - -Stuff that should be discussed here in detail: - -<UL> - <LI> Authentication-phase handlers not invoked unless auth is - configured for the directory. - <LI> Common auth configuration stored in the core per-dir - configuration; it has accessors <CODE>ap_auth_type</CODE>, - <CODE>ap_auth_name</CODE>, and <CODE>ap_requires</CODE>. - <LI> Common routines, to handle the protocol end of things, at least - for HTTP basic authentication (<CODE>ap_get_basic_auth_pw</CODE>, - which sets the <CODE>connection->user</CODE> structure field - automatically, and <CODE>ap_note_basic_auth_failure</CODE>, which - arranges for the proper <CODE>WWW-Authenticate:</CODE> header - to be sent back). -</UL> - -<H3><A NAME="log_handlers">Special considerations for logging handlers</A></H3> - -When a request has internally redirected, there is the question of -what to log. Apache handles this by bundling the entire chain of -redirects into a list of <CODE>request_rec</CODE> structures which are -threaded through the <CODE>r->prev</CODE> and <CODE>r->next</CODE> -pointers. The <CODE>request_rec</CODE> 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). - -<H2><A NAME="pools">Resource allocation and resource pools</A></H2> -<P> -One of the problems of writing and designing a server-pool server is -that of preventing leakage, that is, allocating resources (memory, -open files, <EM>etc.</EM>), 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 <EM>automatically</EM> released when the server is done with -them. -</P> -<P> -The way this works is as follows: the memory which is allocated, file -opened, <EM>etc.</EM>, to deal with a particular request are tied to a -<EM>resource pool</EM> which is allocated for the request. The pool -is a data structure which itself tracks the resources in question. -</P> -<P> -When the request has been processed, the pool is <EM>cleared</EM>. 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. -</P> -<P> -Server restarts, and allocation of memory and resources for per-server -configuration, are handled in a similar way. There is a -<EM>configuration pool</EM>, 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. -</P> -<P> -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 <CODE><A HREF="#pool-files">ap_pfopen</A></CODE>, which also -arranges for the underlying file descriptor to be closed before any -child processes, such as for CGI scripts, are <CODE>exec</CODE>ed), 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, <CODE>ap_palloc</CODE> is generally faster than -<CODE>malloc</CODE>. -</P> -<P> -We begin here by describing how memory is allocated to pools, and then -discuss how other resources are tracked by the resource pool -machinery. -</P> -<H3>Allocation of memory in pools</H3> -<P> -Memory is allocated to pools by calling the function -<CODE>ap_palloc</CODE>, which takes two arguments, one being a pointer to -a resource pool structure, and the other being the amount of memory to -allocate (in <CODE>char</CODE>s). Within handlers for handling -requests, the most common way of getting a resource pool structure is -by looking at the <CODE>pool</CODE> slot of the relevant -<CODE>request_rec</CODE>; hence the repeated appearance of the -following idiom in module code: -</P> -<PRE> -int my_handler(request_rec *r) -{ - struct my_structure *foo; - ... - - foo = (foo *)ap_palloc (r->pool, sizeof(my_structure)); -} -</PRE> -<P> -Note that <EM>there is no <CODE>ap_pfree</CODE></EM> --- -<CODE>ap_palloc</CODE>ed memory is freed only when the associated -resource pool is cleared. This means that <CODE>ap_palloc</CODE> does not -have to do as much accounting as <CODE>malloc()</CODE>; all it does in -the typical case is to round up the size, bump a pointer, and do a -range check. -</P> -<P> -(It also raises the possibility that heavy use of <CODE>ap_palloc</CODE> -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 <CODE>malloc</CODE>, and try to be sure that all of the memory -gets explicitly <CODE>free</CODE>d, 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). -</P> -<H3>Allocating initialized memory</H3> -<P> -There are functions which allocate initialized memory, and are -frequently useful. The function <CODE>ap_pcalloc</CODE> has the same -interface as <CODE>ap_palloc</CODE>, but clears out the memory it -allocates before it returns it. The function <CODE>ap_pstrdup</CODE> -takes a resource pool and a <CODE>char *</CODE> as arguments, and -allocates memory for a copy of the string the pointer points to, -returning a pointer to the copy. Finally <CODE>ap_pstrcat</CODE> is a -varargs-style function, which takes a pointer to a resource pool, and -at least two <CODE>char *</CODE> arguments, the last of which must be -<CODE>NULL</CODE>. It allocates enough memory to fit copies of each -of the strings, as a unit; for instance: -</P> -<PRE> - ap_pstrcat (r->pool, "foo", "/", "bar", NULL); -</PRE> -<P> -returns a pointer to 8 bytes worth of memory, initialized to -<CODE>"foo/bar"</CODE>. -</P> -<H3><A NAME="pools-used">Commonly-used pools in the Apache Web server</A></H3> -<P> -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: -</P> -<DL COMPACT> - <DT>permanent_pool - </DT> - <DD> - <UL> - <LI>never passed to anything else, this is the ancestor of all pools - </LI> - </UL> - </DD> - <DT>pconf - </DT> - <DD> - <UL> - <LI>subpool of permanent_pool - </LI> - <LI>created at the beginning of a config "cycle"; exists until the - server is terminated or restarts; passed to all config-time - routines, either via cmd->pool, or as the "pool *p" argument on - those which don't take pools - </LI> - <LI>passed to the module init() functions - </LI> - </UL> - </DD> - <DT>ptemp - </DT> - <DD> - <UL> - <LI>sorry I lie, this pool isn't called this currently in 1.3, I - renamed it this in my pthreads development. I'm referring to - the use of ptrans in the parent... contrast this with the later - definition of ptrans in the child. - </LI> - <LI>subpool of permanent_pool - </LI> - <LI>created at the beginning of a config "cycle"; exists until the - end of config parsing; passed to config-time routines <EM>via</EM> - cmd->temp_pool. Somewhat of a "bastard child" because it isn't - available everywhere. Used for temporary scratch space which - may be needed by some config routines but which is deleted at - the end of config. - </LI> - </UL> - </DD> - <DT>pchild - </DT> - <DD> - <UL> - <LI>subpool of permanent_pool - </LI> - <LI>created when a child is spawned (or a thread is created); lives - until that child (thread) is destroyed - </LI> - <LI>passed to the module child_init functions - </LI> - <LI>destruction happens right after the child_exit functions are - called... (which may explain why I think child_exit is redundant - and unneeded) - </LI> - </UL> - </DD> - <DT>ptrans - <DT> - <DD> - <UL> - <LI>should be a subpool of pchild, but currently is a subpool of - permanent_pool, see above - </LI> - <LI>cleared by the child before going into the accept() loop to receive - a connection - </LI> - <LI>used as connection->pool - </LI> - </UL> - </DD> - <DT>r->pool - </DT> - <DD> - <UL> - <LI>for the main request this is a subpool of connection->pool; for - subrequests it is a subpool of the parent request's pool. - </LI> - <LI>exists until the end of the request (<EM>i.e.</EM>, - ap_destroy_sub_req, or - in child_main after process_request has finished) - </LI> - <LI>note that r itself is allocated from r->pool; <EM>i.e.</EM>, - r->pool is - first created and then r is the first thing palloc()d from it - </LI> - </UL> - </DD> -</DL> -<P> -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. -</P> -<P> -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. -</P> -<P> -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 -- <EM>i.e.</EM>, after the output has been sent to -the client and logging has happened. -</P> -<H3><A NAME="pool-files">Tracking open files, etc.</A></H3> -<P> -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 <CODE>ap_pfopen</CODE>, which -takes a resource pool and two strings as arguments; the strings are -the same as the typical arguments to <CODE>fopen</CODE>, <EM>e.g.</EM>, -</P> -<PRE> - ... - FILE *f = ap_pfopen (r->pool, r->filename, "r"); - - if (f == NULL) { ... } else { ... } -</PRE> -<P> -There is also a <CODE>ap_popenf</CODE> routine, which parallels the -lower-level <CODE>open</CODE> system call. Both of these routines -arrange for the file to be closed when the resource pool in question -is cleared. -</P> -<P> -Unlike the case for memory, there <EM>are</EM> functions to close -files allocated with <CODE>ap_pfopen</CODE>, and <CODE>ap_popenf</CODE>, -namely <CODE>ap_pfclose</CODE> and <CODE>ap_pclosef</CODE>. (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 <CODE>ap_pfopen</CODE> and -<CODE>ap_popenf</CODE>, since to do otherwise could cause fatal errors on -systems such as Linux, which react badly if the same -<CODE>FILE*</CODE> is closed more than once. -</P> -<P> -(Using the <CODE>close</CODE> 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). -</P> -<H3>Other sorts of resources --- cleanup functions</H3> -<BLOCKQUOTE> -More text goes here. Describe the the cleanup primitives in terms of -which the file stuff is implemented; also, <CODE>spawn_process</CODE>. -</BLOCKQUOTE> -<P> -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. <EM>i.e.</EM>, clear_pool(a) doesn't -delete a, it just frees up all the resources and you can start using it -again immediately. -</P> -<H3>Fine control --- creating and dealing with sub-pools, with a note -on sub-requests</H3> - -On rare occasions, too-free use of <CODE>ap_palloc()</CODE> and the -associated primitives may result in undesirably profligate resource -allocation. You can deal with such a case by creating a -<EM>sub-pool</EM>, 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 <EM>is</EM> 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 -<EM>very</EM> large directories. Unnecessary use of the primitives -discussed here can hair up your code quite a bit, with very little -gain). <P> - -The primitive for creating a sub-pool is <CODE>ap_make_sub_pool</CODE>, -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 -<CODE>ap_clear_pool</CODE> and <CODE>ap_destroy_pool</CODE>, respectively. -(The difference is that <CODE>ap_clear_pool</CODE> frees resources -associated with the pool, while <CODE>ap_destroy_pool</CODE> 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). <P> - -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 <CODE>ap_sub_req_...</CODE> functions) -is <CODE>ap_destroy_sub_req</CODE>, 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 -<CODE>request_rec</CODE> structure). <P> - -(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 -<CODE>ap_destroy_...</CODE> functions). - -<H2><A NAME="config">Configuration, commands and the like</A></H2> - -One of the design goals for this server was to maintain external -compatibility with the NCSA 1.3 server --- that is, to read the same -configuration files, to process all the directives therein correctly, -and in general to be a drop-in replacement for NCSA. On the other -hand, another design goal was to move as much of the server's -functionality into modules which have as little as possible to do with -the monolithic server core. The only way to reconcile these goals is -to move the handling of most commands from the central server into the -modules. <P> - -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 <CODE>AddType</CODE> and -<CODE>DefaultType</CODE> directives, and so forth. In general, the -governing philosophy is that anything which <EM>can</EM> be made -configurable by directory should be; per-server information is -generally used in the standard set of modules for information like -<CODE>Alias</CODE>es and <CODE>Redirect</CODE>s which come into play -before the request is tied to a particular place in the underlying -file system. <P> - -Another requirement for emulating the NCSA server is being able to -handle the per-directory configuration files, generally called -<CODE>.htaccess</CODE> 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 <CODE>.htaccess</CODE> files which might be -present. The information which is read in then has to be -<EM>merged</EM> with the applicable information from the server's own -config files (either from the <CODE><Directory></CODE> sections -in <CODE>access.conf</CODE>, or from defaults in -<CODE>srm.conf</CODE>, which actually behaves for most purposes almost -exactly like <CODE><Directory /></CODE>).<P> - -Finally, after having served a request which involved reading -<CODE>.htaccess</CODE> 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. <P> - -<H3><A NAME="per-dir">Per-directory configuration structures</A></H3> - -Let's look out how all of this plays out in <CODE>mod_mime.c</CODE>, -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 -<CODE>AddType</CODE> and <CODE>AddEncoding</CODE> commands. These -commands can appear in <CODE>.htaccess</CODE> files, so they must be -handled in the module's private per-directory data, which in fact, -consists of two separate <CODE>table</CODE>s for MIME types and -encoding information, and is declared as follows: - -<PRE> -typedef struct { - table *forced_types; /* Additional AddTyped stuff */ - table *encoding_types; /* Added with AddEncoding... */ -} mime_dir_config; -</PRE> - -When the server is reading a configuration file, or -<CODE><Directory></CODE> section, which includes one of the MIME -module's commands, it needs to create a <CODE>mime_dir_config</CODE> -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 <CODE>NULL</CODE> for -<CODE>srm.conf</CODE>), and a pointer to a resource pool in which the -allocation should happen. <P> - -(If we are reading a <CODE>.htaccess</CODE> 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). <P> - -For the MIME module, the per-dir config creation function just -<CODE>ap_palloc</CODE>s the structure above, and a creates a couple of -<CODE>table</CODE>s to fill it. That looks like this: - -<PRE> -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; -} -</PRE> - -Now, suppose we've just read in a <CODE>.htaccess</CODE> file. We -already have the per-directory configuration structure for the next -directory up in the hierarchy. If the <CODE>.htaccess</CODE> file we -just read in didn't have any <CODE>AddType</CODE> or -<CODE>AddEncoding</CODE> 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. <P> - -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: - -<PRE> -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; -} -</PRE> - -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 (<EM>e.g.</EM>, for the -includes module, whose per-directory configuration information -consists solely of the state of the <CODE>XBITHACK</CODE>), and for -those modules, you can just not declare one, and leave the -corresponding structure slot in the module itself <CODE>NULL</CODE>.<P> - -<H3><A NAME="commands">Command handling</A></H3> - -Now that we have these structures, we need to be able to figure out -how to fill them. That involves processing the actual -<CODE>AddType</CODE> and <CODE>AddEncoding</CODE> commands. To find -commands, the server looks in the module's <CODE>command table</CODE>. -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 <CODE>AddType</CODE> command handler, which -looks like this (the <CODE>AddEncoding</CODE> command looks basically -the same, and won't be shown here): - -<PRE> -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; -} -</PRE> - -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 <CODE>cmd_parms</CODE> 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.<P> - -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 -<CODE>NULL</CODE>; this causes an error to be printed out on the -server's <CODE>stderr</CODE>, followed by a quick exit, if it is in -the main config files; for a <CODE>.htaccess</CODE> 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). <P> - -The MIME module's command table has entries for these commands, which -look like this: - -<PRE> -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 (<EM>e.g.</EM>, gzip), followed by a file extension" }, -{ NULL } -}; -</PRE> - -The entries in these tables are: - -<UL> - <LI> The name of the command - <LI> The function which handles it - <LI> a <CODE>(void *)</CODE> pointer, which is passed in the - <CODE>cmd_parms</CODE> structure to the command handler --- - this is useful in case many similar commands are handled by the - same function. - <LI> A bit mask indicating where the command may appear. There are - mask bits corresponding to each <CODE>AllowOverride</CODE> - option, and an additional mask bit, <CODE>RSRC_CONF</CODE>, - indicating that the command may appear in the server's own - config files, but <EM>not</EM> in any <CODE>.htaccess</CODE> - file. - <LI> A flag indicating how many arguments the command handler wants - pre-parsed, and how they should be passed in. - <CODE>TAKE2</CODE> indicates two pre-parsed arguments. Other - options are <CODE>TAKE1</CODE>, which indicates one pre-parsed - argument, <CODE>FLAG</CODE>, which indicates that the argument - should be <CODE>On</CODE> or <CODE>Off</CODE>, and is passed in - as a boolean flag, <CODE>RAW_ARGS</CODE>, which causes the - server to give the command the raw, unparsed arguments - (everything but the command name itself). There is also - <CODE>ITERATE</CODE>, which means that the handler looks the - same as <CODE>TAKE1</CODE>, but that if multiple arguments are - present, it should be called multiple times, and finally - <CODE>ITERATE2</CODE>, which indicates that the command handler - looks like a <CODE>TAKE2</CODE>, but if more arguments are - present, then it should be called multiple times, holding the - first argument constant. - <LI> Finally, we have a string which describes the arguments that - should be present. If the arguments in the actual config file - are not as required, this string will be used to help give a - more specific error message. (You can safely leave this - <CODE>NULL</CODE>). -</UL> - -Finally, having set this all up, we have to use it. This is -ultimately done in the module's handlers, specifically for its -file-typing handler, which looks more or less like this; note that the -per-directory configuration structure is extracted from the -<CODE>request_rec</CODE>'s per-directory configuration vector by using -the <CODE>ap_get_module_config</CODE> function. - -<PRE> -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; -} - -</PRE> - -<H3><A NAME="servconf">Side notes --- per-server configuration, virtual - servers, <EM>etc</EM>.</A></H3> - -The basic ideas behind per-server module configuration are basically -the same as those for per-directory configuration; there is a creation -function and a merge function, the latter being invoked where a -virtual server has partially overridden the base server configuration, -and a combined structure must be computed. (As with per-directory -configuration, the default if no merge function is specified, and a -module is configured in some virtual server, is that the base -configuration is simply ignored). <P> - -The only substantial difference is that when a command needs to -configure the per-server private module data, it needs to go to the -<CODE>cmd_parms</CODE> 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): - -<PRE> -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; -} -</PRE> -<!--#include virtual="footer.html" --> -</BODY></HTML> diff --git a/docs/manual/developer/modules.html.en b/docs/manual/developer/modules.html.en deleted file mode 100644 index d2d898f88f..0000000000 --- a/docs/manual/developer/modules.html.en +++ /dev/null @@ -1,239 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Converting Modules from Apache 1.3 to Apache 2.0</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> - -<!--#include virtual="header.html" --> - -<H1 ALIGN="CENTER">From Apache 1.3 to Apache 2.0<br>Modules</H1> - -<p> -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. -</p> -<hr> -<h2>The easier changes... -</h2> - -<h3>Cleanup Routines</h3> -<p> -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. -</p> - -<h3>Initialisation Routines</h3> - -<p> -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 -</p> -<ul style="list-style:none"> -<li>apr_pool_t *p,</li> -<li>apr_pool_t *plog,</li> -<li>apr_pool_t *ptemp,</li> -<li>server_rec *s</li> -</ul> - -<h3>Data Types</h3> -<p> -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. -<ul style="list-style:none"> -<li>pool becomes apr_pool_t</li> -<li>table becomes apr_table_t</li> -</ul> -<hr> - -<h2> -The <em>messier</em> changes... -</h2> -<h3>Register Hooks</h3> -<p> -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. -</p> -<p> -This is the code that was added to mod_mmap_static: -</p> -<pre> -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); -}; -</pre> -<p> -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? -</p> -<p><strong> -ap_hook_[phase_name](function_name, predecessors, successors, position); -</strong></p> -<p> -There are 3 hook positions defined... -</p> -<ul style="list-style:none"> -<li>HOOK_FIRST</li> -<li>HOOK_MIDDLE</li> -<li>HOOK_LAST</li> -</ul> -<p> -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). -</p> -<p> -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. -</p> -<h3>Module Definition</h3> - -<p> -There are now a lot fewer stages to worry about when creating your module definition. The old defintion looked like -</p> -<pre> -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 */ -}; -</pre> -<p> -The new structure is a great deal simpler... -</p> -<pre> -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 */ - }; -</pre> -<p> -Some of these read directly across, some don't. I'll try to summarise what should be done below. -</p> -<p> -The stages that read directly across : -</p> -<ul style="list-style:none"> -<li> -/* dir config creater */ ==> /* create per-directory config structures */ -</li> -<li> -/* server config */ ==> /* create per-server config structures */ -</li> -<li> -/* dir merger */ ==> /* merge per-directory config structures */ -</li> -<li> -/* merge server config */ ==> /* merge per-server config structures */ -</li> -<li> -/* command table */ ==> /* command apr_table_t */ -</li> -<li> -/* handlers */ ==> /* handlers */ -</li> -</ul> -<P> -The remainder of the old functions should be registered as hooks. There are the following hook stages defined so far... -</P> - -<ul style="list-style:none"> -<li> -ap_hook_post_config <em>(this is where the old _init routines get registered)</em> -</li> -<li> -ap_hook_http_method <em>(retrieve the http method from a request. (legacy))</em> -</li> -<li> -ap_hook_open_logs <em>(open any specified logs)</em> -</li> -<li> -ap_hook_auth_checker <em>(check if the resource requires authorization)</em> -</li> -<li> -ap_hook_access_checker <em>(check for module-specific restrictions)</em> -</li> -<li> -ap_hook_check_user_id <em>(check the user-id and password)</em> -</li> -<li> -ap_hook_default_port <em>(retrieve the default port for the server)</em> -</li> -<li> -ap_hook_pre_connection <em>(do any setup required just before processing, but after accepting)</em> -</li> -<li> -ap_hook_process_connection <em>(run the correct protocol)</em> -</li> -<li> -ap_hook_child_init <em>(call as soon as the child is started)</em> -</li> -<li> -ap_hook_create_request <em>(??)</em> -</li> -<li> -ap_hook_fixups <em>(last chance to modify things before generating content)</em> -</li> -<li> -ap_hook_handler <em>(generate the content)</em> -</li> -<li> -ap_hook_header_parser <em>(let's modules look at the headers, not used by most modules, because they use post_read_request for this.)</em> -</li> -<li> -ap_hook_insert_filter <em>(to insert filters into the filter chain)</em> -</li> -<li> -ap_hook_log_transaction <em>(log information about the request)</em> -</li> -<li> -ap_hook_optional_fn_retrieve <em>(retrieve any functions registered as optional)</em> -</li> -<li> -ap_hook_post_read_request <em>(called after reading the request, before any other phase)</em> -</li> -<li> -ap_hook_quick_handler <em>(??)</em> -</li> -<li> -ap_hook_translate_name <em>(translate the URI into a filename)</em> -</li> -<li> -ap_hook_type_checker <em>(determine and/or set the doc type)</em> - - -<!--#include virtual="footer.html" --> - -</body> -</html> - - - - - diff --git a/docs/manual/dso.html.en b/docs/manual/dso.html.en deleted file mode 100644 index bff578e444..0000000000 --- a/docs/manual/dso.html.en +++ /dev/null @@ -1,394 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML><HEAD> -<TITLE>Apache 1.3 Dynamic Shared Object (DSO) support</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<BLOCKQUOTE> -<!--#include virtual="header.html" --> - -<DIV ALIGN=CENTER> - -<H1> -Apache 1.3<BR> -Dynamic Shared Object (DSO)<BR> -Support -</H1> - -<ADDRESS>Originally written by<BR> -Ralf S. Engelschall <rse@apache.org>, April 1998</ADDRESS> - -</DIV> - -<H3>Background</H3> - -<P>On modern Unix derivatives there exists a nifty mechanism usually called -dynamic linking/loading of <EM>Dynamic Shared Objects</EM> (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. - -<P>This loading can usually be done in two ways: Automatically by a system -program called <CODE>ld.so</CODE> when an executable program is started or -manually from within the executing program via a programmatic system interface -to the Unix loader through the system calls <CODE>dlopen()/dlsym()</CODE>. - -<P>In the first way the DSO's are usually called <EM>shared libraries</EM> or -<EM>DSO libraries</EM> and named <CODE>libfoo.so</CODE> or -<CODE>libfoo.so.1.2</CODE>. They reside in a system directory (usually -<CODE>/usr/lib</CODE>) and the link to the executable program is established -at build-time by specifying <CODE>-lfoo</CODE> to the linker command. This -hard-codes library references into the executable program file so that at -start-time the Unix loader is able to locate <CODE>libfoo.so</CODE> in -<CODE>/usr/lib</CODE>, in paths hard-coded via linker-options like -<CODE>-R</CODE> or in paths configured via the environment variable -<CODE>LD_LIBRARY_PATH</CODE>. It then resolves any (yet unresolved) symbols in -the executable program which are available in the DSO. - -<P>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 <CODE>ld.so</CODE> is 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 like <CODE>libc.so</CODE>, saving disk space for every program. - -<P>In the second way the DSO's are usually called <EM>shared objects</EM> or -<EM>DSO files</EM> and can be named with an arbitrary extension (although the -canonical name is <CODE>foo.so</CODE>). 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 -<CODE>dlopen()</CODE>. 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 ubiquitous <CODE>libc.so</CODE>). 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. - -<P>Finally, to take advantage of the DSO's API the executable program has to -resolve particular symbols from the DSO via <CODE>dlsym()</CODE> for later use -inside dispatch tables <EM>etc.</EM> 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. - -<P>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. - -<H3>Practical Usage</H3> - -<P>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. - -<P>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, <EM>etc.</EM> 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. - -<P>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. - -<H3>Implementation</H3> - -<P>The DSO support for loading individual Apache modules is based on a module -named <A HREF="mod/mod_so.html"><CODE>mod_so.c</CODE></A> which has to be -statically compiled into the Apache core. It is the only module besides -<CODE>http_core.c</CODE> which 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 -<CODE>configure</CODE>'s <CODE>--enable-shared</CODE> option (see top-level -<CODE>INSTALL</CODE> file) or by changing the <CODE>AddModule</CODE> command -in your <CODE>src/Configuration</CODE> into a <CODE>SharedModule</CODE> -command (see <CODE>src/INSTALL</CODE> file). After a module is compiled into -a DSO named <CODE>mod_foo.so</CODE> you can use <A -HREF="mod/mod_so.html"><CODE>mod_so</CODE></A>'s <A -HREF="mod/mod_so.html#loadmodule"><CODE>LoadModule</CODE></A> command in your -<CODE>httpd.conf</CODE> file to load this module at server startup or restart. - -<P>To simplify this creation of DSO files for Apache modules -(especially for third-party modules) a new support program named <a -href="programs/apxs.html">apxs</a> (<EM>APache eXtenSion</EM>) is -available. It can be used to build DSO based modules <EM>outside -of</EM> the Apache source tree. The idea is simple: When installing -Apache the <CODE>configure</CODE>'s <CODE>make install</CODE> -procedure installs the Apache C header files and puts the -platform-dependent compiler and linker flags for building DSO files -into the <CODE>apxs</CODE> program. This way the user can use -<CODE>apxs</CODE> to 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. - -<P>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 -<CODE>SHARED_CORE</CODE> has to be enabled via <CODE>configure</CODE>'s -<CODE>--enable-rule=SHARED_CORE</CODE> option (see top-level -<CODE>INSTALL</CODE> file) or by changing the <CODE>Rule</CODE> command in -your <CODE>Configuration</CODE> file to <CODE>Rule SHARED_CORE=yes</CODE> (see -<CODE>src/INSTALL</CODE> file). The Apache core code is then placed into a DSO -library named <CODE>libhttpd.so</CODE>. Because one cannot link a DSO against -static libraries on all platforms, an additional executable program named -<CODE>libhttpd.ep</CODE> is created which both binds this static code and -provides a stub for the <CODE>main()</CODE> function. Finally the -<CODE>httpd</CODE> executable program itself is replaced by a bootstrapping -code which automatically makes sure the Unix loader is able to load and start -<CODE>libhttpd.ep</CODE> by providing the <CODE>LD_LIBRARY_PATH</CODE> to -<CODE>libhttpd.so</CODE>. - -<H3>Supported Platforms</H3> - -<P>Apache's <CODE>src/Configure</CODE> script 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: - -<P> -<UL> -<LI>Out-of-the-box supported platforms:<BR> -(actually tested versions in parenthesis) - -<PRE> -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) -</PRE> - -<P> -<LI> Explicitly unsupported platforms: - -<PRE> -o Ultrix (no dlopen-style interface under this platform) -</PRE> - -</UL> - -<H3>Usage Summary</H3> - -<P>To give you an overview of the DSO features of Apache 1.3, here is a short -and concise summary: - -<OL> - -<LI>Placing the Apache core code (all the stuff which usually forms the -<CODE>httpd</CODE> binary) into a DSO <CODE>libhttpd.so</CODE>, an executable -program <CODE>libhttpd.ep</CODE> and a bootstrapping executable program -<CODE>httpd</CODE> (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): - -<P> -<UL> -<LI>Build and install via <CODE>configure</CODE> (preferred): -<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD> -<PRE> -$ ./configure --prefix=/path/to/install - --enable-rule=SHARED_CORE ... -$ make install -</PRE> -</TD></TR></TABLE> - -<LI>Build and install manually: -<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD> -<PRE> -- 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/ -</PRE> -</TD></TR></TABLE> -</UL> - -<LI>Build and install a <EM>distributed</EM> Apache module, say -<CODE>mod_foo.c</CODE>, into its own DSO <CODE>mod_foo.so</CODE>: - -<P> -<UL> -<LI>Build and install via <CODE>configure</CODE> (preferred): -<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD> -<PRE> -$ ./configure --prefix=/path/to/install - --enable-shared=foo -$ make install -</PRE> -</TD></TR></TABLE> - -<LI>Build and install manually: -<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD> -<PRE> -- 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 -</PRE> -</TD></TR></TABLE> -</UL> - -<LI>Build and install a <EM>third-party</EM> Apache module, say -<CODE>mod_foo.c</CODE>, into its own DSO <CODE>mod_foo.so</CODE> - -<P> -<UL> -<LI>Build and install via <CODE>configure</CODE> (preferred): -<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD> -<PRE> -$ ./configure --add-module=/path/to/3rdparty/mod_foo.c - --enable-shared=foo -$ make install -</PRE> -</TD></TR></TABLE> - -<LI>Build and install manually: -<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD> -<PRE> -$ 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 -</PRE> -</TD></TR></TABLE> -</UL> - -<P> -<LI>Build and install a <EM>third-party</EM> Apache module, say -<CODE>mod_foo.c</CODE>, into its own DSO <CODE>mod_foo.so</CODE> <EM>outside -of</EM> the Apache source tree: - -<P> -<UL> -<LI>Build and install via <a href="programs/apxs.html">apxs</a>: -<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD> -<PRE> -$ cd /path/to/3rdparty -$ apxs -c mod_foo.c -$ apxs -i -a -n foo mod_foo.so -</PRE> -</TD></TR></TABLE> -</UL> - -</OL> - -<H3>Advantages & Disadvantages</H3> - -<P>The above DSO based features of Apache 1.3 have the following advantages: - -<UL> -<LI> The server package is more flexible at run-time because the actual server - process can be assembled at run-time via <A - HREF="mod/mod_so.html#loadmodule"><CODE>LoadModule</CODE></A> - <CODE>httpd.conf</CODE> configuration commands instead of - <CODE>Configuration</CODE> <CODE>AddModule</CODE> commands 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], <EM>etc.</EM>) with only one Apache installation. -<P> -<LI> 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, <EM>etc.</EM> -<P> -<LI> Easier Apache module prototyping because with the DSO/<CODE>apxs</CODE> - pair you can both work outside the Apache source tree and only need an - <CODE>apxs -i</CODE> command followed by an <CODE>apachectl - restart</CODE> to bring a new version of your currently developed module - into the running Apache server. -</UL> - -<P>DSO has the following disadvantages: - -<UL> -<LI> 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. -<P> -<LI> The server is approximately 20% slower at startup time because of the - symbol resolving overhead the Unix loader now has to do. -<P> -<LI> 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. -<P> -<LI> Because DSO modules cannot be linked against other DSO-based libraries - (<CODE>ld -lfoo</CODE>) 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 (<CODE>libc</CODE>) - and all other dynamic or static libraries used by the Apache core, or - from static library archives (<CODE>libfoo.a</CODE>) 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 via <CODE>dlopen()</CODE> or enabling the - <CODE>SHARED_CHAIN</CODE> rule while building Apache when your platform - supports linking DSO files against DSO libraries. -<P> -<LI> 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 <CODE>SHARED_CORE</CODE> feature because this - way the global symbols are forced to be exported. As a consequence the - Apache <CODE>src/Configure</CODE> script automatically enforces - <CODE>SHARED_CORE</CODE> on these platforms when DSO features are used in - the <CODE>Configuration</CODE> file or on the configure command line. -</UL> - -<!--#include virtual="footer.html" --> -</BLOCKQUOTE> -</BODY> -</HTML> diff --git a/docs/manual/filter.html.en b/docs/manual/filter.html.en deleted file mode 100644 index c62b4315b0..0000000000 --- a/docs/manual/filter.html.en +++ /dev/null @@ -1,58 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Filters - Apache HTTPD</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<H1 ALIGN="CENTER">Filters</H1> - -<table border="1"> -<tr><td valign="top"> -<strong>Related Modules</strong><br><br> - -<a href="mod/mod_ext_filter.html">mod_ext_filter</a><br> -<A HREF="mod/mod_include.html">mod_include</A><br> -</td> -<td valign="top"> -<strong>Related Directives</strong><br><br> - -<a href="mod/mod_ext_filter.html#extfilterdefine">ExtFilterDefine</a></br> -<a href="mod/mod_ext_filter.html#extfilteroptions">ExtFilterOptions</a><br> -<a href="mod/core.html#setinputfilter">SetInputFilter</a><br> -<a href="mod/core.html#setoutputfilter">SetOutputFilter</a><br> -</td> -</tr></table> - -<p>A <em>filter</em> 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 <em>input filters</em> while data sent by the -server to the client is processed by <em>output filters</em>. -Multiple filters can be applied to the data, and the order -of the filters can be explicitly specified.</p> - -<p>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 <code>SetInputFilter</code> and <code>SetOutputFilter</code> -directives.</p> - -<p>The only configurable filter currently included with the Apache -distribution is the <code>INCLUDES</code> filter which is provided by -<a href="mod/mod_include.html">mod_include</a> to process output for -Server Side Includes. There is also an experimental module called <a -href="mod/mod_ext_filter.html">mod_ext_filter</a> which allows for -external programs to be defined as filters.</p> - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/docs/manual/install.html.en b/docs/manual/install.html.en deleted file mode 100644 index 8d8f4178af..0000000000 --- a/docs/manual/install.html.en +++ /dev/null @@ -1,532 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Compiling and Installing Apache</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> - -<H1 ALIGN="CENTER">Compiling and Installing</H1> - - -<p>This document covers compilation and installation of Apache on Unix -and Unix-like systems only. For compiling and installation on Windows, -see <A HREF="platform/windows.html">Using Apache with Microsoft -Windows</A>. For other platforms, see the <a -href="platform/">platform</a> documentation.</p> - -<p>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.</p> - -<ul> -<li><a href="#overview">Overview for the impatient</a></li> -<li><a href="#requirements">Requirements</a></li> -<li><a href="#download">Download</a></li> -<li><a href="#extract">Extract</a></li> -<li><a href="#configure">Configuring the source tree</a> - <ul> - <li><a href="#environment">Environment Variables</a></li> - <li><a href="#output">autoconf Output Options</a></li> - <li><a href="#pathnames">Pathnames</a></li> - <li><a href="#modules">Modules</a></li> - <li><a href="#suexec">Suexec</a></li> - </ul></li> -<li><a href="#compile">Build</a></li> -<li><a href="#install">Install</a></li> -<li><a href="#customize">Customize</a></li> -<li><a href="#test">Test</a></li> -</ul> - -<hr> - -<h3><a name="overview">Overview for the impatient</a></h3> - -<table> -<tr><td><a href="#download">Download</a></td> -<td><code>$ lynx http://www.apache.org/dist/httpd/httpd-2_0_<em>NN</em>.tar.gz -</code></td></tr> - -<tr><td><a href="#extract">Extract</a></td> -<td><code>$ gzip -d httpd-2_0_<em>NN</em>.tar.gz<br> -$ tar xvf httpd-2_0_<em>NN</em>.tar -</code></td></tr> - -<tr><td><a href="#configure">Configure</a></td> -<td><code>$ ./configure --prefix=<em>PREFIX</em> -</code></td></tr> - -<tr><td><a href="#compile">Compile</a></td> -<td><code>$ make -</code></td></tr> - -<tr><td><a href="#install">Install</a></td> -<td><code>$ make install -</code></td></tr> - -<tr><td><a href="#customize">Customize</a></td> -<td><code>$ vi <em>PREFIX</em>/conf/httpd.conf -</code></td></tr> - -<tr><td><a href="#test">Test</a></td> -<td><code>$ <em>PREFIX</em>/bin/apachectl start -</code></td></tr> - -</table> - -<p><em>NN</em> must be replaced with the current minor version number, -and <em>PREFIX</em> must be replaced with the filesystem path under -which the server should be installed. If <em>PREFIX</em> is not -specified, it defaults to <code>/usr/local/apache2</code>.</p> - -<p>Each section of the compilation and installation process is -described in more detail below, beginning with the requirements -for compiling and installing Apache HTTPD.</p> - -<h3><a name="requirements">Requirements</a></h3> - -<p>The following requirements exist for building Apache:</p> - -<ul> - -<li>Disk Space<br><br> Make sure you have at least 50 MB of temporary -free disk space available. After installation Apache occupies -approximately 10 MB of disk space. The actual disk space requirements -will vary considerably based on your chosen configuration options and -any third-party modules.<br><br></li> - -<li>ANSI-C Compiler and Build System<br><br> Make sure you have an -ANSI-C compiler installed. The <a -href="http://www.gnu.org/software/gcc/gcc.html">GNU C compiler -(GCC)</a> from the <a href="http://www.gnu.org/">Free Software -Foundation (FSF)</a> is recommended (version 2.7.2 is fine). If you -don't have GCC then at least make sure your vendor's compiler is ANSI -compliant. In addition, your <code>PATH</code> must contain basic -build tools such as <code>make</code>.<br><br></li> - -<li>Accurate time keeping<br><br> Elements of the HTTP protocol are -expressed as the time of day. So, it's time to investigate setting -some time synchronization facility on your system. Usually the ntpdate -or xntpd programs are used for this purpose which are based on the -Network Time Protocol (NTP). See the Usenet newsgroup <a -href="news:comp.protocols.time.ntp">comp.protocols.time.ntp</a> and -the <a href="http://www.eecis.udel.edu/~ntp/">NTP homepage</a> for more -details about NTP software and public time servers.<br><br></li> - -<li><a href="http://www.perl.org/">Perl 5</a> [OPTIONAL]<br><br> For -some of the support scripts like <a href="programs/apxs.html">apxs</a> -or <a href="programs/dbmmanage.html">dbmmanage</a> (which are written -in Perl) the Perl 5 interpreter is required (versions 5.003 and 5.004 -are fine). If no such interpreter is found by the `configure' script -there is no harm. Of course, you still can build and install Apache -2.0. Only those support scripts cannot be used. If you have multiple -Perl interpreters installed (perhaps a Perl 4 from the vendor and a -Perl 5 from your own), then it is recommended to use the --with-perl -option (see below) to make sure the correct one is selected by -./configure. <br><br></li> - -</ul> - -<h3><a name="download">Download</a></h3> - -<p>Apache can be downloaded from the <a -href="http://www.apache.org/dist/httpd/">Apache Software Foundation -download site</a> or from a <a -href="http://www.apache.org/dyn/closer.cgi">nearby mirror</a>.</p> - -<p>Version numbers that end in <code>alpha</code> indicate early -pre-test versions which may or may not work. Version numbers ending -in <code>beta</code> 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 <code>alpha</code> nor -<code>beta</code> in its filename.</p> - -<p>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 <code>KEYS</code> file -from the <a href="http://www.apache.org/dist/">Apache distribution -site</a>. (To assure that the <code>KEYS</code> 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):</p> -<blockquote><code> -$ pgp < KEYS -</code></blockquote> -or -<blockquote><code> -$ gpg --import KEYS -</code></blockquote> - -<p>The next step is to test the tarball against the PGP signature, -which should always be obtained from the <a -href="http://www.apache.org/dist/httpd">main Apache website</a>. The -signature file has a filename identical to the source tarball with the -addition of <code>.asc</code>. Then you can check the distribution -with one of the following commands (again, depending on your pgp -version):</p> -<blockquote><code> -$ pgp httpd-2_0_<em>NN</em>.tar.gz.asc -</code></blockquote> -or -<blockquote><code> -$ gpg --verify httpd-2_0_<em>NN</em>.tar.gz.asc -</code></blockquote - -<p>You should receive a message like</p> -<blockquote><code> -Good signature from user "Martin Kraemer <martin@apache.org>". -</code></blockquote> -<p>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 <code>KEYS</code> file.</p> - -<h3><a name="extract">Extract</a></h3> - -<p>Extracting the source from the Apache HTTPD tarball is a simple -matter of uncompressing, and then untarring:</p> - -<blockquote><code> -$ gzip -d httpd-2_0_<em>NN</em>.tar.gz<br> -$ tar xvf httpd-2_0_<em>NN</em>.tar -</code></blockquote> - -<p>This will create a new directory under the current directory -containing the source code for the distribution. You should -<code>cd</code> into that directory before proceeding with -compiling the server.</p> - -<h3><a name="configure">Configuring the source tree</a></h3> - -<p>The next step is to configure the Apache source tree for your -particular platform and personal requirements. This is done using the -script <code>configure</code> included in the root directory of the -distribution. (Developers downloading the CVS version of the Apache -source tree will need to have <code>autoconf</code> and -<code>libtool</code> installed and will need to run -<code>buildconf</code> before proceeding with the next steps. This is -not necessary for official releases.)</p> - -<p>To configure the source tree using all the default options, simply -type <code>./configure</code>. To change the default options, -<code>configure</code> accepts a variety of variables and command line -options. Environment variables are generally placed before the -<code>./configure</code> 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.</p> - -<p>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:</p> - -<blockquote><code> - $ CC="pgcc" CFLAGS="-O2" \<br> - ./configure --prefix=/sw/pkg/apache \<br> - --enable-rewrite=shared \<br> - --enable-speling=shared -</code></blockquote> - -<p>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.</p> - -<p>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.</p> - -<h4><a name="environment">Environment Variables</a></h4> - -<p>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 <code>configure</code>, but it is usually easier to specify -them on the <code>configure</code> command line as demonstrated -in the example above.</p> - -<dl> - -<dt><code>CC=...</code></dt> -<dd>The name of the C compiler command.</dd> - -<dt><code>CPPFLAGS=...</code></dt> <dd>Miscellaneous C preprocessor -and compiler options.</dd> - -<dt><code>CFLAGS=...</code></dt> -<dd>Debugging and optimization options for the C compiler.</dd> - -<dt><code>LDFLAGS=...</code></dt> -<dd>Miscellaneous options to be passed to the linker.</dd> - -<dt><code>LIBS=...</code></dt> -<dd>Library location information ("-L" and "-l" options) -to pass to the linker.</dd> - -<dt><code>INCLUDES=...</code></dt> -<dd>Header file search directories ("-I<em>dir</em>").</dd> - -<dt><code>TARGET=...</code> [Default: apache]</dt> -<dd>Name of the executable which will be built.</dd> - -<dt><code>NOTEST_CPPFLAGS=...</code></dt> -<dt><code>NOTEST_CFLAGS=...</code></dt> -<dt><code>NOTEST_LDFLAGS=...</code></dt> -<dt><code>NOTEST_LIBS=...</code></dt> -<dd>These variables share the same function as their non-NOTEST namesakes. -However, the variables are applied to the build process only after -autoconf has performed its feature testing. This allows the inclusion of -flags which will cause problems during feature testing, but must be used -for the final compilation.</dd> - -<dt><code>SHLIB_PATH=...</code></dt> -<dd>Options which specify shared library paths for the compiler and -linker.</dd> - -</dl> - -<h4><a name="output">autoconf Output Options</a></h4> - -<dl> - -<dt><code>--help</code></dt> -<dd>Prints the usage message including all available options, but -does not actually configure anything.</dd> - -<dt><code>--quiet</code></dt> -<dd>Prevents the printing of the usual "checking..." messages.</dd> - -<dt><code>--verbose</code></dt> -<dd>Prints much more information during the configuration process, -including the names of all the files examined.</dd> - -</dl> - -<h4><a name="pathnames">Pathnames</a></h4> - -<p>There 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.</p> - -<dl> -<dt><code>--prefix=<em>PREFIX</em></code> [Default: -/usr/local/apache2]</dt> -<dd>Specifies the directory under which the Apache files will be -installed.</dd> -</dl> - -<p>It is possible to specify that architecture-dependent files should -be placed under a different directory.</p> - -<dl> -<dt><code>--exec-prefix=<em>EPREFIX</em></code> [Default: -<em>PREFIX</em>]</dt> -<dd>Specifies the directory under which architecture-dependent files -will be placed.</dd> -</dl> - -<p>The second, and more flexible way to configure the install path -locations for Apache is using the <code>config.layout</code> file. -Using this method, it is possible to separately specify the location -for each type of file within the Apache installation. The -<code>config.layout</code> 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 <code><Layout FOO>...</Layout></code> -sections and referred to by name as in <code>FOO</code>.</p> - -<dl> - -<dt><code>--enable-layout=<em>LAYOUT</em></code></dt> -<dd>Use the named layout in the <code>config.layout</code> file -to specify the installation paths.</dd> - -</dl> - -<p>Presently it is not possible to mix the -<code>--enable-layout</code> and <code>--prefix</code> options. Nor -is it possible to individually specify detailed pathnames on the -<code>configure</code> command line. If you want just a basic -install, you can simply use the <code>--prefix</code> option on its -own. If you want to customize your install, you should edit the -<code>config.layout</code> file and use the -<code>--enable-layout</code> option.</p> - -<h4><a name="modules">Modules</a></h4> - -<p>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 <a -href="mod/index-bytype.html">list of modules</a> included in the -documentation. Those modules with a <a -href="mod/module-dict.html#Status">status</a> -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.</p> - -<p>There are two ways for a module to be compiled and used with -Apache. Modules may be <em>statically compiled</em>, 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 <em>dynamically -compiled</em>. 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 <a -href="mod/mod_so.html">mod_so</a>. 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 <code>--enable-so</code>.</p> - -<dl> - -<dt><code>--enable-<em>MODULE</em>[=shared]</code></dt> <dd>Compile -and include the module <em>MODULE</em>. The identifier -<em>MODULE</em> is the <a -href="mod/module-dict.html#ModuleIdentifier" ->Module Identifier</a> from the module documentation without the -"_module" string. To compile the module as a DSO, add the -option <code>=shared</code>.</dd> - -<dt><code>--disable-<em>MODULE</em></code></dt> -<dd>Remove the module <em>MODULE</em> which would otherwise be -compiled and included.</dd> - -<dt><code>--enable-modules=<em>MODULE-LIST</em></code> <dd>Compile and -include the modules listed in the space-separated -<em>MODULE-LIST</em>.</dd> - -<dt><code>--enable-mods-shared=<em>MODULE-LIST</em></code> <dd>Compile -and include the modules in the space-separated <em>MODULE-LIST</em> as -dynamically loadable (DSO) modules.</dd> - -</dl> - -<p>The <em>MODULE-LIST</em> in the <code>--enable-modules</code> and -<code>--enable-mods-shared</code> options is usually a space-separated list -of module identifiers. For example, to enable mod_dav and mod_info, you -can either use</p> -<blockquote><code> -./configure --enable-dav --enable-info -</code></blockquote> -<p>or, equivalently,</p> -<blockquote><code> -./configure --enable-modules="dav info" -</code></blockquote> -<p>In addition, the special keywords <code>all</code> -or <code>most</code> 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 <code>--disable-<em>MODULE</em></code> option. For example, -to include all modules as DSOs with the exception of mod_info, you can use</p> -<blockquote><code> -./configure --enable-mods-shared=all --disable-info -</code></blockquote> - -<p>In addition to the standard set of modules, Apache 2.0 also -includes a choice of <a href="mpm.html">Multi-Processing Modules</a> -(MPMs). One, and only one MPM must be included in the compilation -process. The default MPMs for each platform are listed on the <a -href="mpm.html">MPM documentation page</a>, but can be overridden -on the <code>configure</code> command line. - -<dl> - -<dt><code>--with-mpm=<em>NAME</em></code></dt> -<dd>Choose the mpm <em>NAME</em>. - -</dl> - -<h4><a name="suexec">Suexec</a></h4> - -<p>Apache includes a support program called <a -href="suexec.html">suexec</a> 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 <a href="suexec.html">suexec documentation</a> before -implementing this feature.</p> - - -<h3><a name="compile">Build</a></h3> - -<p>Now you can build the various parts which form the Apache package -by simply running the command:</p> - -<blockquote><code> - $ make -</code></blockquote> - -<p>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.</p> - - -<h3><a name="install">Install</a></h3> - -<p>Now its time to install the package under the configured -installation <em>PREFIX</em> (see <code>--prefix</code> option above) -by running:</h3> <blockquote><code> $ make install -</code></blockquote> - -<p>If you are upgrading, the installation will not overwrite -your configuration files or documents.</p> - - -<h3><a name="customize">Customize</a></h3> - -<p>Next, you can customize your Apache HTTP server by editing the <a -href="configuring.html">configuration files</a> under -<em>PREFIX</em>/conf/.</p> - -<blockquote><code> -$ vi <em>PREFIX</em>/conf/httpd.conf -</code></blockquote> - -<p>Have a look at the Apache manual under <a -href="./">docs/manual/</a> or <a -href="http://httpd.apache.org/docs/">http://httpd.apache.org/docs/</a> -for a complete reference of available <a -href="mod/directives.html">configuration directives</a>.</p> - -<h3><a name="test">Test</a></h3> - -<p>Now you can <a href="invoking.html">start</a> your Apache HTTP -server by immediately running:</p> - -<blockquote><code> - $ <em>PREFIX</em>/bin/apachectl start -</code></blockquote> - -<p>and then you should be able to request your first document via URL -http://localhost/. The web page you see is located under the <a -href="mod/core.html#documentroot">DocumentRoot</a> which will usually -be <code><em>PREFIX</em>/htdocs/</code>. Then <a -href="stopping.html">stop</a> the server again by running:</p> - -<blockquote><code> $ <em>PREFIX</em>/bin/apachectl stop -</code></blockquote> - - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/docs/manual/invoking.html.en b/docs/manual/invoking.html.en deleted file mode 100644 index c8c6e3ba4c..0000000000 --- a/docs/manual/invoking.html.en +++ /dev/null @@ -1,118 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Starting Apache</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<H1 ALIGN="CENTER">Starting Apache</H1> - - -<ul> -<li><a href="#windows">Starting Apache on Windows</a></li> -<li><a href="#unix">Starting Apache on Unix</a> -<ul> -<li><a href="#errors">Errors During Start-up</a></li> -<li><a href="#boot">Starting at Boot-Time</a></li> -<li><a href="#info">Additional Information</a></li> -</ul> -</li> -</ul> - -<hr> - -<h2><a name="windows">Starting Apache On Windows</a></h2> - -<p>On Windows, Apache is normally run as a service on Windows NT, or -as a console application on Windows 95. For details, see <A -HREF="platform/windows.html#run">running Apache for Windows</A>.</p> - -<h2><a name="unix">Starting Apache on Unix</a></h2> - -<p>On Unix, the <a href="programs/httpd.html">httpd</a> program is run -as a daemon which executes continuously in the background to handle -requests.</p> - -<p>If the <a href="mod/core.html#port">Port</a> 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 <em>child</em> processes which -do the work of listening for and answering requests from clients. The -main <code>httpd</code> process continues to run as the root user, but -the child processes run as a less privileged user. This is controlled -by the selected <a href="mpm.html">Multi-Processing Module</a>.</p> - -<p>The first thing that <code>httpd</code> does when it is invoked is -to locate and read the <a href="configuring.html">configuration -file</a> <code>httpd.conf</code>. The location of this file is set at -compile-time, but it is possible to specify its location at run time -using the <code>-f</code> command-line option as in</p> -<blockquote><code> /usr/local/apache/bin/httpd -f -/usr/local/apache/conf/httpd.conf </code></blockquote> - -<p>As an alternative to invoking the <code>httpd</code> binary -directly, a shell script called <a -href="programs/apachectl.html">apachectl</a> is provided which can be -used to control the daemon process with simple commands such as -<code>apachectl start</code> and <code>apachectl stop</code>.</p> - -<p>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 <a href="mod/core.html#documentroot">DocumentRoot</a> -directory and the local copy of the documentation linked from -that page.</p> - -<h3><a name="errors">Errors During Start-up</a></h3> - -<p>If Apache suffers a fatal problem during startup, it will write a -message describing the problem either to the console or to the <a -href="mod/core.html#errorlog">ErrorLog</a> before exiting. One of the -most common error messages is "<code>Unable to bind to Port -...</code>". This message is usually caused by either:</p> -<ul> -<li>Trying to start the server on a privileged port when not -logged in as the root user; or</li> -<li>Trying to start the server when there is another instance -of Apache or some other web server already bound to the same Port.</li> -</ul> -<p>For further trouble-shooting instructions, consult the Apache <a -href="faq/">FAQ</a>.</p> - -<h3><a name="boot">Starting at Boot-Time</a></h3> - -<p>If you want your server to continue running after a system reboot, -you should add a call to <code>httpd</code> or <code>apachectl</code> -to your system startup files (typically <code>rc.local</code> or a -file in an <code>rc.N</code> directory). This will start Apache as -root. Before doing this ensure that your server is properly configured -for security and access restrictions. The <code>apachectl</code> -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.</p> - -<h3><a name="info">Additional Information</a></h3> - -<p>Additional information about the command-line options of <a -href="programs/httpd.html">httpd</a> and <a -href="programs/apachectl.html">apachectl</a> as well as other support -programs included with the server is available on the <a -href="programs/">Server and Supporting Programs</a> page. There is -also documentation on all the <a href="mod/">modules</a> included with -the Apache distribution and the <a -href="mod/directives.html">directives</a> that they provide.</p> - - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/docs/manual/logs.html.en b/docs/manual/logs.html.en deleted file mode 100644 index f83f474bf2..0000000000 --- a/docs/manual/logs.html.en +++ /dev/null @@ -1,582 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Log Files - Apache HTTP Server</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<h1 align="center">Log Files</h1> - -<p>In order to effectively manage a web server, it is necessary to get -feedback about the activity and performance of the server as well as -any problems that may be occuring. The Apache HTTP Server provides -very comprehensive and flexible logging capabilities. This document -describes how to configure its logging capabilities, and how to -understand what the logs contain.</p> - -<ul> -<li><a href="#security">Security Warning</a></li> -<li><a href="#errorlog">Error Log</a></li> -<li><a href="#accesslog">Access Log</a> - <ul> - <li><a href="#common">Common Log Format</a></li> - <li><a href="#combined">Combined Log Format</a></li> - <li><a href="#multiple">Multiple Access Logs</a></li> - <li><a href="#conditional">Conditional Logging</a></li> - </ul></li> -<li><a href="#rotation">Log Rotation</a></li> -<li><a href="#piped">Piped Logs</a></li> -<li><a href="#virtualhosts">VirtualHosts</a> -<li><a href="#other">Other Log Files</a> - <ul> - <li><a href="#pidfile">PID File</a></li> - <li><a href="#scriptlog">Script Log</a></li> - <li><a href="#rewritelog">Rewrite Log</a></li> - </ul></li> -</ul> - -<hr> - -<h2><a name="security">Security Warning</a></h2> - -<p>Anyone who can write to the directory where Apache is writing a -log file can almost certainly gain access to the uid that the server is -started as, which is normally root. Do <EM>NOT</EM> give people write -access to the directory the logs are stored in without being aware of -the consequences; see the <A HREF="misc/security_tips.html">security tips</A> -document for details.</p> - -<p>In addition, log files may contain information supplied directly -by the client, without escaping. Therefore, it is possible for -malicious clients to insert control-characters in the log files, so -care must be taken in dealing with raw logs.</p> - -<hr> - -<h2><a name="errorlog">Error Log</a></h2> - -<table border="1"> -<tr><td valign="top"> -<strong>Related Directives</strong><br><br> - -<a href="mod/core.html#errorlog">ErrorLog</a><br> -<a href="mod/core.html#loglevel">LogLevel</a> -</td></tr></table> - -<p>The server error log, whose name and location is set by the <a -href="mod/core.html#errorlog">ErrorLog</a> directive, is the most -important log file. This is the place where Apache httpd will send -diagnostic information and record any errors that it encounters in -processing requests. It is the first place to look when a problem -occurs with starting the server or with the operation of the server, -since it will often contain details of what went wrong and how to fix -it.</p> - -<p>The error log is usually written to a file (typically -<code>error_log</code> on unix systems and <code>error.log</code> on -Windows and OS/2). On unix systems it is also possible to have the -server send errors to <code>syslog</code> or <a href="#pipe">pipe -them to a program</a>.</p> - -<p>The format of the error log is relatively free-form and -descriptive. But there is certain information that is contained -in most error log entries. For example, here is a typical message.</p> - -<blockquote><code> -[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied by server configuration: /export/home/live/ap/htdocs/test -</code></blockquote> - -<p>The first item in the log entry is the date and time of the -message. The second entry lists the severity of the error being -reported. The <a href="mod/core.html#loglevel">LogLevel</a> directive -is used to control the types of errors that are sent to the error log -by restricting the severity level. The third entry gives the IP -address of the client that generated the error. Beyond that is the -message itself, which in this case indicates that the server has been -configured to deny the client access. The server reports the -file-system path (as opposed to the web path) of the requested -document.</p> - -<p>A very wide variety of different messages can appear in the error -log. Most look similar to the example above. The error log will also -contain debugging output from CGI scripts. Any information written to -<code>stderr</code> by a CGI script will be copied directly to the -error log.</p> - -<p>It is not possible to customize the error log by adding or removing -information. However, error log entries dealing with particular -requests have corresponding entries in the <a href="accesslog">access -log</a>. For example, the above example entry corresponds to an -access log entry with status code 403. Since it is possible to -customize the access log, you can obtain more information about error -conditions using that log file.</p> - -<p>During testing, it is often useful to continuously monitor the -error log for any problems. On unix systems, you can accomplish this -using:</p> -<blockquote><code> -tail -f error_log -</code></blockquote> - -<hr> - -<h2><a name="accesslog">Access Log</a></h2> - -<table border=1><tr><td valign="top"> -<strong>Related Modules</strong><br><br> - -<a href="mod/mod_log_config.html">mod_log_config</a><br> - -</td><td valign="top"> -<strong>Related Directives</strong><br><br> - -<a href="mod/mod_log_config.html#customlog">CustomLog</a><br> -<a href="mod/mod_log_config.html#logformat">LogFormat</a><br> -<a href="mod/mod_setenvif.html#setenvif">SetEnvIf</a> - -</td></tr></table> - -<p>The server access log records all requests processed by the server. -The location and content of the access log are controlled -by the <a href="mod/mod_log_config.html#customlog">CustomLog</a> -directive. The <a -href="mod/mod_log_config.html#logformat">LogFormat</a> directive can -be used to simplify the selection of the contents of the logs. -This section describes how to configure the server to record -information in the access log.</p> - -<p>Of course, storing the information in the access log is only the -start of log management. The next step is to analyze this information -to produce useful statistics. Log analysis in general is beyond the -scope of this document, and not really part of the job of the -web server itself. For more information about this topic, and for -applications which perform log analysis, check the <a -href="http://dmoz.org/Computers/Software/Internet/Site_Management/Log_analysis/" ->Open Directory</a> or <a -href="http://dir.yahoo.com/Computers_and_Internet/Software/Internet/World_Wide_Web/Servers/Log_Analysis_Tools/" ->Yahoo</a>.</p> - -<p>Various versions of Apache httpd have used other modules and -directives to control access logging, including mod_log_referer, -mod_log_agent, and the <code>TransferLog</code> directive. The -<code>CustomLog</code> directive now subsumes the functionality of all -the older directives.</p> - -<p>The format of the access log is highly configurable. The format is -specified using a <a href="mod/mod_log_config.html#format">format -string</a> that looks much like a C-style printf(1) format string. -Some examples are presented in the next sections. For a complete list -of the possible contents of the format string, see the <a -href="mod/mod_log_config.html">mod_log_config documentation</a>.</p> - -<h3><a name="common">Common Log Format</a></h3> - -<p>A typical configuration for the access log might look -as follows.</p> - -<blockquote><code> -LogFormat "%h %l %u %t \"%r\" %>s %b" common<br> -CustomLog logs/access_log common -</code></blockquote> - -<p>This defines the <em>nickname</em> <code>common</code> and -associates it with a particular log format string. The format string -consists of percent directives, each of which tell the server to log a -particular piece of information. Literal characters may also be -placed in the format string and will be copied directly into the log -output. The quote character (<code>"</code>) must be escaped by -placing a back-slash before it to prevent it from being interpreted as -the end of the format string. The format string may also contain the -special control characters "<code>\n</code>" for new-line and -"<code>\t</code>" for tab.</p> - -<p>The <code>CustomLog</code> directive sets up a new log file using -the defined <em>nickname</em>. The filename for the access log is -relative to the <a href="mod/core.html#serverroot">ServerRoot</a> -unless it begins with a slash.</p> - -<p>The above configuration will write log entries in a format known as -the Common Log Format (CLF). This standard format can be produced by -many different web servers and read by many log analysis programs. -The log file entries produced in CLF will look something like -this:</p> - -<blockquote><code> -127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 -</code></blockquote> - -<p>Each part of this log entry is described below.</p> - -<dl> -<dt><code>127.0.0.1</code> (<code>%h</code>)</dt> <dd>This is the IP -address of the client (remote host) which made the request to the -server. If <a -href="mod/core.html#hostnamelookups">HostNameLookups</a> is set to -<code>On</code>, then the server will try to determine the hostname -and log it in place of the IP address. However, this configuration is -not recommended since it can significantly slow the server. Instead, -it is best to use a log post-processor such as <a -href="programs/logresolve.html">logresolve</a> to determine the -hostnames. The IP address reported here is not necessarily the -address of the machine at which the user is sitting. If a proxy -server exists between the user and the server, this address will be -the address of the proxy, rather than the originating machine.</dd> - -<dt><code>-</code> (<code>%l</code>)</dt> <dd>The "hyphen" in the -output indicates that the requested piece of information is not -available. In this case, the information that is not available is the -RFC 1413 identity of the client determined by <code>identd</code> on -the clients machine. This information is highly unreliable and should -almost never be used except on tightly controlled internal networks. -Apache httpd will not even attempt to determine this information -unless <a href="mod/core.html#identitycheck">IdentityCheck</a> is set -to <code>On</code>.</dd> - -<dt><code>frank</code> (<code>%u</code>)</dt> <dd>This is the userid -of the person requesting the document as determined by HTTP -authentication. The same value is typically provided to CGI scripts -in the <code>REMOTE_USER</code> environment variable. If the status -code for the request (see below) is 401, then this value should not be -trusted because the user is not yet authenticated. If the document is -not password protected, this entry will be "<code>-</code>" just like -the previous one.</dd> - -<dt><code>[10/Oct/2000:13:55:36 -0700]</code> (<code>%t</code>)</dt> -<dd>The time that the server finished processing the request. The -format is: -<BLOCKQUOTE><CODE> [day/month/year:hour:minute:second zone] <BR> -day = 2*digit<BR> -month = 3*letter<BR> -year = 4*digit<BR> -hour = 2*digit<BR> -minute = 2*digit<BR> -second = 2*digit<BR> -zone = (`+' | `-') 4*digit</CODE></BLOCKQUOTE> -It is possible to have the time displayed in another format -by specifying <code>%{format}t</code> in the log format string, where -<code>format</code> is as in <code>strftime(3)</code> from the C -standard library. -</dd> - -<dt><code>"GET /apache_pb.gif HTTP/1.0"</code> -(<code>\"%r\"</code>)</dt> <dd>The request line from the client is -given in double quotes. The request line contains a great deal of -useful information. First, the method used by the client is -<code>GET</code>. Second, the client requested the resource -<code>/apache_pb.gif</code>, and third, the client used the protocol -<code>HTTP/1.0</code>. It is also possible to log one or more -parts of the request line independently. For example, the format -string "<code>%m %U%q %H</code>" will log the method, path, -query-string, and protocol, resulting in exactly the same output as -"<code>%r</code>".</dd> - -<dt><code>200</code> (<code>%>s</code>)</dt> <dd>This is the status -code that the server sends back to the client. This information is -very valuable, because it reveals whether the request resulted in a -successful response (codes beginning in 2), a redirection (codes -beginning in 3), an error caused by the client (codes beginning in 4), -or an error in the server (codes beginning in 5). -The full list of possible status codes can be -found in the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.txt" ->HTTP specification</a> (RFC2616 section 10).</dd> - -<dt><code>2326</code> (<code>%b</code>) -<dd>The last entry indicates the size of the object returned to -the client, not including the response headers. If no content -was returned to the client, this value will be "<code>-</code>". -To log "<code>0</code>" for no content, use <code>%B</code> -instead.</dd> - -</dl> - -<h4><a name="combined">Combined Log Format</a></h4> - -<p>Another commonly used format string is called the -Combined Log Format. It can be used as follows.</p> - -<blockquote><code> -LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined<br> -CustomLog log/acces_log combined -</code></blockquote> - -<p>This format is exactly the same as the Common Log Format, with the -addition of two more fields. Each of the additional fields uses the -percent-directive <code>%{<em>header</em>}i</code>, where -<em>header</em> can be any HTTP request header. The access log under -this format will look like:</p> - -<blockquote><code> -127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)" -</code></blockquote> - -<p>The additional fields are:</p> - -<dl> - -<dt><code>"http://www.example.com/start.html"</code> -(<code>\"%{Referer}i\"</code>)</dt> <dd>The "Referer" (sic) HTTP -request header. This gives the site that the client reports having -been referred from. (This should be the page that links to or includes -<code>/apache_pb.gif</code>). - -<dt><code>"Mozilla/4.08 [en] (Win98; I ;Nav)"</code> -(<code>\"%{User-agent}i\"</code>)</dt> <dd>The User-Agent HTTP request -header. This is the identifying information that the client browser -reports about itself.</dd> - -</dl> - -<h3><a name="multiple">Multiple Access Logs</a></h3> - -<p>Multiple access logs can be created simply by specifying multiple -<code>CustomLog</code> directives in the configuration file. For -example, the following directives will create three access logs. The -first contains the basic CLF information, while the second and third -contain referer and browser information. The last two -<code>CustomLog</code> lines show how to mimic the effects of the -<code>ReferLog</code> and <code>AgentLog</code> directives.</p> - -<blockquote><code> -LogFormat "%h %l %u %t \"%r\" %>s %b" common<br> -CustomLog logs/access_log common<br> -CustomLog logs/referer_log "%{Referer}i -> %U"<br> -CustomLog logs/agent_log "%{User-agent}i" -</code></blockquote> - -<p>This example also shows that it is not necessary to define a -nickname with the <code>LogFormat</code> directive. Instead, the log -format can be specified directly in the <code>CustomLog</code> -directive.</p> - -<h3><a name="conditional">Conditional Logging</a></h3> - -<p>There are times when it is convenient to exclude certain entries -from the access logs based on characteristics of the client request. -This is easily accomplished with the help of <a -href="env.html">environment variables</a>. First, an environment -variable must be set to indicate that the request meets certain -conditions. This is usually accomplished with <a -href="mod/mod_setenvif.html#setenvif">SetEnvIf</a>. Then the -<code>env=</code> clause of the <code>CustomLog</code> directive is -used to include or exclude requests where the environment variable is -set. Some examples:</p> - -<blockquote><code> -# Mark requests from the loop-back interface<br> -SetEnvIf Remote_Addr "127\.0\.0\.1" dontlog<br> -# Mark requests for the robots.txt file<br> -SetEnvIf Request_URI "^/robots\.txt$" dontlog<br> -# Log what remains<br> -CustomLog logs/access_log common env=!dontlog -</code></blockquote> - -<p>As another example, consider logging requests from english-speakers -to one log file, and non-english speakers to a different log file.</p> - -<blockquote><code> -SetEnvIf Accept-Language "en" english<br> -CustomLog logs/english_log common env=english<br> -CustomLog logs/non_english_log common env=!english -</code></blockquote> - -<p>Although we have just shown that conditional logging is very -powerful and flexibly, it is not the only way to control the contents -of the logs. Log files are more useful when they contain a complete -record of server activity. It is often easier to simply post-process -the log files to remove requests that you do not want to consider.</p> - -<hr> - -<h2><a name="rotation">Log Rotation</a></h2> - -<p>On even a moderately busy server, the quantity of information -stored in the log files is very large. The access log file typically -grows 1 MB or more per 10,000 requests. It will consequently be -necessary to periodically rotate the log files by moving or deleting -the existing logs. This cannot be done while the server is running, -because Apache will continue writing to the old log file as long as it -holds the file open. Instead, the server must be <a -href="stopping.html">restarted</a> after the log files are moved or -deleted so that it will open new log files.</p> - -<p>By using a <em>graceful</em> restart, the server can be instructed -to open new log files without losing any existing or pending -connections from clients. However, in order to accomplish this, the -server must continue to write to the old log files while it finishes -serving old requests. It is therefore necessary to wait for some time -after the restart before doing any processing on the log files. A -typical scenario that simply rotates the logs and compresses the old -logs to save space is:</p> - -<blockquote><code> -mv access_log access_log.old<br> -mv error_log error_log.old<br> -apachectl graceful<br> -sleep 600<br> -gzip access_log.old error_log.old -</code></blockquote> - -<p>Another way to perform log rotation is using <a href="#piped">piped -logs</a> as discussed in the next section.</p> - -<hr> - -<h2><a name="piped">Piped Logs</a></h2> - -<p>Apache httpd is capable of writing error and access log files -through a pipe to another process, rather than directly to a file. -This capability dramatically increases the flexibility of logging, -without adding code to the main server. In order to write logs to a -pipe, simply replace the filename with the pipe character -"<code>|</code>", followed by the name of the executable which should -accept log entries on its standard input. Apache will start the -piped-log process when the server starts, and will restart it if it -crashes while the server is running. (This last feature is why we can -refer to this technique as "reliable piped logging".)</p> - -<p>Piped log processes are spawned by the parent Apache httpd process, -and inherit the userid of that process. This means that piped log -programs usually run as root. It is therefore very important to keep -the programs simple and secure.</p> - -<p>Some simple examples using piped logs:</p> - -<blockquote><code> -# compressed logs<br> -CustomLog "|/usr/bin/gzip -c >> /var/log/access_log.gz" common<br> -# almost-real-time name resolution<br> -CustomLog "|/usr/local/apache/bin/logresolve >> /var/log/access_log" common -</code></blockquote> - -<p>Notice that quotes are used to enclose the entire command -that will be called for the pipe. Although these examples are -for the access log, the same technique can be used for the -error log.</p> - -<p>One important use of piped logs is to allow log rotation without -having to restart the server. The Apache HTTP Server includes a -simple program called <a -href="programs/rotatelogs.html">rotatelogs</a> for this purpose. For -example, to rotate the logs every 24 hours, you can use:</p> - -<blockquote><code> -CustomLog "|/usr/local/apache/bin/rotatelogs /var/log/access_log 86400" common -</code></blockquote> - -<p>A similar, but much more flexible log rotation program -called <a href="http://www.ford-mason.co.uk/resources/cronolog/">cronolog</a> -is available at an external site.</p> - -<p>As with conditional logging, piped logs are a very powerful tool, -but they should not be used where a simpler solution like -off-line post-processing is available.</p> - -<hr> - -<h2><a name="virtualhosts">Virtual Hosts</a></h2> - -<p>When running a server with many <a href="vhosts/">virtual -hosts</a>, there are several options for dealing with log files. -First, it is possible to use logs exactly as in a single-host server. -Simply by placing the logging directives outside the -<code><VirtualHost></code> sections in the main server context, -it is possible to log all requests in the same access log and error -log. This technique does not allow for easy collection of statistics -on individual virtual hosts.</p> - -<p>If <code>CustomLog</code> or <code>ErrorLog</code> directives are -placed inside a <code><VirtualHost></code> section, all requests -or errors for that virtual host will be logged only to the specified -file. Any virtual host which does not have logging directives will -still have its requests sent to the main server logs. This technique -is very useful for a small number of virtual hosts, but if the number -of hosts is very large, it can be complicated to manage. In addition, -it can often create problems with <a -href="vhosts/fd-limits.html">insufficient file descriptors</a>.</p> - -<p>For the access log, there is a very good compromise. By adding -information on the virtual host to the log format string, -it is possible to log all hosts to the same log, and later -split the log into individual files. For example, consider the -following directives.</p> - -<blockquote><code> -LogFormat "%v %l %u %t \"%r\" %>s %b" comonvhost<br> -CustomLog logs/access_log comonvhost -</code></blockquote> - -<p>The <code>%v</code> is used to log the name of the virtual host -that is serving the request. Then a program like <a -href="programs/other.html">split-logfile</a> can be used to -post-process the access log in order to split it into one file per -virtual host.</p> - -<p>Unfortunately, no similar technique is available for the error log, -so you must choose between mixing all virtual hosts in the same error -log and using one error log per virtual host.</p> - -<hr> - -<h2><a name="other">Other Log Files</a></h2> - -<table border=1><tr><td valign="top"> -<strong>Related Modules</strong><br><br> - -<a href="mod/mod_cgi.html">mod_cgi</a><br> -<a href="mod/mod_rewrite.html">mod_rewrite</a> - -</td><td valign="top"> -<strong>Related Directives</strong><br><br> - -<a href="mod/core.html#pidfile">PidFile</a><br> -<a href="mod/mod_rewrite.html#RewriteLog">RewriteLog</a></br> -<a href="mod/mod_rewrite.html#RewriteLogLevel">RewriteLogLevel</a></br> -<a href="mod/mod_cgi.html#scriptlog">ScriptLog</a><br> -<a href="mod/mod_cgi.html#scriptloglength">ScriptLogLength</a><br> -<a href="mod/mod_cgi.html#scriptlogbuffer">ScriptLogBuffer</a> - -</td></tr></table> - -<h3><a name="pidfile">PID File</a></h3> - -<p>On startup, Apache httpd saves the process id of the parent httpd -process to the file <code>logs/httpd.pid</code>. This filename can be -changed with the <A HREF="mod/core.html#pidfile">PidFile</A> -directive. The process-id is for use by the administrator in -restarting and terminating the daemon by sending signals -to the parent process; on Windows, use the -k command line -option instead. For more information see the <A -HREF="stopping.html">Stopping and Restarting</A> page. - -<h3><a name="scriptlog">Script Log</a></h3> - -<p>In order to aid in debugging, the -<a href="mod/mod_cgi.html#scriptlog">ScriptLog</a> -directive allows you to record the input to and output from -CGI scripts. This should only be used in testing - not for -live servers. More information is available in the -<a href="mod/mod_cgi.html">mod_cgi documentation</a>. - -<h3><a name="rewritelog">Rewrite Log</a></h3> - -<p>When using the powerful and complex features of <a -href="mod/mod_rewrite.html">mod_rewrite</a>, it is almost always -necessary to use the <a -href="mod/mod_rewrite.html#RewriteLog">RewriteLog</a> to help in -debugging. This log file produces a detailed analysis of how the -rewriting engine transforms requests. The level of detail is -controlled by the <a -href="mod/mod_rewrite.html#RewriteLogLevel">RewriteLogLevel</a> -directive.</p> - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/docs/manual/mod/directive-dict.html.en b/docs/manual/mod/directive-dict.html.en deleted file mode 100644 index 60458af690..0000000000 --- a/docs/manual/mod/directive-dict.html.en +++ /dev/null @@ -1,378 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> - <HEAD> - <TITLE>Definitions of terms used to describe Apache directives - </TITLE> - </HEAD> -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> - <BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" - > -<!--#include virtual="header.html" --> - <H1 ALIGN="CENTER">Terms Used to Describe Apache Directives</H1> - - <P> - Each Apache configuration directive is described using a common format - that looks like this: - </P> - <DL> - <DD><A - HREF="#Syntax" - REL="Help" - ><STRONG>Syntax:</STRONG></A> <EM>directive-name</EM> <EM>some args</EM> - <BR> - <A - HREF="#Default" - REL="Help" - ><STRONG>Default:</STRONG></A> - <SAMP><EM>directive-name default-value</EM></SAMP> - <BR> - <A - HREF="#Context" - REL="Help" - ><STRONG>Context:</STRONG></A> <EM>context-list</EM> - <BR> - <A - HREF="#Override" - REL="Help" - ><STRONG>Override:</STRONG></A> <EM>override</EM> - <BR> - <A - HREF="#Status" - REL="Help" - ><STRONG>Status:</STRONG></A> <EM>status</EM> - <BR> - <A - HREF="#Module" - REL="Help" - ><STRONG>Module:</STRONG></A> <EM>module-name</EM> - <BR> - <A - HREF="#Compatibility" - REL="Help" - ><STRONG>Compatibility:</STRONG></A> <EM>compatibility notes</EM> - <BR> - <A - HREF="#Deprecated" - REL="Help" - ><STRONG>Deprecated:</STRONG></A> <EM>see other</EM> - </DD> - </DL> - <P> - Each of the directive's attributes, complete with possible values - where possible, are described in this document. - </P> - - <H2>Directive Terms</H2> - <UL> - <LI><A HREF="#Syntax">Syntax</A> - </LI> - <LI><A HREF="#Default">Default</A> - </LI> - <LI><A HREF="#Context">Context</A> - </LI> - <LI><A HREF="#Override">Override</A> - </LI> - <LI><A HREF="#Status">Status</A> - </LI> - <LI><A HREF="#Module">Module</A> - </LI> - <LI><A HREF="#Compatibility">Compatibility</A> - </LI> - <LI><A HREF="#Deprecated">Deprecated</A> - </LI> - </UL> - - <HR> - <H2><A NAME="Syntax">Syntax</A></H2> - <P> - 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 space-separated arguments. If an argument contains a space, - the argument must be enclosed in double quotes. Optional arguments - are enclosed in square brackets. Where an argument can take on more - than one possible value, the possible values are separated by - vertical bars "|". Literal text is presented in the default font, - while argument-types for which substitution is necessary are - <em>emphasized</em>. Directives which can take a variable number of - arguments will end in "..." indicating that the last argument is - repeated. - </P> - - <P> - Directives use a great number of different argument types. - A few common ones are defined below.</p> - -<dl> - -<dt><em>URL</em></dt> - -<dd>A complete Uniform Resource Locator including a scheme, hostname, -and optional pathname as in -<code>http://www.example.com/path/to/file.html</code></dd> - -<dt><em>URL-path</em><dt> - -<dd>The part of a <em>url</em> which follows the scheme and hostname -as in <code>/path/to/file.html</code>. The <em>url-path</em> -represents a web-view of a resource, as opposed to a file-system -view.</dd> - -<dt><em>file-path</em></dt> - -<dd>The path to a file in the local file-system beginning with the -root directory as in -<code>/usr/local/apache/htdocs/path/to/file.html</code>. Unless -otherwise specified, a <em>file-path</em> which does not begin with a -slash will be treated as relative to the <a -href="core.html#serverroot">ServerRoot</a>.</dd> - -<dt><em>directory-path</em></dt> - -<dd>The path to a directory in the local file-system beginning with -the root directory as in -<code>/usr/local/apache/htdocs/path/to/</code>. - -<dt><em>filename</em></dt> - -<dd>The name of a file with no accompanying path information as in -<code>file.html</code>.</dd> - -<dt><em>regex</em></dt> - -<dd>A regular expression, which is a way of describing a pattern to -match in text. The directive definition will specify what the -<em>regex</em> is matching against.</dd> - -<dt><em>extension</em></dt> - -<dd>In general, this is the part of the <em>filename</em> which -follows the last dot. However, Apache recognizes multiple filename -extensions, so if a <em>filename</em> contains more than one dot, each -dot-separated part of the filename following the first dot is an -<em>extension</em>. For example, the <em>filename</em> -<code>file.html.en</code> contains two extensions: <code>.html</code> -and <code>.en</code>. For Apache directives, you may specify -<em>extension</em>s with or without the leading dot. In addition, -<em>extension</em>s are not case sensitive.</dd> - -<dt><em>MIME-type</em></dt> - -<dd>A method of describing the format of a file which consists of a -major format type and a minor format type, separated by a slash -as in <code>text/html</code>. - -<dt><em>env-variable</em></dt> - -<dd>The name of an <a href="../env.html">environment variable</a> -defined in the Apache configuration process. Note this is not -necessarily the same as an operating system environment variable. See -the <a href="../env.html">environment variable documentation</a> for -more details.</dd> - -</dl> - - <HR> - <H2><A NAME="Default">Default</A></H2> - <P> - If the directive has a default value (<EM>i.e.</EM>, 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 - "<EM>None</EM>". Note that the default listed here is not - necessarily the same as the value the directive takes in the - default httpd.conf distributed with the server. - </P> - - <HR> - <H2><A NAME="Context">Context</A></H2> - <P> - 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: - </P> - <DL> - <DT><STRONG>server config</STRONG> - </DT> - <DD>This means that the directive may be used in the server - configuration files (<EM>e.g.</EM>, <SAMP>httpd.conf</SAMP>, - <SAMP>srm.conf</SAMP>, and <SAMP>access.conf</SAMP>), but - <STRONG>not</STRONG> within any <SAMP><VirtualHost></SAMP> or - <Directory> containers. It is not allowed in - <SAMP>.htaccess</SAMP> files at all. - <P> - </P> - </DD> - <DT><STRONG>virtual host</STRONG> - </DT> - <DD>This context means that the directive may appear inside - <SAMP><VirtualHost></SAMP> containers in the server - configuration files. - <P> - </P> - </DD> - <DT><STRONG>directory</STRONG> - </DT> - <DD>A directive marked as being valid in this context may be used - inside <SAMP><Directory></SAMP>, - <SAMP><Location></SAMP>, and <SAMP><Files></SAMP> - containers in the server configuration files, subject to the - restrictions outlined in <A HREF="../sections.html">How Directory, - Location and Files sections work</A>. - <P> - </P> - </DD> - <DT><STRONG>.htaccess</STRONG> - </DT> - <DD>If a directive is valid in this context, it means that it can - appear inside <EM>per</EM>-directory <SAMP>.htaccess</SAMP> files. - It may not be processed, though depending upon the - <A - HREF="#Override" - REL="Help" - >overrides</A> - currently active. - <P> - </P> - </DD> - </DL> - <P> - The directive is <EM>only</EM> 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 -- - <EM>i.e.</EM>, the server won't even start. - </P> - <P> - 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 "<SAMP>server config, - .htaccess</SAMP>" can be used in the <SAMP>httpd.conf</SAMP> file - and in <SAMP>.htaccess</SAMP> files, but not within any - <Directory> or <VirtualHost> containers. - </P> - - <HR> - <H2><A NAME="Override">Override</A></H2> - <P> - This directive attribute indicates which configuration override must - be active in order for the directive to be processed when it appears - in a <SAMP>.htaccess</SAMP> file. If the directive's - <A - HREF="#Context" - REL="Help" - >context</A> - doesn't permit it to appear in <SAMP>.htaccess</SAMP> files, this - attribute should say "<EM>Not applicable</EM>". - </P> - <P> - Overrides are activated by the - <A - HREF="core.html#allowoverride" - REL="Help" - ><SAMP>AllowOverride</SAMP></A> - directive, and apply to a particular scope (such as a directory) and - all descendants, unless further modified by other - <SAMP>AllowOverride</SAMP> directives at lower levels. The - documentation for that directive also lists the possible override - names available. - </P> - - <HR> - <H2><A NAME="Status">Status</A></H2> - <P> - 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: - </P> - <DL> - <DT><STRONG>Core</STRONG> - </DT> - <DD>If a directive is listed as having "Core" status, that - means it is part of the innermost portions of the Apache Web server, - and is always available. - <P> - </P> - </DD> - <DT><STRONG>MPM</STRONG> - </DT> - <DD>A directive labeled as having "MPM" status is - provided by a <a href="../mpm.html">Multi-Processing Module</a>. - This type of directive will be available if and only if you are - using one of the MPMs lised on the <a href="#Module">Module</a> - line of the directive definition. - <P> - </P> - </DD> - <DT><STRONG>Base</STRONG> - </DT> - <DD>A directive labeled as having "Base" status is - supported by one of the standard Apache modules which is compiled - into the server by default, and is therefore normally available - unless you've taken steps to remove the module from your configuration. - <P> - </P> - </DD> - <DT><STRONG>Extension</STRONG> - </DT> - <DD>A directive with "Extension" status is provided by one - of the modules included with the Apache server kit, but the module - isn't normally compiled into the server. To enable the directive - and its functionality, you will need to change the server build - configuration files and re-compile Apache. - <P> - </P> - </DD> - <DT><STRONG>Experimental</STRONG> - </DT> - <DD>"Experimental" status indicates that the directive is - available as part of the Apache kit, but you're on your own if you - try to use it. The directive is being documented for completeness, - and is not necessarily supported. The module which provides the - directive may or may not be compiled in by default; check the top of - the page which describes the directive and its module to see if it - remarks on the availability. - <P> - </P> - </DD> - </DL> - - <HR> - <H2><A NAME="Module">Module</A></H2> - <P> - This quite simply lists the name of the source module which defines - the directive. - </P> - - <HR> - <H2><A NAME="Compatibility">Compatibility</A></H2> - <P> - 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 "<EM>No - compatibility issues.</EM>" - </P> - - <HR> - <H2><A NAME="Deprecated">Deprecated</A></H2> - <P> - If this directive is eliminated since the Apache version 1 distribution, - the directive or option that replaces the behavior should be cited here. - In general, directives, features, and options are only deprecated to - minimize debugging of conflicting features, or if the feature can only - continue to be supported in an alternate manner. - </P> - -<!--#include virtual="footer.html" --> - </BODY> -</HTML> diff --git a/docs/manual/mod/module-dict.html.en b/docs/manual/mod/module-dict.html.en deleted file mode 100644 index 7d99828e81..0000000000 --- a/docs/manual/mod/module-dict.html.en +++ /dev/null @@ -1,144 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> - <HEAD> - <TITLE>Definitions of terms used to describe Apache modules - </TITLE> - </HEAD> -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> - <BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" - > -<!--#include virtual="header.html" --> - <H1 ALIGN="CENTER">Terms Used to Describe Apache Modules</H1> - - <P> - Each Apache module is described using a common format that looks - like this: - </P> - <DL> - <DD><A - HREF="#Status" - REL="Help" - ><STRONG>Status:</STRONG></A> <EM>status</EM> - <BR> - <A - HREF="#SourceFile" - REL="Help" - ><STRONG>Source File:</STRONG></A> <EM>source-file</EM> - <BR> - <A - HREF="#ModuleIdentifier" - REL="Help" - ><STRONG>Module Identifier:</STRONG></A> <EM>module-identifier</EM> - <BR> - <A - HREF="#Compatibility" - REL="Help" - ><STRONG>Compatibility:</STRONG></A> <EM>compatibility notes</EM> - </DD> - </DL> - <P> - Each of the attributes, complete with values where possible, are - described in this document. - </P> - - <H2>Module Terms</H2> - <UL> - <LI><A HREF="#Status">Status</A> - </LI> - <LI><A HREF="#SourceFile">Source File</A> - </LI> - <LI><A HREF="#ModuleIdentifier">Module Identifier</A> - </LI> - <LI><A HREF="#Compatibility">Compatibility</A> - </LI> - </UL> - - <HR> - <H2><A NAME="Status">Status</A></H2> - <P> - 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: - </P> - <DL> - <DT><STRONG>MPM</STRONG> - </DT> - <DD>A module with status "MPM" is a <a - href="../mpm.html">Multi-Processing Module</a>. Unlike the other - types of modules, Apache must have one and only one MPM in use at - any time. This type of module is responsible for basic request - handling and dispatching. - <P> - </P> - <DT><STRONG>Base</STRONG> - </DT> - <DD>A module labeled as having "Base" status is compiled - and loaded into the server by default, and is therefore normally - available unless you have taken steps to remove the module from your - configuration. - <P> - </P> - </DD> - <DT><STRONG>Extension</STRONG> - </DT> - <DD>A module with "Extension" status is not normally - compiled and loaded into the server. To enable the module and its - functionality, you may need to change the server build - configuration files and re-compile Apache. - <P> - </P> - </DD> - <DT><STRONG>Experimental</STRONG> - </DT> - <DD>"Experimental" status indicates that the module is - available as part of the Apache kit, but you are on your own if you - try to use it. The module is being documented for completeness, - and is not necessarily supported. - <P> - </P> - </DD> - <DT><STRONG>External</STRONG> - </DT> - <DD>Modules which are not included with the base Apache - distribution ("third-party modules") may use the - "External" status. We are not responsible for, nor do we - support such modules. - <P> - </P> - </DD> - </DL> - - <HR> - <H2><A NAME="SourceFile">Source File</A></H2> - <P> - 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 <A - HREF="core.html#ifmodule"><CODE><IfModule></CODE></A> - directive. - </P> - - <HR> - <H2><A NAME="ModuleIdentifier">Module Identifier</A></H2> - <P> - This is a string which identifies the module for use in the <A - HREF="mod_so.html#loadmodule">LoadModule</A> directive when - dynamically loading modules. In particular, it is the name - of the external variable of type module in the source file. - </P> - - <HR> - <H2><A NAME="Compatibility">Compatibility</A></H2> - <P> - If the module was not part of the original Apache version 2 - distribution, the version in which it was introduced should be listed - here. - </P> -<!--#include virtual="footer.html" --> - </BODY> -</HTML> diff --git a/docs/manual/mpm.html.en b/docs/manual/mpm.html.en deleted file mode 100644 index 9c63844e92..0000000000 --- a/docs/manual/mpm.html.en +++ /dev/null @@ -1,90 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Apache Multi-Processing Modules (MPMs)</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> - -<!--#include virtual="header.html" --> - -<h1 align="center">Apache Multi-Processing Modules</h1> - -<p>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.</p> - -<p>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.</p> - -<p>Extending the modular design to this level of the server -allows two important benefits: -<ul> -<li>Apache can more cleanly and efficiently support a wide variety of -operating systems. In particular, the Windows version of Apache is -now much more efficient, since <a -href="mod/mpm_winnt.html">mpm_winnt</a> can use native networking -features in place of the POSIX layer used in Apache 1.3. This benefit -also extends to other operating systems that implement specialized -MPMs.</li> -<li>The server can be better customized for the needs of the -particular site. For example, sites that need a great deal of -scalability can choose to use a threaded MPM like <a -href="mod/threaded.html">threaded</a>, while sites requiring -stability or compatibility with older software can use a <a -href="mod/prefork.html">preforking MPM</a>. In addition, special -features like serving different hosts under different userids -(<a href="mod/perchild.html">perchild</a>) can be provided.</li> -</ul> - -<p>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 <a href="mod/">module index page</a>.</p> - -<h2 align="center">Choosing an MPM</h2> - -<p>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.</p> - -<p>To actually choose the desired MPM, use the argument --with-mpm= -<EM>NAME</EM> with the ./configure script. <EM>NAME</EM> is the name of -the desired MPM.</p> - -<p>Once the server has been compiled, it is possible to determine which -MPM was chosen by using <code>./httpd -l</code>. This command will list -every module that is compiled into the server, including the MPM.</p> - -<h2 align="center">MPM Defaults</h2> - -<ul> - <li> BeOS: mpmt_beos</li> - <li> OS/2: mpmt_os2</li> - <li> Unix: prefork </li> - <li> Windows: winnt</li> -</ul> - -<!--#include virtual="footer.html" --> - -</body> -</html> - diff --git a/docs/manual/sections.html.en b/docs/manual/sections.html.en deleted file mode 100644 index 7d91191a6c..0000000000 --- a/docs/manual/sections.html.en +++ /dev/null @@ -1,163 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML><HEAD> -<TITLE>How Directory, Location and Files sections work</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> - -<H1 ALIGN="CENTER">How Directory, Location and Files sections work</H1> - -<p>The sections <A -HREF="mod/core.html#directory"><CODE><Directory></CODE></A>, <A -HREF="mod/core.html#location"><CODE><Location></CODE></A> and <A -HREF="mod/core.html#files"><CODE><Files></CODE></A> 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.</p> - -<H2>Directives allowed in the sections</H2> - -<p>Everything that is syntactically allowed in -<CODE><Directory></CODE> is also allowed in -<CODE><Location></CODE> (except a sub-<CODE><Files></CODE> -section). Semantically, however some things, most -notably <CODE>AllowOverride</CODE> and the two options -<CODE>FollowSymLinks</CODE> and <CODE>SymLinksIfOwnerMatch</CODE>, -make no sense in <CODE><Location></CODE>, -<CODE><LocationMatch></CODE> or <CODE><DirectoryMatch></CODE>. -The same for <CODE><Files></CODE> -- syntactically everything -is fine, but semantically some things are different.</p> - -<H2>How the sections are merged</H2> - -<p>The order of merging is:</p> - -<OL> - -<LI> - - <CODE><Directory></CODE> (except regular expressions) and - .htaccess done simultaneously (with .htaccess, if allowed, overriding - <CODE><Directory></CODE>) - -</LI> - -<LI> - <CODE><DirectoryMatch></CODE>, and - <CODE><Directory></CODE> with regular expressions - -</LI> - - <LI><CODE><Files></CODE> and <CODE><FilesMatch></CODE> done - simultaneously - </LI> - - <LI><CODE><Location></CODE> and <CODE><LocationMatch></CODE> done - simultaneously - </LI> - -</OL> - -<p>Apart from <CODE><Directory></CODE>, each group is processed in -the order that they appear in the configuration -files. <CODE><Directory></CODE> (group 1 above) is processed in -the order shortest directory component to longest. If multiple -<CODE><Directory></CODE> 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 <CODE>Include</CODE> -directive will be treated as if they were inside the including file -at the location of the <CODE>Include</CODE> directive.</p> - -<p>Sections inside <CODE><VirtualHost></CODE> sections are applied -<EM>after</EM> the corresponding sections outside the virtual host -definition. This allows virtual hosts to override the main server -configuration.</p> - -<p>Later sections override earlier ones.</p> - -<H2>Notes about using sections</H2> - -<p>The general guidelines are:</p> - -<UL> -<LI> - If you are attempting to match objects at the filesystem level - then you must use <CODE><Directory></CODE> and/or - <CODE><Files></CODE>. -</LI> - -<LI> - If you are attempting to match objects at the URL level then you - must use <CODE><Location></CODE> -</LI> -</UL> - -<p>But a notable exception is:</p> - -<UL> -<LI> - proxy control is done via <CODE><Directory></CODE>. This is - a legacy mistake because the proxy existed prior to - <CODE><Location></CODE>. A future version of the config - language should probably switch this to - <CODE><Location></CODE>. -</LI> -</UL> - -<p>Note about .htaccess parsing:</p> - -<UL> -<LI> - Modifying .htaccess parsing during Location doesn't do - anything because .htaccess parsing has already occurred. -</UL> - -<p><CODE><Location></CODE> and symbolic links:</p> - -<UL> -<LI> - It is not possible to use "<CODE>Options FollowSymLinks</CODE>" - or "<CODE>Options SymLinksIfOwnerMatch</CODE>" inside a - <CODE><Location></CODE>, <CODE><LocationMatch></CODE> - or <CODE><DirectoryMatch></CODE> section - (the options are simply ignored). - Using the options in question is only possible inside a - <CODE><Directory></CODE> section (or a <CODE>.htaccess</CODE> file). -</UL> - -<p><CODE><Files></CODE> and <CODE>Options</CODE>:</p> - -<UL> -<LI> - Apache won't check for it, but using an <CODE>Options</CODE> - directive inside a <CODE><Files></CODE> section has no effect. -</UL> - -<p>Another note:</p> - -<UL> -<LI> - There is actually a - <CODE><Location></CODE>/<CODE><LocationMatch></CODE> - sequence performed just before the name translation phase (where - <CODE>Aliases</CODE> and <CODE>DocumentRoots</CODE> are used to - map URLs to filenames). The results of this sequence are - completely thrown away after the translation has completed. -</LI> -</UL> - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/docs/manual/stopping.html.en b/docs/manual/stopping.html.en deleted file mode 100644 index eb6502574a..0000000000 --- a/docs/manual/stopping.html.en +++ /dev/null @@ -1,193 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Stopping and Restarting the Server</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<H1 ALIGN="CENTER">Stopping and Restarting the Server</H1> - -<P>This document covers stopping and restarting Apache on Unix-like -systems. Windows users should see <A -HREF="platform/windows.html#signal">Signalling Apache when -running</A>.</P> - -<P>You will notice many <CODE>httpd</CODE> executables running on your system, -but you should not send signals to any of them except the parent, whose -pid is in the <A HREF="mod/core.html#pidfile">PidFile</A>. 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: -<CODE>TERM</CODE>, <CODE>HUP</CODE>, and <CODE>USR1</CODE>, which will -be described in a moment. - -<P>To send a signal to the parent you should issue a command such as: -<BLOCKQUOTE><PRE> - kill -TERM `cat /usr/local/apache/logs/httpd.pid` -</PRE></BLOCKQUOTE> - -You can read about its progress by issuing: - -<BLOCKQUOTE><PRE> - tail -f /usr/local/apache/logs/error_log -</PRE></BLOCKQUOTE> - -Modify those examples to match your -<A HREF="mod/core.html#serverroot">ServerRoot</A> and -<A HREF="mod/core.html#pidfile">PidFile</A> settings. - -<p>A shell script called <a -href="programs/apachectl.html">apachectl</a> is provided which -automates the processing of signalling Apache. For details about this -script, see the documentation on <a href="invoking.html">starting -Apache</a>.</p> - -<H3>Stop Now</h3> - -<p><strong>Signal:</strong> TERM<br> -<code>apachectl stop</code></p> - -<P>Sending the <CODE>TERM</CODE> 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. - -<H3>Graceful Restart</H3> - -<p><strong>Signal:</strong> WINCH<br> -<code>apachectl graceful</code></p> - -<P>The <CODE>WINCH</CODE> signal causes the parent process to <EM>advise</EM> -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 <EM>generation</EM> of the -configuration, which begins serving new requests immediately.</p> - -<P>This code is designed to always respect the <A -HREF="mod/mpm_common.html#maxclients">MaxClients</A>, <A -HREF="mod/prefork.html#minspareservers">MinSpareServers</A>, and <A -HREF="mod/prefork.html#maxspareservers">MaxSpareServers</A> -settings. Furthermore, it respects <A -HREF="mod/mpm_common.html#startservers">StartServers</A> 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.</p> - -<P>Users of the -<A HREF="mod/mod_status.html">status module</A> -will notice that the server statistics -are <STRONG>not</STRONG> set to zero when a <CODE>USR1</CODE> 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 <EM>scoreboard</EM> used to keep track -of all children across generations. - -<P>The status module will also use a <CODE>G</CODE> to indicate those -children which are still serving requests started before the graceful -restart was given. - -<P>At present there is no way for a log rotation script using -<CODE>WINCH</CODE> 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 <CODE>WINCH</CODE> 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. - -<P><STRONG>Note:</STRONG> 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 <CODE>-t</CODE> -command line argument (see <A -HREF="programs/httpd.html">httpd</A>). 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. - - -<H3>Restart Now</H3> - -<p><strong>Signal:</strong> HUP<br> -<code>apachectl restart</code></p> - -<P>Sending the <CODE>HUP</CODE> signal to the parent causes it to kill off -its children like in <CODE>TERM</CODE> 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. - -<P>Users of the -<A HREF="mod/mod_status.html">status module</A> -will notice that the server statistics are -set to zero when a <CODE>HUP</CODE> is sent. - -<P><STRONG>Note:</STRONG> 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. - - -<H3>Appendix: signals and race conditions</H3> - -<P>Prior to Apache 1.2b9 there were several <EM>race conditions</EM> -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. - -<P>Architectures that use an on disk -<A HREF="mod/core.html#scoreboardfile">ScoreBoardFile</A> -have the potential to corrupt their scoreboards. This can result in -the "bind: Address already in use" (after <CODE>HUP</CODE>) or -"long lost child came home!" (after <CODE>USR1</CODE>). 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 <a HREF= -"mod/core.html#scoreboardfile">ScoreBoardFile</a> documentation for a -architecture uses it. - -<P><CODE>NEXT</CODE> and <CODE>MACHTEN</CODE> (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. -<!-- they don't have sigaction, or we're not using it -djg --> - -<P>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. - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/docs/manual/suexec.html.en b/docs/manual/suexec.html.en deleted file mode 100644 index 8988cd42b8..0000000000 --- a/docs/manual/suexec.html.en +++ /dev/null @@ -1,516 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Apache suEXEC Support</TITLE> -</HEAD> -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> - -<H1 ALIGN="CENTER">Apache suEXEC Support</H1> - -<P ALIGN="LEFT"> -<OL> - <LI><BIG><STRONG>CONTENTS</STRONG></BIG></LI> - <LI><A HREF="#what">What is suEXEC?</A></LI> - <LI><A HREF="#before">Before we begin.</A></LI> - <LI><A HREF="#model">suEXEC Security Model.</A></LI> - <LI><A HREF="#install">Configuring & Installing suEXEC</A></LI> - <LI><A HREF="#enable">Enabling & Disabling suEXEC</A></LI> - <LI><A HREF="#usage">Using suEXEC</A></LI> - <LI><A HREF="#debug">Debugging suEXEC</A></LI> - <LI><A HREF="#jabberwock">Beware the Jabberwock: Warnings & - Examples</A></LI> -</OL> -</P> - -<H3><A NAME="what">What is suEXEC?</A></H3> -<P ALIGN="LEFT"> -The <STRONG>suEXEC</STRONG> feature -- introduced in Apache 1.2 -- provides -Apache users the ability to run <STRONG>CGI</STRONG> and <STRONG>SSI</STRONG> -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. -</P> - -<P ALIGN="LEFT"> -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. -</P> - -<P ALIGN="CENTER"> -<STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> -</P> - -<H3><A NAME="before">Before we begin.</A></H3> -<P ALIGN="LEFT"> -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. -</P> - -<P ALIGN="LEFT"> -First, it is assumed that you are using a UNIX derivate operating system that -is capable of <STRONG>setuid</STRONG> and <STRONG>setgid</STRONG> operations. -All command examples are given in this regard. Other platforms, if they are -capable of supporting suEXEC, may differ in their configuration. -</P> - -<P ALIGN="LEFT"> -Second, it is assumed you are familiar with some basic concepts of your -computer's security and its administration. This involves an understanding -of <STRONG>setuid/setgid</STRONG> operations and the various effects they -may have on your system and its level of security. -</P> - -<P ALIGN="LEFT"> -Third, it is assumed that you are using an <STRONG>unmodified</STRONG> -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 -<STRONG>highly</STRONG> 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. -</P> - -<P ALIGN="LEFT"> -Fourth, and last, it has been the decision of the Apache Group to -<STRONG>NOT</STRONG> 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. -</P> - -<P ALIGN="LEFT"> -Still with us? Yes? Good. Let's move on! -</P> - -<P ALIGN="CENTER"> -<STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> -</P> - -<H3><A NAME="model">suEXEC Security Model</A></H3> -<P ALIGN="LEFT"> -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. -</P> - -<P ALIGN="LEFT"> -<STRONG>suEXEC</STRONG> 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. -</P> - -<P ALIGN="LEFT"> -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: -<OL> - <LI><STRONG>Was the wrapper called with the proper number of - arguments?</STRONG> - <BLOCKQUOTE> - 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. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the user executing this wrapper a valid user of this - system?</STRONG> - <BLOCKQUOTE> - This is to ensure that the user executing the wrapper is truly a user of the - system. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is this valid user allowed to run the wrapper?</STRONG> - <BLOCKQUOTE> - Is this user the user allowed to run this wrapper? Only one user (the - Apache user) is allowed to execute this program. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Does the target program have an unsafe hierarchical - reference?</STRONG> - <BLOCKQUOTE> - Does the target program contain a leading '/' or have a '..' backreference? - These are not allowed; the target program must reside within the Apache - webspace. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target user name valid?</STRONG> - <BLOCKQUOTE> - Does the target user exist? - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target group name valid?</STRONG> - <BLOCKQUOTE> - Does the target group exist? - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target user <EM>NOT</EM> superuser?</STRONG> - <BLOCKQUOTE> - Presently, suEXEC does not allow 'root' to execute CGI/SSI programs. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target userid <EM>ABOVE</EM> the minimum ID - number?</STRONG> - <BLOCKQUOTE> - 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. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target group <EM>NOT</EM> the superuser group?</STRONG> - <BLOCKQUOTE> - Presently, suEXEC does not allow the 'root' group to execute CGI/SSI - programs. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target groupid <EM>ABOVE</EM> the minimum ID - number?</STRONG> - <BLOCKQUOTE> - 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. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Can the wrapper successfully become the target user and - group?</STRONG> - <BLOCKQUOTE> - 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. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Does the directory in which the program resides exist?</STRONG> - <BLOCKQUOTE> - If it doesn't exist, it can't very well contain files. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the directory within the Apache webspace?</STRONG> - <BLOCKQUOTE> - 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? - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the directory <EM>NOT</EM> writable by anyone else?</STRONG> - <BLOCKQUOTE> - We don't want to open up the directory to others; only the owner user - may be able - to alter this directories contents. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Does the target program exist?</STRONG> - <BLOCKQUOTE> - If it doesn't exists, it can't very well be executed. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target program <EM>NOT</EM> writable by anyone - else?</STRONG> - <BLOCKQUOTE> - We don't want to give anyone other than the owner the ability to - change the program. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target program <EM>NOT</EM> setuid or setgid?</STRONG> - <BLOCKQUOTE> - We do not want to execute programs that will then change our UID/GID again. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target user/group the same as the program's - user/group?</STRONG> - <BLOCKQUOTE> - Is the user the owner of the file? - </BLOCKQUOTE> - </LI> - <LI><STRONG>Can we successfully clean the process environment to - ensure safe operations?</STRONG> - <BLOCKQUOTE> - 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). - </BLOCKQUOTE> - </LI> - <LI><STRONG>Can we successfully become the target program and - execute?</STRONG> - <BLOCKQUOTE> - Here is where suEXEC ends and the target program begins. - </BLOCKQUOTE> - </LI> -</OL> -</P> - -<P ALIGN="LEFT"> -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. -</P> - -<P ALIGN="LEFT"> -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 -<A HREF="#jabberwock">"Beware the Jabberwock"</A> -section of this document. -</P> - -<P ALIGN="CENTER"> -<STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> -</P> - -<H3><A NAME="install">Configuring & Installing suEXEC</A></H3> -<P ALIGN="LEFT"> -Here's where we begin the fun. If you use Apache 1.2 or prefer to configure -Apache 1.3 with the "<CODE>src/Configure</CODE>" 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). -</P> - -<P ALIGN="LEFT"> -<STRONG>APACI's suEXEC configuration options</STRONG><BR> -<DL> -<DT><CODE>--enable-suexec</CODE> -<DD>This option enables the suEXEC feature which is never installed or - activated by default. At least one --suexec-xxxxx option has to be - provided together with the --enable-suexec option to let APACI - accept your request for using the suEXEC feature. -<DT><CODE>--suexec-caller=<EM>UID</EM></CODE> -<DD>The <A HREF="mod/core.html#user">username</A> under which - Apache normally runs. - This is the only user allowed to execute this program. -<DT><CODE>--suexec-docroot=<EM>DIR</EM></CODE> -<DD>Define as the DocumentRoot set for Apache. - This will be the only hierarchy (aside from UserDirs) - that can be used for suEXEC behavior. - The default directory is the --datadir value with - the suffix "/htdocs", <EM>e.g.</EM> if you configure with - "<CODE>--datadir=/home/apache</CODE>" the directory - "/home/apache/htdocs" is used as document root for - the suEXEC wrapper. -<DT><CODE>--suexec-logfile=<EM>FILE</EM></CODE> -<DD>This defines the filename to which all suEXEC transactions and - errors are logged (useful for auditing and debugging purposes). - By default the logfile is named "suexec_log" and located in your - standard logfile directory (--logfiledir). -<DT><CODE>--suexec-userdir=<EM>DIR</EM></CODE> -<DD>Define to be the subdirectory under users' - home directories where suEXEC access should - be allowed. All executables under this directory - will be executable by suEXEC as the user so - they should be "safe" programs. If you are - using a "simple" UserDir directive (ie. one - without a "*" in it) this should be set to - the same value. suEXEC will not work properly - in cases where the UserDir directive points to - a location that is not the same as the user's - home directory as referenced in the passwd file. - Default value is "public_html". - <BR> - If you have virtual hosts with a different - UserDir for each, you will need to define them to - all reside in one parent directory; then name that - parent directory here. <STRONG>If this is not defined - properly, "~userdir" cgi requests will not work!</STRONG> -<DT><CODE>--suexec-uidmin=<EM>UID</EM></CODE> -<DD>Define this as the lowest UID allowed to be a target user - for suEXEC. For most systems, 500 or 100 is common. - Default value is 100. -<DT><CODE>--suexec-gidmin=<EM>GID</EM></CODE> -<DD>Define this as the lowest GID allowed to be a target group - for suEXEC. For most systems, 100 is common and therefore - used as default value. -<DT><CODE>--suexec-safepath=<EM>PATH</EM></CODE> -<DD>Define a safe PATH environment to pass to CGI executables. - Default value is "/usr/local/bin:/usr/bin:/bin". -</DL> -</P> - -<P ALIGN="LEFT"> -<STRONG>Checking your suEXEC setup</STRONG><BR> -Before you compile and install the suEXEC wrapper you can check -the configuration with the --layout option. -<BR> -Example output: -<PRE> - 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 -</PRE> -</P> - -<P ALIGN="LEFT"> -<STRONG>Compiling and installing the suEXEC wrapper</STRONG><BR> -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". -<BR> -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". -<BR> -Please note that you need <STRONG><EM>root privileges</EM></STRONG> for -the installation step. In order for the wrapper to set the user ID, it -must be installed as owner <CODE><EM>root</EM></CODE> and must have the -setuserid execution bit set for file modes. -</P> - -<P ALIGN="CENTER"> -<STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> -</P> - -<H3><A NAME="enable">Enabling & Disabling suEXEC</A></H3> -<P ALIGN="LEFT"> -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: -<PRE> - [notice] suEXEC mechanism enabled (wrapper: <EM>/path/to/suexec</EM>) -</PRE> -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 <EM>setuid root</EM>. -<BR> -If you want to enable the suEXEC mechanism for the first time -and an Apache server is already running you must kill and restart Apache. -Restarting it with a simple HUP or USR1 signal will not be enough. -<BR> -If you want to disable suEXEC you should kill and restart Apache after -you have removed the "suexec" file. -</P> - -<P ALIGN="CENTER"> -<STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> -</P> - -<H3><A NAME="usage">Using suEXEC</A></H3> -<P ALIGN="LEFT"> -<STRONG>Virtual Hosts:</STRONG><BR> -One way to use the suEXEC wrapper is through the -<A HREF="mod/core.html#user">User</A> and -<A HREF="mod/core.html#group">Group</A> directives in -<A HREF="mod/core.html#virtualhost">VirtualHost</A> -definitions. By setting these directives to values different from the -main server user ID, all requests for CGI resources will be executed as -the <EM>User</EM> and <EM>Group</EM> defined for that -<CODE><VirtualHost></CODE>. If only one or -neither of these directives are specified for a -<CODE><VirtualHost></CODE> then the main -server userid is assumed. -<P> -<STRONG>User directories:</STRONG><BR> -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 "<STRONG><CODE>~</CODE></STRONG>" 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 <A HREF="#model">security checks</A> above. - -<P ALIGN="CENTER"> -<STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> -</P> - -<H3><A NAME="debug">Debugging suEXEC</A></H3> -<P ALIGN="LEFT"> -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. -</P> - -<P ALIGN="CENTER"> -<STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> -</P> - -<H3> -<A NAME="jabberwock">Beware the Jabberwock: Warnings & Examples</A> -</H3> -<P ALIGN="LEFT"> -<STRONG>NOTE!</STRONG> This section may not be complete. For the latest -revision of this section of the documentation, see the Apache Group's -<A HREF="http://www.apache.org/docs/suexec.html">Online Documentation</A> -version. -</P> - -<P ALIGN="LEFT"> -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. -<UL> - <LI><STRONG>suEXEC Points Of Interest</STRONG></LI> - <LI>Hierarchy limitations - <BLOCKQUOTE> - 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.) - </BLOCKQUOTE> - </LI> - <LI>suEXEC's PATH environment variable - <BLOCKQUOTE> - This can be a dangerous thing to change. Make certain every - path you include in this define is a <STRONG>trusted</STRONG> - directory. You don't want to open people up to having someone - from across the world running a trojan horse on them. - </BLOCKQUOTE> - </LI> - <LI>Altering the suEXEC code - <BLOCKQUOTE> - Again, this can cause <STRONG>Big Trouble</STRONG> if you try - this without knowing what you are doing. Stay away from it - if at all possible. - </BLOCKQUOTE> - </LI> -</UL> - -<P ALIGN="CENTER"> -<STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> -</P> - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/docs/manual/urlmapping.html.en b/docs/manual/urlmapping.html.en deleted file mode 100755 index 4f26c80629..0000000000 --- a/docs/manual/urlmapping.html.en +++ /dev/null @@ -1,247 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Mapping URLs to Filesystem Locations - Apache HTTP Server</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<h1 align="center">Mapping URLs to Filesystem Locations</h1> - -<p>This document explains how Apache uses the URL of a request to -determine the filesystem location from which to serve a file.</p> - -<ul> -<li><a href="#documentroot">DocumentRoot</a></li> -<li><a href="#outside">Files Outside the DocumentRoot</a></li> -<li><a href="#user">User Directories</a></li> -<li><a href="#redirect">URL Redirection</a></li> -<li><a href="#rewrite">Rewrite Engine</a></li> -<li><a href="#notfound">File Not Found</a></li> -</ul> - -<hr> - -<table border="1"> -<tr><td valign="top"> -<strong>Related Modules</strong><br><br> - -<a href="mod/mod_alias.html">mod_alias</a><br> -<a href="mod/mod_rewrite.html">mod_rewrite</a><br> -<a href="mod/mod_userdir.html">mod_userdir</a><br> -<a href="mod/mod_speling.html">mod_speling</a><br> -<a href="mod/mod_vhost_alias.html">mod_vhost_alias</a><br> - -</td><td valign="top"> -<strong>Related Directives</strong><br><br> - -<A HREF="mod/mod_alias.html#alias">Alias</A><br> -<A HREF="mod/mod_alias.html#aliasmatch">AliasMatch</A><br> -<A HREF="mod/mod_speling.html#checkspelling">CheckSpelling</A><br> -<A HREF="mod/core.html#documentroot">DocumentRoot</A><br> -<A HREF="mod/core.html#errordocument">ErrorDocument</A><br> -<a href="mod/core.html#options">Options</a><br> -<A HREF="mod/mod_alias.html#redirect">Redirect</A><br> -<A HREF="mod/mod_alias.html#redirectmatch">RedirectMatch</A><br> -<A HREF="mod/mod_rewrite.html#RewriteCond">RewriteCond</A><br> -<A HREF="mod/mod_rewrite.html#RewriteRule">RewriteRule</A><br> -<A HREF="mod/mod_alias.html#scriptalias">ScriptAlias</A><br> -<A HREF="mod/mod_alias.html#scriptaliasmatch">ScriptAliasMatch</A><br> -<A HREF="mod/mod_userdir.html#userdir">UserDir</A><br> - -</td></tr></table> - -<h2><a name="documentroot">DocumentRoot</a></h2> - -<p>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 hostname and port) and add it to the end of the -<a href="mod/core.html#documentroot">DocumentRoot</a> specified in -your configuration files. Therefore, the files and directories -underneath the <code>DocumentRoot</code> make up the basic document -tree which will be visible from the web.</p> - -<p>Apache is also capable of <a href="vhosts/">Virtual Hosting</a>, -where the server receives requests for more than one host. In this -case, a different <code>DocumentRoot</code> can be specified for each -virtual host, or alternatively, the directives provided by the module -<a href="mod/mod_vhost_alias.html">mod_vhost_alias</a> can be used to -dynamically determine the appropriate place from which to serve -content based on the requested IP address or hostname.</p> - -<h2><a name="outside">Files Outside the DocumentRoot</a></h2> - -<p>There are frequently circumstances where it is necessary to allow -web access to parts of the filesystem that are not strictly underneath -the <a href="mod/core.html#documentroot">DocumentRoot</a>. Apache -offers several different ways to accomplish this. On Unix systems, -symbolic links can bring other parts of the filesystem under the -<code>DocumentRoot</code>. For security reasons, Apache will follow -symbolic links only if the <a href="mod/core.html#options">Options</a> -setting for the relevant directory includes -<code>FollowSymLinks</code> or <code>SymLinksIfOwnerMatch</code>.</p> - -<p>Alternatively, the <a href="mod/mod_alias.html#alias">Alias</a> -directive will map any part of the filesystem into the web -space. For example, with</p> - -<blockquote><code>Alias /docs /var/web/ -</code></blockquote> - -<p>the URL <code>http://www.example.com/docs/dir/file.html</code> will -be served from <code>/var/web/dir/file.html</code>. The <a -href="mod/mod_alias.html#scriptalias">ScriptAlias</a> directive works -the same way, with the additional effect that all content located at -the target path is treated as CGI scripts.</p> - -<p>For situations where you require additional flexibility, you can -use the <a href="mod/mod_alias.html#aliasmatch">AliasMatch</a> and <a -href="mod/mod_alias.html#scriptaliasmatch">ScriptAliasMatch</a> -directives to do powerful regular-expression based matching and -substitution. For example,</p> - -<blockquote><code> ScriptAliasMatch ^/~([^/]*)/cgi-bin/(.*) -/home/$1/cgi-bin/$2 </code></blockquote> - -<p>will map a request to -<code>http://example.com/~user/cgi-bin/script.cgi</code> to the path -<code>/home/user/cgi-bin/script.cgi</code> and will treat the -resulting file as a CGI script.</p> - -<h2><a name="user">User Directories</a></h2> - -<p>Traditionally on Unix systems, the home directory of a particular -<em>user</em> can be referred to as <code>~user/</code>. The module -<a href="mod/mod_userdir.html">mod_userdir</a> extends this idea to -the web by allowing files under each user's home directory to be -accessed using URLs such as the following.</p> - -<blockquote><code>http://www.example.com/~user/file.html</code></blockquote> - -<p>For security reasons, it is inappropriate to give direct -access to a user's home directory from the web. Therefore, the <a -href="mod/mod_userdir.html#userdir">UserDir</a> directive -specifies a directory underneath the user's home directory where web -files are located. Using the default setting of <code>Userdir -public_html</code>, the above URL maps to a file at a directory -like <code>/home/user/public_html/file.html</code> where -<code>/home/user/</code> is the user's home directory as specified in -<code>/etc/passwd</code>.</p> - -<p>There are also several other forms of the <code>Userdir</code> -directive which you can use on systems where <code>/etc/passwd</code> -does not contain the location of the home directory.</p> - -<p>Some people find the "~" symbol (which is often encoded on the web -as <code>%7e</code>) 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 <a -href="mod/mod_alias.html#aliasmatch">AliasMatch</a> directive to -achieve the desired effect. For example, to make -<code>http://www.example.com/upages/user/file.html</code> map to -<code>/home/user/public_html/file.html</code>, use the following -<code>AliasMatch</code> directive:</p> - -<blockquote><code> -AliasMatch ^/upages/([^/]*)/?(.*) /home/$1/public_html/$2 -</code></blockquote> - -<h2><a name="redirect">URL Redirection</a></h2> - -<p>The configuration directives discussed in the above sections 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 requested content is located at a different -URL, and instruct the client to make a new request with the new URL. -This is called <em>redirection</em> and is implemented by the -<a href="mod/mod_alias.html#redirect">Redirect</a> directive. For -example, if the contents of the directory <code>/foo/</code> under the -<code>DocumentRoot</code> are moved to the new directory -<code>/bar/</code>, you can instruct clients to request the content at -the new location as follows:</p> - -<blockquote><code>Redirect permanent -/foo/ http://www.example.com/bar/</code></blockquote> - -<p>This will redirect any URL-Path starting in <code>/foo/</code> to -the same URL path on the <code>www.example.com</code> server with -<code>/bar/</code> substituted for <code>/foo/</code>. You can -redirect clients to any server, not only the origin server.</p> - -<p>Apache also provides a <a -href="mod/mod_alias.html#redirectmatch">RedirectMatch</a> directive -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, use the following configuration:</p> - -<blockquote><code> -RedirectMatch permanent ^/$ http://www.example.com/startpage.html -</code></blockquote> - -<p>Alternatively, to temporarily redirect all pages on a site to one -particular page, use the following:</p> - -<blockquote><code> -RedirectMatch temp .* http://www.example.com/startpage.html -</code></blockquote> - -<h2><a name="rewrite">Rewriting Engine</a></h2> - -<p>When even more powerful substitution is required, the rewriting -engine provided by <a href="mod/mod_rewrite.html">mod_rewrite</a> can -be useful. The directives provided by this module 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 <a href="misc/rewriteguide.html">URL -Rewriting Guide</a>.</p> - -<h2><a name="notfound">File Not Found</a></h2> - -<p>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 <a href="#redirect">URL -redirection</a> 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.</p> - -<p>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 <a href="mod/mod_speling.html">mod_speling</a> -(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.</p> - -<p>An especially useful feature of mod_speling, is that it will -compare filenames without respect to case. This can help systems -where users are unaware of the case-sensitive nature of URLs and the -unix filesystem. But using mod_speling for anything more than the -occasional URL correction can place additional load on the server, -since each "incorrect" request is followed by a URL redirection and a -new request from the client.</p> - -<p>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 <a -href="mod/core.html#errordocument">ErrorDocument</a> directive and can -be customized in a flexible manner as discussed in the <a -href="custom-error.html">Custom error responses</a> and <a -href="misc/custom_errordocs.html">International Server Error -Responses</a> documents.</p> - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/docs/manual/vhosts/fd-limits.html.en b/docs/manual/vhosts/fd-limits.html.en deleted file mode 100644 index 6b9d0f93c4..0000000000 --- a/docs/manual/vhosts/fd-limits.html.en +++ /dev/null @@ -1,59 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Apache Server Virtual Host Support</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<H1 ALIGN="CENTER">File Descriptor Limits</H1> - -<P> -When using a large number of Virtual Hosts, Apache may run out of available -file descriptors (sometimes called <CITE>file handles</CITE> 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. -<P> -Although Apache attempts to increase the limit as required, this -may not work if: -<OL> -<LI>Your system does not provide the setrlimit() system call. -<LI>The setrlimit(RLIMIT_NOFILE) call does not function on your system - (such as Solaris 2.3) -<LI>The number of file descriptors required exceeds the hard limit. -<LI>Your system imposes other limits on file descriptors, such as a limit -on stdio streams only using file descriptors below 256. (Solaris 2) -</OL> - -In the event of problems you can: -<UL> -<LI>Reduce the number of log files; don't specify log files in the VirtualHost -sections, but only log to the main log files. -<LI>If you system falls into 1 or 2 (above), then increase the file descriptor -limit before starting Apache, using a script like -<BLOCKQUOTE><CODE> -#!/bin/sh <BR> -ulimit -S -n 100 <BR> -exec httpd</CODE></BLOCKQUOTE> -</UL> -<P> -Please see the -<A HREF="../misc/descriptors.html">Descriptors and Apache</A> -document containing further details about file descriptor problems and how -they can be solved on your operating system. -</P> - -<!--#include virtual="footer.html" --> -</BODY></HTML> - diff --git a/docs/manual/vhosts/index.html.en b/docs/manual/vhosts/index.html.en deleted file mode 100644 index bb4a0f8931..0000000000 --- a/docs/manual/vhosts/index.html.en +++ /dev/null @@ -1,65 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML> -<HEAD> -<TITLE>Apache Virtual Host documentation</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<H1 ALIGN="CENTER">Apache Virtual Host documentation</H1> - -<P>The term <CITE>Virtual Host</CITE> 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 -<SAMP>www.company1.com</SAMP> and <SAMP>www.company2.com</SAMP>, -without requiring the user to know any extra path information.</P> - -<P>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.</P> - -<P>Below is a list of documentation pages which explain all details -of virtual host support in Apache version 1.3 and later.</P> - -<HR> - -<H2>Virtual Host Support</H2> - -<UL> -<LI><A HREF="name-based.html">Name-based Virtual Hosts</A> -<LI><A HREF="ip-based.html">IP-based Virtual Hosts</A> -<LI><A HREF="examples.html">Virtual Host examples for common setups</A> -<LI><A HREF="details.html">In-Depth Discussion of Virtual Host Matching</A> -<LI><A HREF="fd-limits.html">File Descriptor Limits</A> -<LI><A HREF="mass.html">Dynamically Configured Mass Virtual Hosting</A> -</UL> - -<H2>Configuration directives</H2> - -<UL> -<LI><A HREF="../mod/core.html#virtualhost"><VirtualHost></A> -<LI><A HREF="../mod/core.html#namevirtualhost">NameVirtualHost</A> -<LI><A HREF="../mod/core.html#servername">ServerName</A> -<LI><A HREF="../mod/core.html#serveralias">ServerAlias</A> -<LI><A HREF="../mod/core.html#serverpath">ServerPath</A> -</UL> - -<P>Folks trying to debug their virtual host configuration may find the -Apache <CODE>-S</CODE> 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. - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/docs/manual/vhosts/name-based.html.en b/docs/manual/vhosts/name-based.html.en deleted file mode 100644 index 1d834f2989..0000000000 --- a/docs/manual/vhosts/name-based.html.en +++ /dev/null @@ -1,169 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML><HEAD> -<TITLE>Apache name-based Virtual Hosts</TITLE> -</HEAD> - -<!-- Background white, links blue (unvisited), navy (visited), red (active) --> -<BODY - BGCOLOR="#FFFFFF" - TEXT="#000000" - LINK="#0000FF" - VLINK="#000080" - ALINK="#FF0000" -> -<!--#include virtual="header.html" --> -<H1 ALIGN="CENTER">Apache name-based Virtual Host Support</H1> - -<STRONG>See Also:</STRONG> -<A HREF="ip-based.html">IP-based Virtual Host Support</A> - -<HR> - -<H2>Name-based vs. IP-based virtual hosts</H2> - -<P>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).</P> - -<P>The <CODE>HTTP/1.1</CODE> protocol, and a common extension to -<CODE>HTTP/1.0</CODE>, 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.</P> - -<P>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.</P> - -<H2>Using name-based virtual hosts</H2> - -<P>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 -<A HREF="../mod/core.html#namevirtualhost"><CODE>NameVirtualHost</CODE></A> -directive which specifies an IP address that should be used as a -target for name-based virtual hosts, or the wildcard <CODE>*</CODE> to -indicate that the server only does name-based virtual hosting (no -IP-based virtual hosting).</P> - -<P>For example, suppose that both <SAMP>www.domain.tld</SAMP> and -<SAMP>www.otherdomain.tld</SAMP> point at the IP address of your -server. Then you simply add to one of the Apache configuration files -(most likely <CODE>httpd.conf</CODE> or <CODE>srm.conf</CODE>) code -similar to the following:</P> - -<PRE> - NameVirtualHost * - - <VirtualHost *> - ServerName www.domain.tld - DocumentRoot /www/domain - </VirtualHost> - - <VirtualHost *> - ServerName www.otherdomain.tld - DocumentRoot /www/otherdomain - </VirtualHost> -</PRE> - -<P>Of course, any additional directives can (and should) be placed -into the <CODE><VirtualHost></CODE> section. To make this work, -all that is needed is to make sure that the names -<SAMP>www.domain.tld</SAMP> and <SAMP>www.otherdomain.tld</SAMP> -are pointing to the right IP address. - -<P>Note: When you specify an IP address in a <CODE>NameVirtualHost</CODE> -directive then requests to that IP address will only ever be served -by matching <VirtualHost>s. The "main server" will -<STRONG>never</STRONG> 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 -<EM>every</EM> server (hostname) you want to maintain on your server. - -<P>Additionally, many servers may wish to be accessible by more than -one name. For example, the example server might want to be accessible -as <CODE>domain.tld</CODE>, or <CODE>www2.domain.tld</CODE>, assuming -the IP addresses pointed to the same server. In fact, one might want it -so that all addresses at <CODE>domain.tld</CODE> were picked up by the -server. This is possible with the -<A HREF="../mod/core.html#serveralias"><CODE>ServerAlias</CODE></A> -directive, placed inside the <VirtualHost> section. For -example:</P> - -<PRE> - ServerAlias domain.tld *.domain.tld -</PRE> - -<P>Note that you can use <CODE>*</CODE> and <CODE>?</CODE> as wild-card -characters.</P> - -<P>You also might need <CODE>ServerAlias</CODE> 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 -<CODE>ServerAlias www www.foobar</CODE>. 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 <CODE>ServerAlias</CODE> directive is generally a way to have different -hostnames pointing to the same virtual host. -</P> - -<H2>Compatibility with Older Browsers</H2> - -<P>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 -<CITE>primary</CITE> name-based virtual host).</P> - -<P>There is a possible workaround with the -<A HREF="../mod/core.html#serverpath"><CODE>ServerPath</CODE></A> -directive, albeit a slightly cumbersome one:</P> - -<P>Example configuration: - -<PRE> - NameVirtualHost 111.22.33.44 - - <VirtualHost 111.22.33.44> - ServerName www.domain.tld - ServerPath /domain - DocumentRoot /web/domain - </VirtualHost> -</PRE> - -<P>What does this mean? It means that a request for any URI beginning -with "<SAMP>/domain</SAMP>" will be served from the virtual host -<SAMP>www.domain.tld</SAMP> This means that the pages can be accessed as -<CODE>http://www.domain.tld/domain/</CODE> for all clients, although -clients sending a <SAMP>Host:</SAMP> header can also access it as -<CODE>http://www.domain.tld/</CODE>.</P> - -<P>In order to make this work, put a link on your primary virtual host's page -to <SAMP>http://www.domain.tld/domain/</SAMP> -Then, in the virtual host's pages, be sure to use either purely -relative links (<EM>e.g.</EM>, "<SAMP>file.html</SAMP>" or -"<SAMP>../icons/image.gif</SAMP>" or links containing the prefacing -<SAMP>/domain/</SAMP> -(<EM>e.g.</EM>, "<SAMP>http://www.domain.tld/domain/misc/file.html</SAMP>" or -"<SAMP>/domain/misc/file.html</SAMP>").</P> - -<P>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.</P> - -<P>See also: <A HREF="examples.html#serverpath">ServerPath configuration -example</A></P> - -<!--#include virtual="footer.html" --> -</BODY> -</HTML> diff --git a/modules/proxy/.cvsignore b/modules/proxy/.cvsignore deleted file mode 100644 index ba6a3f02e0..0000000000 --- a/modules/proxy/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -Debug -Release -Makefile -*.lo -*.plg -*.slo -*.la -*.so -modules.mk -.deps -.libs diff --git a/modules/proxy/.indent.pro b/modules/proxy/.indent.pro deleted file mode 100644 index 20c2d83371..0000000000 --- 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 e5b3df5e3d..0000000000 --- a/modules/proxy/CHANGES +++ /dev/null @@ -1,197 +0,0 @@ -mod_proxy changes for httpd 2.0.25-dev - - *) Split proxy: space using <Proxy[Match] > directive blocks from - the <Directory[Match] > and <Files[Match] > blocks. Mod_proxy - now bypasses the directory and files testing phase (and skips - the http TRACE default handler on it's own, as well). Note that - <Location > blocks continue to be processed for proxy: requests. - [William Rowe <wrowe@covalent.net>] - - *) apr_uri type/function namespace changes in apr_uri functions - [Doug MacEachern <dougm@covalent.net>] - -mod_proxy changes for httpd 2.0.23-dev - - *) break the proxy_http_handler into multiple smaller functions. - [John Barbee <barbee@veribox.net>] - - *) Fix the proxy when the origin server sends back a 100 - Continue response. [John Barbee <barbee@veribox.net>] - - *) Change 'readbytes' from apr_size_t to apr_off_t due to change - in ap_get_brigade's parameters [John Barbee <barbee@veribox.net>] - -mod_proxy changes for httpd 2.0.20-dev - *) Timeout added for backend connections. - [Victor Orlikowski <v.j.orlikowski@gte.net>] - - *) Fix abort code path in proxy_http.c, similar to FTP fix. - [Chuck Murcko <chuck@topsail.org>] - - *) Fix FTP ABOR command execution path. - [Victor Orlikowski <v.j.orlikowski@gte.net>] - - *) FTP return code variable cleanup; fixed problem in login - [Chuck Murcko <chuck@topsail.org>] - - *) Get PORT working again in the ftp proxy. - [Victor Orlikowski <v.j.orlikowski@gte.net>] - - *) Return result code check for FTP QUIT, after fixing - problems with passive connection handling. - [Victor Orlikowski <v.j.orlikowski@gte.net>] - - *) Reorganize ap_proxy_string_read() internally to not process eos - buckets. - [Chuck Murcko <chuck@topsail.org>] - [Victor Orlikowski <v.j.orlikowski@gte.net>] - - *) Remove result code check for FTP QUIT command. Some servers send - nothing at all back in response to QUIT. - [Chuck Murcko <chuck@topsail.org>] - [Victor Orlikowski <v.j.orlikowski@gte.net>] - -mod_proxy changes for httpd 2.0.19 - - *) Reverse previous patch since the core reverted. - [Chuck Murcko <chuck@topsail.org>] - - *) Remove indirection on number of bytes to read for input filters. - [Chuck Murcko <chuck@topsail.org>] - - *) Fixed a problem with directory listing corruption in the - PROXY_DIR filter. - [Graham Leggett <minfrin@sharp.fm>] - - *) mod_proxy and the proxy submodules now build properly as DSOs. - [Graham Leggett <minfrin@sharp.fm>] - - *) Stopped the HTTP proxy from trying to read entity bodies when there - wasn't one (response was 1xx, 204, 205 or 304). - [Graham Leggett <minfrin@sharp.fm>] - - *) Made sure dates were canonicalised correctly when passed to the client - browser through the HTTP proxy. - [Graham Leggett <minfrin@sharp.fm>] - - *) Split each individual proxy protocol into separate modules. - [Graham Leggett <minfrin@sharp.fm>] - - *) Added Max-Forwards support for all request types so as to prevent - loops. - [Graham Leggett <minfrin@sharp.fm>] - - *) Fix warnings about byte count type on Darwin (connect handler). - [Chuck Murcko <chuck@topsail.org>] - -mod_proxy changes for httpd 2.0.18 - - *) IPV6 EPSV support for IPV6 in FTP proxy. - [Graham Leggett <minfrin@sharp.fm>] - - *) FTP directory filter works now. - [Graham Leggett <minfrin@sharp.fm>] - - *) Fixed some thread-safety issues with the HTTP proxy in mod_proxy. - [Graham Leggett <minfrin@sharp.fm>] - - *) PASV FTP works now. - [Graham Leggett <minfrin@sharp.fm>] - - *) Reworked the line-at-a-time read from the control connection to - workaround a stray empty bucket returned by the HTTP_IN filter. - [Graham Leggett <minfrin@sharp.fm>] - - *) Stopped the CORE filter from sending off an HTTP response when a - CONNECT tunnel was closed. - [Graham Leggett <minfrin@sharp.fm>] - - *) Fixed the poll() loop in proxy_connect.c -> it works now!!! - [Graham Leggett <minfrin@sharp.fm>] - - *) Converted send_dir() to ap_proxy_send_dir_filter() in proxy_ftp.c. - [Graham Leggett <minfrin@sharp.fm>] - -mod_proxy changes for httpd 2.0.17 - - *) Major rework of ap_proxy_ftp_handler() to use filters (begone foul - BUFF!!!). It compiles, but is untested, and the build environment needs - to be fixed to include proxy_ftp.c. - [Graham Leggett <minfrin@sharp.fm>] - - *) Cleanup of dead functions within proxy_util.c. - [Graham Leggett <minfrin@sharp.fm>] - - *) Reworked the storage of the client socket between keepalive connections - to fix some nasty problems with the socket lasting longer than the - memory pool it was allocated from. - [Graham Leggett <minfrin@sharp.fm>] - - *) Fixed bug where a hostname without a "." in it (such as "localhost") - would not trigger an IP address check with ProxyBlock. - [Graham Leggett <minfrin@sharp.fm>] - -mod_proxy changes for httpd 2.0.16 - - *) Fixed ProxyBlock bugs with ap_proxy_http_handler() and - ap_proxy_connect_handler(). - [Graham Leggett <minfrin@sharp.fm>] - - *) Updated ap_proxy_connect_handler() to support APR, while - moving some common code between http_handler and connect_handler - to proxy_util.c. - [Graham Leggett <minfrin@sharp.fm>] - - *) Updated mod_proxy.html docs to include v2.0 configuration. - [Graham Leggett <minfrin@sharp.fm>] - - *) Fixed problem where responses without entity bodies would cause - the directly following proxy keepalive request to fail. - [Graham Leggett <minfrin@sharp.fm>] - -mod_proxy changes for httpd 2.0.15 - - *) Added support for downstream keepalives in mod_proxy. - [Graham Leggett <minfrin@sharp.fm>] - - *) Changed mod_proxy ap_proxy_http_handler() to support APR properly. - [Graham Leggett <minfrin@sharp.fm>] - - *) Fix problem where incoming response headers were not being returned - to the client in mod_proxy. - [Graham Leggett <minfrin@sharp.fm>] - - *) Added X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Server to - reverse proxied request headers in mod_proxy. - [Graham Leggett <minfrin@sharp.fm>] - - *) replace INADDR_NONE with APR_INADDR_NONE [Ian Holsman <IanH@cnet.com>] - - *) Fix problem with proxy configuration where globally set - configuration options were overridden inside virtual hosts. - [Graham Leggett <minfrin@sharp.fm>] - - *) Fix ProxyReceiveBufferSize where default value was left - uninitialised. - [Graham Leggett <minfrin@sharp.fm>] - - *) Some small changes: - - Ensured hop-by-hop headers were stripped as per - RFC2616 13.5.1. - - Upgraded version code to HTTP/1.1. - - Added Connection: close until Keepalives come. - - Some cosmetic fixes and commenting. - [Graham Leggett <minfrin@sharp.fm>] - -mod_proxy changes for httpd 2.0.14 - - *) removed ProxyNoCache and ProxyCacheForceCompletion config directives, - since we no longer directly cache from this module - [Chuck Murcko <chuck@topsail.org>] - - *) removed cache - [Chuck Murcko <chuck@topsail.org>] - - *) initial rerebuild for 2.0 - [Chuck Murcko <chuck@topsail.org>] - diff --git a/modules/proxy/Makefile.in b/modules/proxy/Makefile.in deleted file mode 100644 index 7c5c149d85..0000000000 --- a/modules/proxy/Makefile.in +++ /dev/null @@ -1,3 +0,0 @@ -# a modules Makefile has no explicit targets -- they will be defined by -# whatever modules are enabled. just grab special.mk to deal with this. -include $(top_srcdir)/build/special.mk diff --git a/modules/proxy/config.m4 b/modules/proxy/config.m4 deleted file mode 100644 index bda91ac106..0000000000 --- a/modules/proxy/config.m4 +++ /dev/null @@ -1,24 +0,0 @@ -dnl modules enabled in this directory by default - -APACHE_MODPATH_INIT(proxy) - -if test "$enable_proxy" = "shared"; then - proxy_mods_enable=shared -elif test "$enable_proxy" = "yes"; then - proxy_mods_enable=yes -else - proxy_mods_enable=no -fi - -proxy_objs="mod_proxy.lo proxy_util.lo" -APACHE_MODULE(proxy, Apache proxy module, $proxy_objs, , $proxy_mods_enable) - -proxy_connect_objs="$proxy_objs proxy_connect.lo" -APACHE_MODULE(proxy_connect, Apache proxy CONNECT module, $proxy_connect_objs, , $proxy_mods_enable) -proxy_ftp_objs="$proxy_objs proxy_ftp.lo" -APACHE_MODULE(proxy_ftp, Apache proxy FTP module, $proxy_ftp_objs, , $proxy_mods_enable) -proxy_http_objs="$proxy_objs proxy_http.lo" -APACHE_MODULE(proxy_http, Apache proxy HTTP module, $proxy_http_objs, , $proxy_mods_enable) - - -APACHE_MODPATH_FINISH diff --git a/modules/proxy/libproxy.exp b/modules/proxy/libproxy.exp deleted file mode 100644 index a20f2378f5..0000000000 --- a/modules/proxy/libproxy.exp +++ /dev/null @@ -1 +0,0 @@ -proxy_module diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c deleted file mode 100644 index 40f128c931..0000000000 --- a/modules/proxy/mod_proxy.c +++ /dev/null @@ -1,974 +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 - * <http://www.apache.org/>. - * - * Portions of this software are based upon public domain software - * originally written at the National Center for Supercomputing Applications, - * University of Illinois, Urbana-Champaign. - */ - -#define CORE_PRIVATE - -#include "mod_proxy.h" - -extern module AP_MODULE_DECLARE_DATA proxy_module; - - -/* - * A Web proxy module. Stages: - * - * translate_name: set filename to proxy:<URL> - * map_to_storage: run proxy_walk (rather than directory_walk/file_walk) - * can't trust directory_walk/file_walk since these are - * not in our filesystem. Prevents mod_http from serving - * the TRACE request we will set aside to handle later. - * type_checker: set type to PROXY_MAGIC_TYPE if filename begins proxy: - * fix_ups: convert the URL stored in the filename to the - * canonical form. - * handler: handle proxy requests - */ - -/* -------------------------------------------------------------- */ -/* Translate the URL into a 'filename' */ - -static int alias_match(const char *uri, const char *alias_fakename) -{ - const char *end_fakename = alias_fakename + strlen(alias_fakename); - const char *aliasp = alias_fakename, *urip = uri; - - while (aliasp < end_fakename) { - if (*aliasp == '/') { - /* any number of '/' in the alias matches any number in - * the supplied URI, but there must be at least one... - */ - if (*urip != '/') - return 0; - - while (*aliasp == '/') - ++aliasp; - while (*urip == '/') - ++urip; - } - else { - /* Other characters are compared literally */ - if (*urip++ != *aliasp++) - return 0; - } - } - - /* Check last alias path component matched all the way */ - - if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/') - return 0; - - /* Return number of characters from URI which matched (may be - * greater than length of alias, since we may have matched - * doubled slashes) - */ - - return urip - uri; -} - -/* Detect if an absoluteURI should be proxied or not. Note that we - * have to do this during this phase because later phases are - * "short-circuiting"... i.e. translate_names will end when the first - * module returns OK. So for example, if the request is something like: - * - * GET http://othervhost/cgi-bin/printenv HTTP/1.0 - * - * mod_alias will notice the /cgi-bin part and ScriptAlias it and - * short-circuit the proxy... just because of the ordering in the - * configuration file. - */ -static int proxy_detect(request_rec *r) -{ - void *sconf = r->server->module_config; - proxy_server_conf *conf; - - conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); - - if (conf->req && r->parsed_uri.scheme) { - /* but it might be something vhosted */ - if (!(r->parsed_uri.hostname - && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r)) - && ap_matches_request_vhost(r, r->parsed_uri.hostname, - r->parsed_uri.port_str ? r->parsed_uri.port : ap_default_port(r)))) { - r->proxyreq = PROXYREQ_PROXY; - r->uri = r->unparsed_uri; - r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL); - r->handler = "proxy-server"; - } - } - /* We need special treatment for CONNECT proxying: it has no scheme part */ - else if (conf->req && r->method_number == M_CONNECT - && r->parsed_uri.hostname - && r->parsed_uri.port_str) { - r->proxyreq = PROXYREQ_PROXY; - r->uri = r->unparsed_uri; - r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL); - r->handler = "proxy-server"; - } - return DECLINED; -} - -static int proxy_trans(request_rec *r) -{ - void *sconf = r->server->module_config; - proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); - int i, len; - struct proxy_alias *ent = (struct proxy_alias *) conf->aliases->elts; - - if (r->proxyreq) { - /* someone has already set up the proxy, it was possibly ourselves - * in proxy_detect - */ - return OK; - } - - /* XXX: since r->uri has been manipulated already we're not really - * compliant with RFC1945 at this point. But this probably isn't - * an issue because this is a hybrid proxy/origin server. - */ - - for (i = 0; i < conf->aliases->nelts; i++) { - len = alias_match(r->uri, ent[i].fake); - - if (len > 0) { - r->filename = apr_pstrcat(r->pool, "proxy:", ent[i].real, - (r->uri + len - 1), NULL); - r->handler = "proxy-server"; - r->proxyreq = PROXYREQ_REVERSE; - return OK; - } - } - return DECLINED; -} - -static int proxy_walk(request_rec *r) -{ - proxy_server_conf *sconf = ap_get_module_config(r->server->module_config, - &proxy_module); - ap_conf_vector_t *per_dir_defaults = r->server->lookup_defaults; - ap_conf_vector_t **sec_proxy = (ap_conf_vector_t **) sconf->sec_proxy->elts; - ap_conf_vector_t *entry_config; - proxy_dir_conf *entry_proxy; - int num_sec = sconf->sec_proxy->nelts; - /* XXX: shouldn't we use URI here? Canonicalize it first? - * Pass over "proxy:" prefix - */ - const char *proxyname = r->filename + 6; - int j; - - for (j = 0; j < num_sec; ++j) - { - entry_config = sec_proxy[j]; - entry_proxy = ap_get_module_config(entry_config, &proxy_module); - - /* XXX: What about case insensitive matching ??? - * Compare regex, fnmatch or string as appropriate - * If the entry doesn't relate, then continue - */ - if (entry_proxy->r - ? ap_regexec(entry_proxy->r, proxyname, 0, NULL, 0) - : (entry_proxy->p_is_fnmatch - ? apr_fnmatch(entry_proxy->p, proxyname, 0) - : strncmp(proxyname, entry_proxy->p, - strlen(entry_proxy->p)))) { - continue; - } - per_dir_defaults = ap_merge_per_dir_configs(r->pool, per_dir_defaults, - entry_config); - } - - r->per_dir_config = per_dir_defaults; - - return OK; -} - -static int proxy_map_location(request_rec *r) -{ - int access_status; - - if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0) - return DECLINED; - - /* Don't let the core or mod_http map_to_storage hooks handle this, - * We don't need directory/file_walk, and we want to TRACE on our own. - */ - if ((access_status = proxy_walk(r))) { - ap_die(access_status, r); - return access_status; - } - - return OK; -} - -/* -------------------------------------------------------------- */ -/* Fixup the filename */ - -/* - * Canonicalise the URL - */ -static int proxy_fixup(request_rec *r) -{ - char *url, *p; - int access_status; - - if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0) - return DECLINED; - - /* XXX: Shouldn't we try this before we run the proxy_walk? */ - url = &r->filename[6]; - - /* canonicalise each specific scheme */ - if ((access_status = proxy_run_canon_handler(r, url))) { - return access_status; - } - - p = strchr(url, ':'); - if (p == NULL || p == url) - return HTTP_BAD_REQUEST; - - return OK; /* otherwise; we've done the best we can */ -} - -/* Send a redirection if the request contains a hostname which is not */ -/* fully qualified, i.e. doesn't have a domain name appended. Some proxy */ -/* servers like Netscape's allow this and access hosts from the local */ -/* domain in this case. I think it is better to redirect to a FQDN, since */ -/* these will later be found in the bookmarks files. */ -/* The "ProxyDomain" directive determines what domain will be appended */ -static int proxy_needsdomain(request_rec *r, const char *url, const char *domain) -{ - char *nuri; - const char *ref; - - /* We only want to worry about GETs */ - if (!r->proxyreq || r->method_number != M_GET || !r->parsed_uri.hostname) - return DECLINED; - - /* If host does contain a dot already, or it is "localhost", decline */ - if (strchr(r->parsed_uri.hostname, '.') != NULL - || strcasecmp(r->parsed_uri.hostname, "localhost") == 0) - return DECLINED; /* host name has a dot already */ - - ref = apr_table_get(r->headers_in, "Referer"); - - /* Reassemble the request, but insert the domain after the host name */ - /* Note that the domain name always starts with a dot */ - r->parsed_uri.hostname = apr_pstrcat(r->pool, r->parsed_uri.hostname, - domain, NULL); - nuri = apr_uri_unparse(r->pool, - &r->parsed_uri, - APR_URI_UNP_REVEALPASSWORD); - - apr_table_set(r->headers_out, "Location", nuri); - ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, - "Domain missing: %s sent to %s%s%s", r->uri, - apr_uri_unparse(r->pool, &r->parsed_uri, - APR_URI_UNP_OMITUSERINFO), - ref ? " from " : "", ref ? ref : ""); - - return HTTP_MOVED_PERMANENTLY; -} - -/* -------------------------------------------------------------- */ -/* Invoke handler */ - -static int proxy_handler(request_rec *r) -{ - char *url, *scheme, *p; - const char *p2; - void *sconf = r->server->module_config; - proxy_server_conf *conf = (proxy_server_conf *) - ap_get_module_config(sconf, &proxy_module); - apr_array_header_t *proxies = conf->proxies; - struct proxy_remote *ents = (struct proxy_remote *) proxies->elts; - int i, rc, access_status; - int direct_connect = 0; - const char *str; - long maxfwd; - - /* is this for us? */ - if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0) - return DECLINED; - - /* handle max-forwards / OPTIONS / TRACE */ - if ((str = apr_table_get(r->headers_in, "Max-Forwards"))) { - maxfwd = strtol(str, NULL, 10); - if (maxfwd < 1) { - switch (r->method_number) { - case M_TRACE: { - int access_status; - r->proxyreq = PROXYREQ_NONE; - if ((access_status = ap_send_http_trace(r))) - ap_die(access_status, r); - else - ap_finalize_request_protocol(r); - return OK; - } - case M_OPTIONS: { - int access_status; - r->proxyreq = PROXYREQ_NONE; - if ((access_status = ap_send_http_options(r))) - ap_die(access_status, r); - else - ap_finalize_request_protocol(r); - return OK; - } - default: { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Max-Forwards has reached zero - proxy loop?"); - } - } - } - maxfwd = (maxfwd > 0) ? maxfwd - 1 : 0; - } - else { - /* set configured max-forwards */ - maxfwd = conf->maxfwd; - } - apr_table_setn(r->headers_in, "Max-Forwards", - apr_psprintf(r->pool, "%ld", (maxfwd > 0) ? maxfwd : 0)); - - if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) - return rc; - - url = r->filename + 6; - p = strchr(url, ':'); - if (p == NULL) - return HTTP_BAD_REQUEST; - - /* If the host doesn't have a domain name, add one and redirect. */ - if (conf->domain != NULL) { - rc = proxy_needsdomain(r, url, conf->domain); - if (ap_is_HTTP_REDIRECT(rc)) - return HTTP_MOVED_PERMANENTLY; - } - - *p = '\0'; - scheme = apr_pstrdup(r->pool, url); - *p = ':'; - - /* Check URI's destination host against NoProxy hosts */ - /* Bypass ProxyRemote server lookup if configured as NoProxy */ - /* we only know how to handle communication to a proxy via http */ - /*if (strcasecmp(scheme, "http") == 0) */ - { - int ii; - struct dirconn_entry *list = (struct dirconn_entry *) conf->dirconn->elts; - - for (direct_connect = ii = 0; ii < conf->dirconn->nelts && !direct_connect; ii++) { - direct_connect = list[ii].matcher(&list[ii], r); - } -#if DEBUGGING - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - (direct_connect) ? "NoProxy for %s" : "UseProxy for %s", - r->uri); -#endif - } - - /* firstly, try a proxy, unless a NoProxy directive is active */ - if (!direct_connect) { - for (i = 0; i < proxies->nelts; i++) { - p2 = ap_strchr_c(ents[i].scheme, ':'); /* is it a partial URL? */ - if (strcmp(ents[i].scheme, "*") == 0 || - (p2 == NULL && strcasecmp(scheme, ents[i].scheme) == 0) || - (p2 != NULL && - strncasecmp(url, ents[i].scheme, strlen(ents[i].scheme)) == 0)) { - - /* handle the scheme */ - ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, - "Trying to run scheme_handler against proxy"); - access_status = proxy_run_scheme_handler(r, conf, url, ents[i].hostname, ents[i].port); - - /* an error or success */ - if (access_status != DECLINED && access_status != HTTP_BAD_GATEWAY) { - return access_status; - } - /* we failed to talk to the upstream proxy */ - } - } - } - - /* otherwise, try it direct */ - /* N.B. what if we're behind a firewall, where we must use a proxy or - * give up?? - */ - - /* handle the scheme */ - ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, - "Trying to run scheme_handler"); - access_status = proxy_run_scheme_handler(r, conf, url, NULL, 0); - if (DECLINED == access_status) { - ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, - "Neither CONNECT, HTTP or FTP for %s", - r->uri); - return HTTP_FORBIDDEN; - } - return access_status; -} - -/* -------------------------------------------------------------- */ -/* Setup configurable data */ - -static void * create_proxy_config(apr_pool_t *p, server_rec *s) -{ - proxy_server_conf *ps = ap_pcalloc(p, sizeof(proxy_server_conf)); - - ps->sec_proxy = ap_make_array(p, 10, sizeof(ap_conf_vector_t *)); - ps->proxies = ap_make_array(p, 10, sizeof(struct proxy_remote)); - ps->aliases = ap_make_array(p, 10, sizeof(struct proxy_alias)); - ps->raliases = ap_make_array(p, 10, sizeof(struct proxy_alias)); - ps->noproxies = ap_make_array(p, 10, sizeof(struct noproxy_entry)); - ps->dirconn = ap_make_array(p, 10, sizeof(struct dirconn_entry)); - ps->allowed_connect_ports = ap_make_array(p, 10, sizeof(int)); - ps->domain = NULL; - ps->viaopt = via_off; /* initially backward compatible with 1.3.1 */ - ps->viaopt_set = 0; /* 0 means default */ - ps->req = 0; - ps->req_set = 0; - ps->recv_buffer_size = 0; /* this default was left unset for some reason */ - ps->recv_buffer_size_set = 0; - ps->maxfwd = DEFAULT_MAX_FORWARDS; - ps->maxfwd_set = 0; - - return ps; -} - -static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv) -{ - proxy_server_conf *ps = ap_pcalloc(p, sizeof(proxy_server_conf)); - proxy_server_conf *base = (proxy_server_conf *) basev; - proxy_server_conf *overrides = (proxy_server_conf *) overridesv; - - ps->proxies = apr_array_append(p, base->proxies, overrides->proxies); - ps->sec_proxy = apr_array_append(p, base->sec_proxy, overrides->sec_proxy); - ps->aliases = apr_array_append(p, base->aliases, overrides->aliases); - ps->raliases = apr_array_append(p, base->raliases, overrides->raliases); - ps->noproxies = apr_array_append(p, base->noproxies, overrides->noproxies); - ps->dirconn = apr_array_append(p, base->dirconn, overrides->dirconn); - ps->allowed_connect_ports = apr_array_append(p, base->allowed_connect_ports, overrides->allowed_connect_ports); - - ps->domain = (overrides->domain == NULL) ? base->domain : overrides->domain; - ps->viaopt = (overrides->viaopt_set == 0) ? base->viaopt : overrides->viaopt; - ps->req = (overrides->req_set == 0) ? base->req : overrides->req; - ps->recv_buffer_size = (overrides->recv_buffer_size_set == 0) ? base->recv_buffer_size : overrides->recv_buffer_size; - ps->maxfwd = (overrides->maxfwd_set == 0) ? base->maxfwd : overrides->maxfwd; - - return ps; -} - -static void *create_proxy_dir_config(apr_pool_t *p, char *dummy) -{ - proxy_dir_conf *new = - (proxy_dir_conf *) apr_pcalloc(p, sizeof(proxy_dir_conf)); - - /* Filled in by proxysection, when applicable */ - - return (void *) new; -} - -static void *merge_proxy_dir_config(apr_pool_t *p, void *basev, void *addv) -{ - proxy_dir_conf *new = (proxy_dir_conf *) apr_pcalloc(p, sizeof(proxy_dir_conf)); - proxy_dir_conf *add = (proxy_dir_conf *) addv; - - new->p = add->p; - new->p_is_fnmatch = add->p_is_fnmatch; - new->r = add->r; - return new; -} - - -static const char * - add_proxy(cmd_parms *cmd, void *dummy, const char *f1, const char *r1) -{ - server_rec *s = cmd->server; - proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module); - struct proxy_remote *new; - char *p, *q; - char *r, *f, *scheme; - int port; - - r = apr_pstrdup(cmd->pool, r1); - scheme = apr_pstrdup(cmd->pool, r1); - f = apr_pstrdup(cmd->pool, f1); - p = strchr(r, ':'); - if (p == NULL || p[1] != '/' || p[2] != '/' || p[3] == '\0') { - return "ProxyRemote: Bad syntax for a remote proxy server"; - } - else { - scheme[p-r] = 0; - } - q = strchr(p + 3, ':'); - if (q != NULL) { - if (sscanf(q + 1, "%u", &port) != 1 || port > 65535) - return "ProxyRemote: Bad syntax for a remote proxy server (bad port number)"; - *q = '\0'; - } - else - port = -1; - *p = '\0'; - if (strchr(f, ':') == NULL) - ap_str_tolower(f); /* lowercase scheme */ - ap_str_tolower(p + 3); /* lowercase hostname */ - - if (port == -1) { - port = apr_uri_default_port_for_scheme(scheme); - } - - new = apr_array_push(conf->proxies); - new->scheme = f; - new->protocol = r; - new->hostname = p + 3; - new->port = port; - return NULL; -} - -static const char * - add_pass(cmd_parms *cmd, void *dummy, const char *f, const char *r) -{ - server_rec *s = cmd->server; - proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module); - struct proxy_alias *new; - if (r!=NULL && cmd->path == NULL ) { - new = apr_array_push(conf->aliases); - new->fake = f; - new->real = r; - } else if (r==NULL && cmd->path != NULL) { - new = apr_array_push(conf->aliases); - new->fake = cmd->path; - new->real = f; - } else { - if ( r== NULL) - return "ProxyPass needs a path when not defined in a location"; - else - return "ProxyPass can not have a path when defined in a location"; - } - - return NULL; -} - -static const char * - add_pass_reverse(cmd_parms *cmd, void *dummy, const char *f, const char *r) -{ - server_rec *s = cmd->server; - proxy_server_conf *conf; - struct proxy_alias *new; - - conf = (proxy_server_conf *)ap_get_module_config(s->module_config, - &proxy_module); - if (r!=NULL && cmd->path == NULL ) { - new = apr_array_push(conf->raliases); - new->fake = f; - new->real = r; - } else if (r==NULL && cmd->path != NULL) { - new = apr_array_push(conf->raliases); - new->fake = cmd->path; - new->real = f; - } else { - if ( r == NULL) - return "ProxyPassReverse needs a path when not defined in a location"; - else - return "ProxyPassReverse can not have a path when defined in a location"; - } - - return NULL; -} - -static const char * - set_proxy_exclude(cmd_parms *parms, void *dummy, const char *arg) -{ - server_rec *s = parms->server; - proxy_server_conf *conf = - ap_get_module_config(s->module_config, &proxy_module); - struct noproxy_entry *new; - struct noproxy_entry *list = (struct noproxy_entry *) conf->noproxies->elts; - struct apr_sockaddr_t *addr; - int found = 0; - int i; - - /* Don't duplicate entries */ - for (i = 0; i < conf->noproxies->nelts; i++) { - if (apr_strnatcasecmp(arg, list[i].name) == 0) { /* ignore case for host names */ - found = 1; - } - } - - if (!found) { - new = apr_array_push(conf->noproxies); - new->name = arg; - if (APR_SUCCESS == apr_sockaddr_info_get(&addr, new->name, APR_UNSPEC, 0, 0, parms->pool)) { - new->addr = addr; - } - else { - new->addr = NULL; - } - } - return NULL; -} - -/* - * Set the ports CONNECT can use - */ -static const char * - set_allowed_ports(cmd_parms *parms, void *dummy, const char *arg) -{ - server_rec *s = parms->server; - proxy_server_conf *conf = - ap_get_module_config(s->module_config, &proxy_module); - int *New; - - if (!apr_isdigit(arg[0])) - return "AllowCONNECT: port number must be numeric"; - - New = apr_array_push(conf->allowed_connect_ports); - *New = atoi(arg); - return NULL; -} - -/* Similar to set_proxy_exclude(), but defining directly connected hosts, - * which should never be accessed via the configured ProxyRemote servers - */ -static const char * - set_proxy_dirconn(cmd_parms *parms, void *dummy, const char *arg) -{ - server_rec *s = parms->server; - proxy_server_conf *conf = - ap_get_module_config(s->module_config, &proxy_module); - struct dirconn_entry *New; - struct dirconn_entry *list = (struct dirconn_entry *) conf->dirconn->elts; - int found = 0; - int i; - - /* Don't duplicate entries */ - for (i = 0; i < conf->dirconn->nelts; i++) { - if (strcasecmp(arg, list[i].name) == 0) - found = 1; - } - - if (!found) { - New = apr_array_push(conf->dirconn); - New->name = apr_pstrdup(parms->pool, arg); - New->hostaddr = NULL; - - if (ap_proxy_is_ipaddr(New, parms->pool)) { -#if DEBUGGING - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "Parsed addr %s", inet_ntoa(New->addr)); - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "Parsed mask %s", inet_ntoa(New->mask)); -#endif - } - else if (ap_proxy_is_domainname(New, parms->pool)) { - ap_str_tolower(New->name); -#if DEBUGGING - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "Parsed domain %s", New->name); -#endif - } - else if (ap_proxy_is_hostname(New, parms->pool)) { - ap_str_tolower(New->name); -#if DEBUGGING - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "Parsed host %s", New->name); -#endif - } - else { - ap_proxy_is_word(New, parms->pool); -#if DEBUGGING - fprintf(stderr, "Parsed word %s\n", New->name); -#endif - } - } - return NULL; -} - -static const char * - set_proxy_domain(cmd_parms *parms, void *dummy, const char *arg) -{ - proxy_server_conf *psf = - ap_get_module_config(parms->server->module_config, &proxy_module); - - if (arg[0] != '.') - return "ProxyDomain: domain name must start with a dot."; - - psf->domain = arg; - return NULL; -} - -static const char * - set_proxy_req(cmd_parms *parms, void *dummy, int flag) -{ - proxy_server_conf *psf = - ap_get_module_config(parms->server->module_config, &proxy_module); - - psf->req = flag; - psf->req_set = 1; - return NULL; -} - -static const char * - set_recv_buffer_size(cmd_parms *parms, void *dummy, const char *arg) -{ - proxy_server_conf *psf = - ap_get_module_config(parms->server->module_config, &proxy_module); - int s = atoi(arg); - if (s < 512 && s != 0) { - return "ProxyReceiveBufferSize must be >= 512 bytes, or 0 for system default."; - } - - psf->recv_buffer_size = s; - psf->recv_buffer_size_set = 1; - return NULL; -} - -static const char * - set_max_forwards(cmd_parms *parms, void *dummy, const char *arg) -{ - proxy_server_conf *psf = - ap_get_module_config(parms->server->module_config, &proxy_module); - long s = atol(arg); - if (s < 0) { - return "ProxyMaxForwards must be greater or equal to zero.."; - } - - psf->maxfwd = s; - psf->maxfwd_set = 1; - return NULL; -} - -static const char* - set_via_opt(cmd_parms *parms, void *dummy, const char *arg) -{ - proxy_server_conf *psf = - ap_get_module_config(parms->server->module_config, &proxy_module); - - if (strcasecmp(arg, "Off") == 0) - psf->viaopt = via_off; - else if (strcasecmp(arg, "On") == 0) - psf->viaopt = via_on; - else if (strcasecmp(arg, "Block") == 0) - psf->viaopt = via_block; - else if (strcasecmp(arg, "Full") == 0) - psf->viaopt = via_full; - else { - return "ProxyVia must be one of: " - "off | on | full | block"; - } - - psf->viaopt_set = 1; - return NULL; -} - -static void ap_add_per_proxy_conf(server_rec *s, ap_conf_vector_t *dir_config) -{ - proxy_server_conf *sconf = ap_get_module_config(s->module_config, - &proxy_module); - void **new_space = (void **)apr_array_push(sconf->sec_proxy); - - *new_space = dir_config; -} - -static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg) -{ - const char *errmsg; - const char *endp = ap_strrchr_c(arg, '>'); - int old_overrides = cmd->override; - char *old_path = cmd->path; - proxy_dir_conf *conf; - ap_conf_vector_t *new_dir_conf = ap_create_per_dir_config(cmd->pool); - regex_t *r = NULL; - const command_rec *thiscmd = cmd->cmd; - - const char *err = ap_check_cmd_context(cmd, - NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT); - if (err != NULL) { - return err; - } - - if (endp == NULL) { - return apr_pstrcat(cmd->pool, cmd->cmd->name, - "> directive missing closing '>'", NULL); - } - - arg=apr_pstrndup(cmd->pool, arg, endp-arg); - - if (!arg) { - if (thiscmd->cmd_data) - return "<ProxyMatch > block must specify a path"; - else - return "<Proxy > block must specify a path"; - } - - cmd->path = ap_getword_conf(cmd->pool, &arg); - cmd->override = OR_ALL|ACCESS_CONF; - - if (strncasecmp(cmd->path, "proxy:", 6)) - cmd->path += 6; - - /* XXX Ignore case? What if we proxy a case-insenstive server?!? - * While we are at it, shouldn't we also canonicalize the entire - * scheme? See proxy_fixup() - */ - if (thiscmd->cmd_data) { /* <ProxyMatch> */ - r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED); - } - else if (!strcmp(cmd->path, "~")) { - cmd->path = ap_getword_conf(cmd->pool, &arg); - if (!cmd->path) - return "<Proxy ~ > block must specify a path"; - if (strncasecmp(cmd->path, "proxy:", 6)) - cmd->path += 6; - r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED); - } - - /* initialize our config and fetch it */ - conf = ap_set_config_vectors(cmd->server, new_dir_conf, cmd->path, - &proxy_module, cmd->pool); - - errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_dir_conf); - if (errmsg != NULL) - return errmsg; - - conf->r = r; - conf->p = cmd->path; - conf->p_is_fnmatch = apr_is_fnmatch(conf->p); - - ap_add_per_proxy_conf(cmd->server, new_dir_conf); - - if (*arg != '\0') { - return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name, - "> arguments not (yet) supported.", NULL); - } - - cmd->path = old_path; - cmd->override = old_overrides; - - return NULL; -} - -static const command_rec proxy_cmds[] = -{ - AP_INIT_RAW_ARGS("<Proxy", proxysection, NULL, RSRC_CONF, - "Container for directives affecting resources located in the proxied " - "location"), - AP_INIT_RAW_ARGS("<ProxyMatch", proxysection, (void*)1, RSRC_CONF, - "Container for directives affecting resources located in the proxied " - "location, in regular expression syntax"), - AP_INIT_FLAG("ProxyRequests", set_proxy_req, NULL, RSRC_CONF, - "on if the true proxy requests should be accepted"), - AP_INIT_TAKE2("ProxyRemote", add_proxy, NULL, RSRC_CONF, - "a scheme, partial URL or '*' and a proxy server"), - AP_INIT_TAKE12("ProxyPass", add_pass, NULL, RSRC_CONF|ACCESS_CONF, - "a virtual path and a URL"), - AP_INIT_TAKE12("ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF|ACCESS_CONF, - "a virtual path and a URL for reverse proxy behaviour"), - AP_INIT_ITERATE("ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF, - "A list of names, hosts or domains to which the proxy will not connect"), - AP_INIT_TAKE1("ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF, - "Receive buffer size for outgoing HTTP and FTP connections in bytes"), - AP_INIT_TAKE1("ProxyMaxForwards", set_max_forwards, NULL, RSRC_CONF, - "The maximum number of proxies a request may be forwarded through."), - AP_INIT_ITERATE("NoProxy", set_proxy_dirconn, NULL, RSRC_CONF, - "A list of domains, hosts, or subnets to which the proxy will connect directly"), - AP_INIT_TAKE1("ProxyDomain", set_proxy_domain, NULL, RSRC_CONF, - "The default intranet domain name (in absence of a domain in the URL)"), - AP_INIT_ITERATE("AllowCONNECT", set_allowed_ports, NULL, RSRC_CONF, - "A list of ports which CONNECT may connect to"), - AP_INIT_TAKE1("ProxyVia", set_via_opt, NULL, RSRC_CONF, - "Configure Via: proxy header header to one of: on | off | block | full"), - {NULL} -}; - -static void register_hooks(apr_pool_t *p) -{ - /* handler */ - ap_hook_handler(proxy_handler, NULL, NULL, APR_HOOK_FIRST); - /* filename-to-URI translation */ - ap_hook_translate_name(proxy_trans, NULL, NULL, APR_HOOK_FIRST); - /* walk <Proxy > entries and suppress default TRACE behavior */ - ap_hook_map_to_storage(proxy_map_location, NULL,NULL, APR_HOOK_FIRST); - /* fixups */ - ap_hook_fixups(proxy_fixup, NULL, NULL, APR_HOOK_FIRST); - /* post read_request handling */ - ap_hook_post_read_request(proxy_detect, NULL, NULL, APR_HOOK_FIRST); -} - -module AP_MODULE_DECLARE_DATA proxy_module = -{ - STANDARD20_MODULE_STUFF, - create_proxy_dir_config, /* create per-directory config structure */ - merge_proxy_dir_config, /* merge per-directory config structures */ - create_proxy_config, /* create per-server config structure */ - merge_proxy_config, /* merge per-server config structures */ - proxy_cmds, /* command table */ - register_hooks -}; - -APR_HOOK_STRUCT( - APR_HOOK_LINK(scheme_handler) - APR_HOOK_LINK(canon_handler) -) - -APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, scheme_handler, - (request_rec *r, proxy_server_conf *conf, - char *url, const char *proxyhost, - apr_port_t proxyport),(r,conf,url, - proxyhost,proxyport),DECLINED) -APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, canon_handler, - (request_rec *r, char *url),(r, - url),DECLINED) diff --git a/modules/proxy/mod_proxy.dsp b/modules/proxy/mod_proxy.dsp deleted file mode 100644 index ac33854522..0000000000 --- a/modules/proxy/mod_proxy.dsp +++ /dev/null @@ -1,111 +0,0 @@ -# Microsoft Developer Studio Project File - Name="mod_proxy" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=mod_proxy - 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 "mod_proxy.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 "mod_proxy.mak" CFG="mod_proxy - Win32 Release" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "mod_proxy - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "mod_proxy - 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)" == "mod_proxy - 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" /D "PROXY_DECLARE_EXPORT" /Fd"Release\mod_proxy" /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/mod_proxy.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy -# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /machine:I386 /out:"Release/mod_proxy.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy - -!ELSEIF "$(CFG)" == "mod_proxy - 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" /D "PROXY_DECLARE_EXPORT" /Fd"Debug\mod_proxy" /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/mod_proxy.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy -# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"Debug/mod_proxy.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy - -!ENDIF - -# Begin Target - -# Name "mod_proxy - Win32 Release" -# Name "mod_proxy - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" -# Begin Source File - -SOURCE=.\mod_proxy.c -# End Source File -# Begin Source File - -SOURCE=.\proxy_util.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" -# Begin Source File - -SOURCE=.\mod_proxy.h -# End Source File -# End Group -# End Target -# End Project diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h deleted file mode 100644 index df81a0ad1d..0000000000 --- a/modules/proxy/mod_proxy.h +++ /dev/null @@ -1,255 +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 - * <http://www.apache.org/>. - * - * 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 MOD_PROXY_H -#define MOD_PROXY_H - -/* - * Main include file for the Apache proxy - */ - -/* - - Also note numerous FIXMEs and CHECKMEs which should be eliminated. - - This code is once again experimental! - - Things to do: - - 1. Make it completely work (for FTP too) - - 2. HTTP/1.1 - - Chuck Murcko <chuck@topsail.org> 02-06-01 - - */ - -#define CORE_PRIVATE - -#include "apr_hooks.h" -#include "apr.h" -#include "apr_compat.h" -#include "apr_lib.h" -#include "apr_strings.h" -#include "apr_buckets.h" -#include "apr_md5.h" -#include "apr_network_io.h" -#include "apr_pools.h" -#include "apr_strings.h" -#include "apr_uri.h" -#include "apr_date.h" -#include "apr_fnmatch.h" - -#include "httpd.h" -#include "http_config.h" -#include "ap_config.h" -#include "http_core.h" -#include "http_protocol.h" -#include "http_request.h" -#include "http_vhost.h" -#include "http_main.h" -#include "http_log.h" -#include "http_connection.h" -#include "util_filter.h" -#include "mod_core.h" - - -#if APR_HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#if APR_HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif - -/* for proxy_canonenc() */ -enum enctype { - enc_path, enc_search, enc_user, enc_fpath, enc_parm -}; - -#if APR_CHARSET_EBCDIC -#define CRLF "\r\n" -#else /*APR_CHARSET_EBCDIC*/ -#define CRLF "\015\012" -#endif /*APR_CHARSET_EBCDIC*/ - -/* default Max-Forwards header setting */ -#define DEFAULT_MAX_FORWARDS 10 - -/* static information about a remote proxy */ -struct proxy_remote { - const char *scheme; /* the schemes handled by this proxy, or '*' */ - const char *protocol; /* the scheme used to talk to this proxy */ - const char *hostname; /* the hostname of this proxy */ - int port; /* the port for this proxy */ -}; - -struct proxy_alias { - const char *real; - const char *fake; -}; - -struct dirconn_entry { - char *name; - struct in_addr addr, mask; - struct apr_sockaddr_t *hostaddr; - int (*matcher) (struct dirconn_entry * This, request_rec *r); -}; - -struct noproxy_entry { - const char *name; - struct apr_sockaddr_t *addr; -}; - -typedef struct { - apr_array_header_t *proxies; - apr_array_header_t *sec_proxy; - apr_array_header_t *aliases; - apr_array_header_t *raliases; - apr_array_header_t *noproxies; - apr_array_header_t *dirconn; - apr_array_header_t *allowed_connect_ports; - const char *domain; /* domain name to use in absence of a domain name in the request */ - int req; /* true if proxy requests are enabled */ - char req_set; - enum { - via_off, - via_on, - via_block, - via_full - } viaopt; /* how to deal with proxy Via: headers */ - char viaopt_set; - size_t recv_buffer_size; - char recv_buffer_size_set; - long maxfwd; - char maxfwd_set; -} proxy_server_conf; - -typedef struct { - const char *p; /* The path */ - int p_is_fnmatch; /* Is this path an fnmatch candidate? */ - regex_t *r; /* Is this a regex? */ -} proxy_dir_conf; - -typedef struct { - conn_rec *connection; - char *hostname; - apr_port_t port; -} proxy_conn_rec; - -typedef struct { - float cache_completion; /* completion percentage */ - int content_length; /* length of the content */ -} proxy_completion; - - -/* hooks */ - -/* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and - * PROXY_DECLARE_DATA with appropriate export and import tags for the platform - */ -#if !defined(WIN32) -#define PROXY_DECLARE(type) type -#define PROXY_DECLARE_NONSTD(type) type -#define PROXY_DECLARE_DATA -#elif defined(PROXY_DECLARE_STATIC) -#define PROXY_DECLARE(type) type __stdcall -#define PROXY_DECLARE_NONSTD(type) type -#define PROXY_DECLARE_DATA -#elif defined(PROXY_DECLARE_EXPORT) -#define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall -#define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type -#define PROXY_DECLARE_DATA __declspec(dllexport) -#else -#define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall -#define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type -#define PROXY_DECLARE_DATA __declspec(dllimport) -#endif - -APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r, - proxy_server_conf *conf, char *url, - const char *proxyhost, apr_port_t proxyport)) -APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r, - char *url)) - -/* proxy_util.c */ - -PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r); -PROXY_DECLARE(int) ap_proxy_hex2c(const char *x); -PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x); -PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t, - int isenc); -PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp, - char **passwordp, char **hostp, apr_port_t *port); -PROXY_DECLARE(const char *)ap_proxy_date_canon(apr_pool_t *p, const char *x); -PROXY_DECLARE(apr_table_t *)ap_proxy_read_headers(request_rec *r, request_rec *rp, char *buffer, int size, conn_rec *c); -PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val); -PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val); -PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x); -PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y); -PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message); -PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p); -PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p); -PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p); -PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p); -PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr); -PROXY_DECLARE(int) ap_proxy_pre_http_connection(conn_rec *c, request_rec *r); -PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos); -PROXY_DECLARE(void) ap_proxy_reset_output_filters(conn_rec *c); - - -#endif /*MOD_PROXY_H*/ diff --git a/modules/proxy/mod_proxy.mak b/modules/proxy/mod_proxy.mak deleted file mode 100644 index 435796b3bd..0000000000 --- a/modules/proxy/mod_proxy.mak +++ /dev/null @@ -1,573 +0,0 @@ -# Microsoft Developer Studio Generated NMAKE File, Based on mod_proxy.dsp -!IF "$(CFG)" == "" -CFG=mod_proxy - Win32 Release -!MESSAGE No configuration specified. Defaulting to mod_proxy - Win32 Release. -!ENDIF - -!IF "$(CFG)" != "mod_proxy - Win32 Release" && "$(CFG)" !=\ - "mod_proxy - Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!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 "mod_proxy.mak" CFG="mod_proxy - Win32 Release" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "mod_proxy - Win32 Release" (based on\ - "Win32 (x86) Dynamic-Link Library") -!MESSAGE "mod_proxy - Win32 Debug" (based on\ - "Win32 (x86) Dynamic-Link Library") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF - -!IF "$(CFG)" == "mod_proxy - Win32 Release" - -OUTDIR=.\Release -INTDIR=.\Release -# Begin Custom Macros -OutDir=.\Release -# End Custom Macros - -!IF "$(RECURSE)" == "0" - -ALL : "$(OUTDIR)\mod_proxy.so" - -!ELSE - -ALL : "libaprutil - Win32 Release" "libhttpd - Win32 Release"\ - "libapr - Win32 Release" "$(OUTDIR)\mod_proxy.so" - -!ENDIF - -!IF "$(RECURSE)" == "1" -CLEAN :"libapr - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"\ - "libaprutil - Win32 ReleaseCLEAN" -!ELSE -CLEAN : -!ENDIF - -@erase "$(INTDIR)\mod_proxy.idb" - -@erase "$(INTDIR)\mod_proxy.obj" - -@erase "$(INTDIR)\proxy_connect.obj" - -@erase "$(INTDIR)\proxy_ftp.obj" - -@erase "$(INTDIR)\proxy_http.obj" - -@erase "$(INTDIR)\proxy_util.obj" - -@erase "$(OUTDIR)\mod_proxy.exp" - -@erase "$(OUTDIR)\mod_proxy.lib" - -@erase "$(OUTDIR)\mod_proxy.map" - -@erase "$(OUTDIR)\mod_proxy.so" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\srclib\apr\include" /I\ - "../../srclib/apr-util/include" /I "..\..\include" /I "..\..\os\win32" /D\ - "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_proxy" /FD\ - /c -CPP_OBJS=.\Release/ -CPP_SBRS=. - -.c{$(CPP_OBJS)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(CPP_OBJS)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(CPP_OBJS)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.c{$(CPP_SBRS)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(CPP_SBRS)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(CPP_SBRS)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -MTL=midl.exe -MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 -RSC=rc.exe -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_proxy.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -LINK32_FLAGS=kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows\ - /dll /incremental:no /pdb:"$(OUTDIR)\mod_proxy.pdb"\ - /map:"$(INTDIR)\mod_proxy.map" /machine:I386 /out:"$(OUTDIR)\mod_proxy.so"\ - /implib:"$(OUTDIR)\mod_proxy.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy -LINK32_OBJS= \ - "$(INTDIR)\mod_proxy.obj" \ - "$(INTDIR)\proxy_connect.obj" \ - "$(INTDIR)\proxy_ftp.obj" \ - "$(INTDIR)\proxy_http.obj" \ - "$(INTDIR)\proxy_util.obj" \ - "..\..\Release\libhttpd.lib" \ - "..\..\srclib\apr-util\Release\libaprutil.lib" \ - "..\..\srclib\apr\Release\libapr.lib" - -"$(OUTDIR)\mod_proxy.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug" - -OUTDIR=.\Debug -INTDIR=.\Debug -# Begin Custom Macros -OutDir=.\Debug -# End Custom Macros - -!IF "$(RECURSE)" == "0" - -ALL : "$(OUTDIR)\mod_proxy.so" - -!ELSE - -ALL : "libaprutil - Win32 Debug" "libhttpd - Win32 Debug"\ - "libapr - Win32 Debug" "$(OUTDIR)\mod_proxy.so" - -!ENDIF - -!IF "$(RECURSE)" == "1" -CLEAN :"libapr - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"\ - "libaprutil - Win32 DebugCLEAN" -!ELSE -CLEAN : -!ENDIF - -@erase "$(INTDIR)\mod_proxy.idb" - -@erase "$(INTDIR)\mod_proxy.obj" - -@erase "$(INTDIR)\proxy_connect.obj" - -@erase "$(INTDIR)\proxy_ftp.obj" - -@erase "$(INTDIR)\proxy_http.obj" - -@erase "$(INTDIR)\proxy_util.obj" - -@erase "$(OUTDIR)\mod_proxy.exp" - -@erase "$(OUTDIR)\mod_proxy.lib" - -@erase "$(OUTDIR)\mod_proxy.map" - -@erase "$(OUTDIR)\mod_proxy.pdb" - -@erase "$(OUTDIR)\mod_proxy.so" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\srclib\apr\include" /I\ - "../../srclib/apr-util/include" /I "..\..\include" /I "..\..\os\win32" /D\ - "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_proxy" /FD\ - /c -CPP_OBJS=.\Debug/ -CPP_SBRS=. - -.c{$(CPP_OBJS)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(CPP_OBJS)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(CPP_OBJS)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.c{$(CPP_SBRS)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(CPP_SBRS)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(CPP_SBRS)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -MTL=midl.exe -MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 -RSC=rc.exe -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_proxy.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -LINK32_FLAGS=kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows\ - /dll /incremental:no /pdb:"$(OUTDIR)\mod_proxy.pdb"\ - /map:"$(INTDIR)\mod_proxy.map" /debug /machine:I386\ - /out:"$(OUTDIR)\mod_proxy.so" /implib:"$(OUTDIR)\mod_proxy.lib"\ - /base:@..\..\os\win32\BaseAddr.ref,mod_proxy -LINK32_OBJS= \ - "$(INTDIR)\mod_proxy.obj" \ - "$(INTDIR)\proxy_connect.obj" \ - "$(INTDIR)\proxy_ftp.obj" \ - "$(INTDIR)\proxy_http.obj" \ - "$(INTDIR)\proxy_util.obj" \ - "..\..\Debug\libhttpd.lib" \ - "..\..\srclib\apr-util\Debug\libaprutil.lib" \ - "..\..\srclib\apr\Debug\libapr.lib" - -"$(OUTDIR)\mod_proxy.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - - -!IF "$(CFG)" == "mod_proxy - Win32 Release" || "$(CFG)" ==\ - "mod_proxy - Win32 Debug" -SOURCE=.\mod_proxy.c -DEP_CPP_MOD_P=\ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\http_request.h"\ - "..\..\include\http_vhost.h"\ - "..\..\include\httpd.h"\ - "..\..\include\pcreposix.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_date.h"\ - "..\..\include\util_filter.h"\ - "..\..\os\win32\os.h"\ - "..\..\srclib\apr-util\include\apr_buckets.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_ring.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr.h"\ - "..\..\srclib\apr\include\apr_compat.h"\ - "..\..\srclib\apr\include\apr_dso.h"\ - "..\..\srclib\apr\include\apr_errno.h"\ - "..\..\srclib\apr\include\apr_file_io.h"\ - "..\..\srclib\apr\include\apr_general.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_lock.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_network_io.h"\ - "..\..\srclib\apr\include\apr_pools.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_tables.h"\ - "..\..\srclib\apr\include\apr_thread_proc.h"\ - "..\..\srclib\apr\include\apr_time.h"\ - "..\..\srclib\apr\network_io\os2\os2nerrno.h"\ - ".\mod_proxy.h"\ - -NODEP_CPP_MOD_P=\ - "..\..\include\ap_config_auto.h"\ - "..\..\include\ap_config_path.h"\ - ".\ap_cache.h"\ - ".\buff.h"\ - - -"$(INTDIR)\mod_proxy.obj" : $(SOURCE) $(DEP_CPP_MOD_P) "$(INTDIR)" - - -SOURCE=.\proxy_connect.c -DEP_CPP_PROXY=\ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\httpd.h"\ - "..\..\include\pcreposix.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_filter.h"\ - "..\..\os\win32\os.h"\ - "..\..\srclib\apr-util\include\apr_buckets.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_ring.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr.h"\ - "..\..\srclib\apr\include\apr_compat.h"\ - "..\..\srclib\apr\include\apr_dso.h"\ - "..\..\srclib\apr\include\apr_errno.h"\ - "..\..\srclib\apr\include\apr_file_io.h"\ - "..\..\srclib\apr\include\apr_general.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_lock.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_network_io.h"\ - "..\..\srclib\apr\include\apr_pools.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_tables.h"\ - "..\..\srclib\apr\include\apr_thread_proc.h"\ - "..\..\srclib\apr\include\apr_time.h"\ - "..\..\srclib\apr\network_io\os2\os2nerrno.h"\ - ".\mod_proxy.h"\ - -NODEP_CPP_PROXY=\ - "..\..\include\ap_config_auto.h"\ - "..\..\include\ap_config_path.h"\ - ".\ap_cache.h"\ - ".\buff.h"\ - - -"$(INTDIR)\proxy_connect.obj" : $(SOURCE) $(DEP_CPP_PROXY) "$(INTDIR)" - - -SOURCE=.\proxy_ftp.c -DEP_CPP_PROXY_=\ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\httpd.h"\ - "..\..\include\pcreposix.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_filter.h"\ - "..\..\os\win32\os.h"\ - "..\..\srclib\apr-util\include\apr_buckets.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_ring.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr.h"\ - "..\..\srclib\apr\include\apr_compat.h"\ - "..\..\srclib\apr\include\apr_dso.h"\ - "..\..\srclib\apr\include\apr_errno.h"\ - "..\..\srclib\apr\include\apr_file_io.h"\ - "..\..\srclib\apr\include\apr_general.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_lock.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_network_io.h"\ - "..\..\srclib\apr\include\apr_pools.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_tables.h"\ - "..\..\srclib\apr\include\apr_thread_proc.h"\ - "..\..\srclib\apr\include\apr_time.h"\ - "..\..\srclib\apr\network_io\os2\os2nerrno.h"\ - ".\mod_proxy.h"\ - -NODEP_CPP_PROXY_=\ - "..\..\include\ap_config_auto.h"\ - "..\..\include\ap_config_path.h"\ - ".\ap_cache.h"\ - ".\buff.h"\ - - -"$(INTDIR)\proxy_ftp.obj" : $(SOURCE) $(DEP_CPP_PROXY_) "$(INTDIR)" - - -SOURCE=.\proxy_http.c -DEP_CPP_PROXY_H=\ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_connection.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\httpd.h"\ - "..\..\include\pcreposix.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_date.h"\ - "..\..\include\util_filter.h"\ - "..\..\os\win32\os.h"\ - "..\..\srclib\apr-util\include\apr_buckets.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_ring.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr.h"\ - "..\..\srclib\apr\include\apr_compat.h"\ - "..\..\srclib\apr\include\apr_dso.h"\ - "..\..\srclib\apr\include\apr_errno.h"\ - "..\..\srclib\apr\include\apr_file_io.h"\ - "..\..\srclib\apr\include\apr_general.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_lock.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_network_io.h"\ - "..\..\srclib\apr\include\apr_pools.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_tables.h"\ - "..\..\srclib\apr\include\apr_thread_proc.h"\ - "..\..\srclib\apr\include\apr_time.h"\ - "..\..\srclib\apr\network_io\os2\os2nerrno.h"\ - ".\mod_proxy.h"\ - -NODEP_CPP_PROXY_H=\ - "..\..\include\ap_config_auto.h"\ - "..\..\include\ap_config_path.h"\ - ".\ap_cache.h"\ - ".\buff.h"\ - - -"$(INTDIR)\proxy_http.obj" : $(SOURCE) $(DEP_CPP_PROXY_H) "$(INTDIR)" - - -SOURCE=.\proxy_util.c -DEP_CPP_PROXY_U=\ - "..\..\include\ap_config.h"\ - "..\..\include\ap_mmn.h"\ - "..\..\include\http_config.h"\ - "..\..\include\http_core.h"\ - "..\..\include\http_log.h"\ - "..\..\include\http_main.h"\ - "..\..\include\http_protocol.h"\ - "..\..\include\httpd.h"\ - "..\..\include\pcreposix.h"\ - "..\..\include\util_cfgtree.h"\ - "..\..\include\util_date.h"\ - "..\..\include\util_filter.h"\ - "..\..\os\win32\os.h"\ - "..\..\srclib\apr-util\include\apr_buckets.h"\ - "..\..\srclib\apr-util\include\apr_hooks.h"\ - "..\..\srclib\apr-util\include\apr_ring.h"\ - "..\..\srclib\apr-util\include\apr_uri.h"\ - "..\..\srclib\apr\include\apr.h"\ - "..\..\srclib\apr\include\apr_compat.h"\ - "..\..\srclib\apr\include\apr_dso.h"\ - "..\..\srclib\apr\include\apr_errno.h"\ - "..\..\srclib\apr\include\apr_file_io.h"\ - "..\..\srclib\apr\include\apr_general.h"\ - "..\..\srclib\apr\include\apr_lib.h"\ - "..\..\srclib\apr\include\apr_lock.h"\ - "..\..\srclib\apr\include\apr_md5.h"\ - "..\..\srclib\apr\include\apr_mmap.h"\ - "..\..\srclib\apr\include\apr_network_io.h"\ - "..\..\srclib\apr\include\apr_pools.h"\ - "..\..\srclib\apr\include\apr_portable.h"\ - "..\..\srclib\apr\include\apr_strings.h"\ - "..\..\srclib\apr\include\apr_tables.h"\ - "..\..\srclib\apr\include\apr_thread_proc.h"\ - "..\..\srclib\apr\include\apr_time.h"\ - "..\..\srclib\apr\include\apr_xlate.h"\ - "..\..\srclib\apr\network_io\os2\os2nerrno.h"\ - ".\mod_proxy.h"\ - -NODEP_CPP_PROXY_U=\ - "..\..\include\ap_config_auto.h"\ - "..\..\include\ap_config_path.h"\ - ".\ap_cache.h"\ - ".\buff.h"\ - - -"$(INTDIR)\proxy_util.obj" : $(SOURCE) $(DEP_CPP_PROXY_U) "$(INTDIR)" - - -!IF "$(CFG)" == "mod_proxy - Win32 Release" - -"libapr - Win32 Release" : - cd "\test\httpd-2.0\srclib\apr" - $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" - cd "..\..\modules\proxy" - -"libapr - Win32 ReleaseCLEAN" : - cd "\test\httpd-2.0\srclib\apr" - $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libapr.mak" CFG="libapr - Win32 Release"\ - RECURSE=1 - cd "..\..\modules\proxy" - -!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug" - -"libapr - Win32 Debug" : - cd "\test\httpd-2.0\srclib\apr" - $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" - cd "..\..\modules\proxy" - -"libapr - Win32 DebugCLEAN" : - cd "\test\httpd-2.0\srclib\apr" - $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libapr.mak" CFG="libapr - Win32 Debug"\ - RECURSE=1 - cd "..\..\modules\proxy" - -!ENDIF - -!IF "$(CFG)" == "mod_proxy - Win32 Release" - -"libhttpd - Win32 Release" : - cd "\test\httpd-2.0" - $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" - cd ".\modules\proxy" - -"libhttpd - Win32 ReleaseCLEAN" : - cd "\test\httpd-2.0" - $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libhttpd.mak"\ - CFG="libhttpd - Win32 Release" RECURSE=1 - cd ".\modules\proxy" - -!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug" - -"libhttpd - Win32 Debug" : - cd "\test\httpd-2.0" - $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" - cd ".\modules\proxy" - -"libhttpd - Win32 DebugCLEAN" : - cd "\test\httpd-2.0" - $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug"\ - RECURSE=1 - cd ".\modules\proxy" - -!ENDIF - -!IF "$(CFG)" == "mod_proxy - Win32 Release" - -"libaprutil - Win32 Release" : - cd "\test\httpd-2.0\srclib\apr-util" - $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release"\ - - cd "..\..\modules\proxy" - -"libaprutil - Win32 ReleaseCLEAN" : - cd "\test\httpd-2.0\srclib\apr-util" - $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\ - CFG="libaprutil - Win32 Release" RECURSE=1 - cd "..\..\modules\proxy" - -!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug" - -"libaprutil - Win32 Debug" : - cd "\test\httpd-2.0\srclib\apr-util" - $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" - cd "..\..\modules\proxy" - -"libaprutil - Win32 DebugCLEAN" : - cd "\test\httpd-2.0\srclib\apr-util" - $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\ - CFG="libaprutil - Win32 Debug" RECURSE=1 - cd "..\..\modules\proxy" - -!ENDIF - - -!ENDIF - diff --git a/modules/proxy/proxy_connect.c b/modules/proxy/proxy_connect.c deleted file mode 100644 index 218b33265f..0000000000 --- a/modules/proxy/proxy_connect.c +++ /dev/null @@ -1,430 +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 - * <http://www.apache.org/>. - * - * Portions of this software are based upon public domain software - * originally written at the National Center for Supercomputing Applications, - * University of Illinois, Urbana-Champaign. - */ - -/* CONNECT method for Apache proxy */ - -#define CORE_PRIVATE - -#include "mod_proxy.h" - -module AP_MODULE_DECLARE_DATA proxy_connect_module; - -int ap_proxy_connect_canon(request_rec *r, char *url); -int ap_proxy_connect_handler(request_rec *r, proxy_server_conf *conf, - char *url, const char *proxyname, - apr_port_t proxyport); - -/* - * This handles Netscape CONNECT method secure proxy requests. - * A connection is opened to the specified host and data is - * passed through between the WWW site and the browser. - * - * This code is based on the INTERNET-DRAFT document - * "Tunneling SSL Through a WWW Proxy" currently at - * http://www.mcom.com/newsref/std/tunneling_ssl.html. - * - * If proxyhost and proxyport are set, we send a CONNECT to - * the specified proxy.. - * - * FIXME: this doesn't log the number of bytes sent, but - * that may be okay, since the data is supposed to - * be transparent. In fact, this doesn't log at all - * yet. 8^) - * FIXME: doesn't check any headers initally sent from the - * client. - * FIXME: should allow authentication, but hopefully the - * generic proxy authentication is good enough. - * FIXME: no check for r->assbackwards, whatever that is. - */ - -static int -allowed_port(proxy_server_conf *conf, int port) -{ - int i; - int *list = (int *) conf->allowed_connect_ports->elts; - - for(i = 0; i < conf->allowed_connect_ports->nelts; i++) { - if(port == list[i]) - return 1; - } - return 0; -} - -/* canonicalise CONNECT URLs. */ -int ap_proxy_connect_canon(request_rec *r, char *url) -{ - - if (r->method_number != M_CONNECT) { - return DECLINED; - } - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: CONNECT: canonicalising URL %s", url); - - return OK; -} - -/* CONNECT handler */ -int ap_proxy_connect_handler(request_rec *r, proxy_server_conf *conf, - char *url, const char *proxyname, - apr_port_t proxyport) -{ - apr_pool_t *p = r->pool; - apr_socket_t *sock; - apr_status_t err, rv; - apr_size_t i, o, nbytes; - char buffer[HUGE_STRING_LEN]; - - apr_pollfd_t *pollfd; - apr_int32_t pollcnt; - apr_int16_t pollevent; - apr_sockaddr_t *uri_addr, *connect_addr; - - apr_uri_t uri; - const char *connectname; - int connectport = 0; - - /* is this for us? */ - if (r->method_number != M_CONNECT) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: CONNECT: rejecting URL %s", url); - return DECLINED; - } - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: CONNECT: serving URL %s", url); - - - /* - * 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_hostinfo(p, url, &uri)) { - return ap_proxyerror(r, HTTP_BAD_REQUEST, - apr_pstrcat(p, "URI cannot be parsed: ", url, NULL)); - } - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: CONNECT: connecting %s to %s:%d", url, uri.hostname, uri.port); - - /* do a DNS lookup for the destination host */ - err = apr_sockaddr_info_get(&uri_addr, uri.hostname, APR_UNSPEC, uri.port, 0, p); - - /* are we connecting directly, or via a proxy? */ - if (proxyname) { - connectname = proxyname; - connectport = proxyport; - err = apr_sockaddr_info_get(&connect_addr, proxyname, APR_UNSPEC, proxyport, 0, p); - } - else { - connectname = uri.hostname; - connectport = uri.port; - connect_addr = uri_addr; - } - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "proxy: CONNECT: connecting to remote proxy %s on port %d", connectname, connectport); - - /* 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"); - } - - /* Check if it is an allowed port */ - if (conf->allowed_connect_ports->nelts == 0) { - /* Default setting if not overridden by AllowCONNECT */ - switch (uri.port) { - case APR_URI_HTTPS_DEFAULT_PORT: - case APR_URI_SNEWS_DEFAULT_PORT: - break; - default: - return HTTP_FORBIDDEN; - } - } else if(!allowed_port(conf, uri.port)) - return HTTP_FORBIDDEN; - - - /* - * Step Two: 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)); - } - - /* create a new socket */ - if ((rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, - "proxy: error creating socket"); - return HTTP_INTERNAL_SERVER_ERROR; - } - - /* Set a timeout on the socket */ - apr_setsocketopt(sock, APR_SO_TIMEOUT, (int)(r->server->timeout * APR_USEC_PER_SEC)); - - /* - * 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: CONNECT: 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; - } - } - } - - - /* - * Step Three: Send the Request - * - * Send the HTTP/1.1 CONNECT request to the remote server - */ - - /* we are acting as a tunnel - the output filter stack should - * be completely empty, because when we are done here we are done completely. - * We add the NULL filter to the stack to do this... - */ - r->output_filters = NULL; - r->connection->output_filters = NULL; - - - /* If we are connecting through a remote proxy, we need to pass - * the CONNECT request on to it. - */ - if (proxyport) { - /* FIXME: Error checking ignored. - */ - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: CONNECT: sending the CONNECT request to the remote proxy"); - nbytes = apr_snprintf(buffer, sizeof(buffer), - "CONNECT %s HTTP/1.0" CRLF, r->uri); - apr_send(sock, buffer, &nbytes); - nbytes = apr_snprintf(buffer, sizeof(buffer), - "Proxy-agent: %s" CRLF CRLF, ap_get_server_version()); - apr_send(sock, buffer, &nbytes); - } - else { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: CONNECT: Returning 200 OK Status"); - nbytes = apr_snprintf(buffer, sizeof(buffer), - "HTTP/1.0 200 Connection Established" CRLF); - apr_send(r->connection->client_socket, buffer, &nbytes); - nbytes = apr_snprintf(buffer, sizeof(buffer), - "Proxy-agent: %s" CRLF CRLF, ap_get_server_version()); - apr_send(r->connection->client_socket, buffer, &nbytes); - } - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: CONNECT: setting up poll()"); - - /* - * Step Four: Handle Data Transfer - * - * Handle two way transfer of data over the socket (this is a tunnel). - */ - -/* r->sent_bodyct = 1;*/ - - if((rv = apr_poll_setup(&pollfd, 2, r->pool)) != APR_SUCCESS) - { - apr_socket_close(sock); - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, - "proxy: CONNECT: error apr_poll_setup()"); - return HTTP_INTERNAL_SERVER_ERROR; - } - - /* Add client side to the poll */ - apr_poll_socket_add(pollfd, r->connection->client_socket, APR_POLLIN); - - /* Add the server side to the poll */ - apr_poll_socket_add(pollfd, sock, APR_POLLIN); - - while (1) { /* Infinite loop until error (one side closes the connection) */ -/* ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, "proxy: CONNECT: going to sleep (poll)");*/ - if ((rv = apr_poll(pollfd, &pollcnt, -1)) != APR_SUCCESS) - { - apr_socket_close(sock); - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy: CONNECT: error apr_poll()"); - return HTTP_INTERNAL_SERVER_ERROR; - } -/* ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: CONNECT: woke from select(), i=%d", pollcnt);*/ - - if (pollcnt) { - apr_poll_revents_get(&pollevent, sock, pollfd); - if (pollevent & APR_POLLIN) { -/* ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: CONNECT: sock was set");*/ - nbytes = sizeof(buffer); - if (apr_recv(sock, buffer, &nbytes) == APR_SUCCESS) { - o = 0; - i = nbytes; - while(i > 0) - { - nbytes = i; - if (apr_send(r->connection->client_socket, buffer + o, &nbytes) != APR_SUCCESS) - break; - o += nbytes; - i -= nbytes; - } - } - else - break; - } - else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) - break; - - - apr_poll_revents_get(&pollevent, r->connection->client_socket, pollfd); - if (pollevent & APR_POLLIN) { -/* ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: CONNECT: client was set");*/ - nbytes = sizeof(buffer); - if (apr_recv(r->connection->client_socket, buffer, &nbytes) == APR_SUCCESS) { - o = 0; - i = nbytes; - while(i > 0) - { - nbytes = i; - if (apr_send(sock, buffer + o, &nbytes) != APR_SUCCESS) - break; - o += nbytes; - i -= nbytes; - } - } - else - break; - } - else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) - break; - } - else - break; - } - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: CONNECT: finished with poll() - cleaning up"); - - /* - * Step Five: Clean Up - * - * Close the socket and clean up - */ - - apr_socket_close(sock); - - return OK; -} - -static void ap_proxy_connect_register_hook(apr_pool_t *p) -{ - proxy_hook_scheme_handler(ap_proxy_connect_handler, NULL, NULL, APR_HOOK_MIDDLE); - proxy_hook_canon_handler(ap_proxy_connect_canon, NULL, NULL, APR_HOOK_MIDDLE); -} - -module AP_MODULE_DECLARE_DATA proxy_connect_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_connect_register_hook /* register hooks */ -}; diff --git a/modules/proxy/proxy_connect.dsp b/modules/proxy/proxy_connect.dsp deleted file mode 100644 index 18c4c37cba..0000000000 --- a/modules/proxy/proxy_connect.dsp +++ /dev/null @@ -1,107 +0,0 @@ -# Microsoft Developer Studio Project File - Name="proxy_connect" - 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_connect - 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_connect.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_connect.mak" CFG="proxy_connect - Win32 Release" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "proxy_connect - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "proxy_connect - 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_connect - 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_connect" /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_connect.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_connect -# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /machine:I386 /out:"Release/proxy_connect.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_connect - -!ELSEIF "$(CFG)" == "proxy_connect - 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_connect" /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_connect.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_connect -# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"Debug/proxy_connect.so" /base:@..\..\os\win32\BaseAddr.ref,proxy_connect - -!ENDIF - -# Begin Target - -# Name "proxy_connect - Win32 Release" -# Name "proxy_connect - 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_connect.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_ftp.c b/modules/proxy/proxy_ftp.c deleted file mode 100644 index 834fd880d1..0000000000 --- a/modules/proxy/proxy_ftp.c +++ /dev/null @@ -1,1657 +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 - * <http://www.apache.org/>. - * - * Portions of this software are based upon public domain software - * originally written at the National Center for Supercomputing Applications, - * University of Illinois, Urbana-Champaign. - */ - -/* FTP routines for Apache proxy */ - -#include "mod_proxy.h" - -#define AUTODETECT_PWD - -module AP_MODULE_DECLARE_DATA proxy_ftp_module; - -int ap_proxy_ftp_canon(request_rec *r, char *url); -int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, - char *url, const char *proxyhost, - apr_port_t proxyport); -apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, - apr_bucket_brigade *bb); - - -/* - * Decodes a '%' escaped string, and returns the number of characters - */ -static int decodeenc(char *x) -{ - int i, j, ch; - - if (x[0] == '\0') - return 0; /* special case for no characters */ - for (i = 0, j = 0; x[i] != '\0'; i++, j++) { - /* decode it if not already done */ - ch = x[i]; - if (ch == '%' && ap_isxdigit(x[i + 1]) && ap_isxdigit(x[i + 2])) { - ch = ap_proxy_hex2c(&x[i + 1]); - i += 2; - } - x[j] = ch; - } - x[j] = '\0'; - return j; -} - -/* - * checks an encoded ftp string for bad characters, namely, CR, LF or - * non-ascii character - */ -static int ftp_check_string(const char *x) -{ - int i, ch = 0; - - for (i = 0; x[i] != '\0'; i++) { - ch = x[i]; - if (ch == '%' && ap_isxdigit(x[i + 1]) && ap_isxdigit(x[i + 2])) { - ch = ap_proxy_hex2c(&x[i + 1]); - i += 2; - } -#if !APR_CHARSET_EBCDIC - if (ch == '\015' || ch == '\012' || (ch & 0x80)) -#else /*APR_CHARSET_EBCDIC*/ - if (ch == '\r' || ch == '\n' || (os_toascii[ch] & 0x80)) -#endif /*APR_CHARSET_EBCDIC*/ - return 0; - } - return 1; -} - -/* - * Canonicalise ftp URLs. - */ -int ap_proxy_ftp_canon(request_rec *r, char *url) -{ - char *user, *password, *host, *path, *parms, *strp, sport[7]; - apr_pool_t *p = r->pool; - const char *err; - apr_port_t port, def_port; - - /* */ - if (strncasecmp(url, "ftp:", 4) == 0) { - url += 4; - } - else { - return DECLINED; - } - def_port = apr_uri_default_port_for_scheme("ftp"); - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, - "proxy: FTP: canonicalising URL %s", url); - - port = def_port; - err = ap_proxy_canon_netloc(p, &url, &user, &password, &host, &port); - if (err) - return HTTP_BAD_REQUEST; - if (user != NULL && !ftp_check_string(user)) - return HTTP_BAD_REQUEST; - if (password != NULL && !ftp_check_string(password)) - return HTTP_BAD_REQUEST; - - /* now parse path/parameters args, according to rfc1738 */ - /* N.B. if this isn't a true proxy request, then the URL path - * (but not query args) has already been decoded. - * This gives rise to the problem of a ; being decoded into the - * path. - */ - strp = strchr(url, ';'); - if (strp != NULL) { - *(strp++) = '\0'; - parms = ap_proxy_canonenc(p, strp, strlen(strp), enc_parm, - r->proxyreq); - if (parms == NULL) - return HTTP_BAD_REQUEST; - } - else - parms = ""; - - path = ap_proxy_canonenc(p, url, strlen(url), enc_path, r->proxyreq); - if (path == NULL) - return HTTP_BAD_REQUEST; - if (!ftp_check_string(path)) - return HTTP_BAD_REQUEST; - - if (r->proxyreq && r->args != NULL) { - if (strp != NULL) { - strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_parm, 1); - if (strp == NULL) - return HTTP_BAD_REQUEST; - parms = apr_pstrcat(p, parms, "?", strp, NULL); - } - else { - strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_fpath, 1); - if (strp == NULL) - return HTTP_BAD_REQUEST; - path = apr_pstrcat(p, path, "?", strp, NULL); - } - r->args = NULL; - } - -/* now, rebuild URL */ - - if (port != def_port) - apr_snprintf(sport, sizeof(sport), ":%d", port); - else - sport[0] = '\0'; - - r->filename = apr_pstrcat(p, "proxy:ftp://", (user != NULL) ? user : "", - (password != NULL) ? ":" : "", - (password != NULL) ? password : "", - (user != NULL) ? "@" : "", host, sport, "/", path, - (parms[0] != '\0') ? ";" : "", parms, NULL); - - return OK; -} - -/* we chop lines longer than 80 characters */ -#define MAX_LINE_LEN 80 - -/* - * Reads response lines, returns both the ftp status code and - * remembers the response message in the supplied buffer - */ -static int ftp_getrc_msg(conn_rec *c, apr_bucket_brigade *bb, char *msgbuf, int msglen) -{ - int status; - char response[MAX_LINE_LEN]; - char buff[5]; - char *mb = msgbuf, - *me = &msgbuf[msglen]; - apr_status_t rv; - int eos; - - if (APR_SUCCESS != (rv = ap_proxy_string_read(c, bb, response, sizeof(response), &eos))) { - return -1; - } - if (!apr_isdigit(response[0]) || !apr_isdigit(response[1]) || - !apr_isdigit(response[2]) || (response[3] != ' ' && response[3] != '-')) - status = 0; - else - status = 100 * response[0] + 10 * response[1] + response[2] - 111 * '0'; - - mb = apr_cpystrn(mb, response+4, me - mb); - - if (response[3] == '-') { - memcpy(buff, response, 3); - buff[3] = ' '; - do { - if (APR_SUCCESS != (rv = ap_proxy_string_read(c, bb, response, sizeof(response), &eos))) { - return -1; - } - mb = apr_cpystrn(mb, response + (' ' == response[0] ? 1 : 4), me - mb); - } while (memcmp(response, buff, 4) != 0); - } - - return status; -} - -/* this is a filter that turns a raw ASCII directory listing into pretty HTML */ - -/* ideally, mod_proxy should simply send the raw directory list up the filter - * stack to mod_autoindex, which in theory should turn the raw ascii into - * pretty html along with all the bells and whistles it provides... - * - * all in good time...! :) - */ - -typedef struct { - apr_bucket_brigade *in; - char buffer[MAX_STRING_LEN]; - enum {HEADER, BODY, FOOTER} state; -} proxy_dir_ctx_t; - -apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *in) -{ - request_rec *r = f->r; - apr_pool_t *p = r->pool; - apr_bucket *e; - apr_bucket_brigade *out = apr_brigade_create(p); - apr_status_t rv; - - register int n; - char *dir, *path, *reldir, *site, *str; - - const char *pwd = apr_table_get(r->notes, "Directory-PWD"); - const char *readme = apr_table_get(r->notes, "Directory-README"); - - proxy_dir_ctx_t *ctx = f->ctx; - if (!ctx) { - f->ctx = ctx = apr_pcalloc(p, sizeof(*ctx)); - ctx->in = apr_brigade_create(p); - ctx->buffer[0] = 0; - ctx->state = HEADER; - } - - /* combine the stored and the new */ - APR_BRIGADE_CONCAT(ctx->in, in); - - if (HEADER == ctx->state) { - - /* Save "scheme://site" prefix without password */ - site = apr_uri_unparse(p, &f->r->parsed_uri, APR_URI_UNP_OMITPASSWORD|APR_URI_UNP_OMITPATHINFO); - /* ... and path without query args */ - path = apr_uri_unparse(p, &f->r->parsed_uri, APR_URI_UNP_OMITSITEPART|APR_URI_UNP_OMITQUERY); - (void)decodeenc(path); - - /* Copy path, strip (all except the last) trailing slashes */ - path = dir = apr_pstrcat(p, path, "/", NULL); - while ((n = strlen(path)) > 1 && path[n-1] == '/' && path[n-2] == '/') - path[n-1] = '\0'; - - /* print "ftp://host/" */ - str = apr_psprintf(p, DOCTYPE_HTML_3_2 - "\n\n<HTML>\n<HEAD>\n<TITLE>%s%s</TITLE>\n" - "<BASE HREF=\"%s%s\">\n</HEAD>\n\n" - "<BODY>\n\n<H2>Directory of " - "<A HREF=\"/\">%s</A>/", - site, path, site, path, site); - - e = apr_bucket_pool_create(str, strlen(str), p); - APR_BRIGADE_INSERT_TAIL(out, e); - - while ((dir = strchr(dir+1, '/')) != NULL) - { - *dir = '\0'; - if ((reldir = strrchr(path+1, '/'))==NULL) - reldir = path+1; - else - ++reldir; - /* print "path/" component */ - str = apr_psprintf(p, "<A HREF=\"/%s/\">%s</A>/", path+1, reldir); - e = apr_bucket_pool_create(str, strlen(str), p); - APR_BRIGADE_INSERT_TAIL(out, e); - *dir = '/'; - } - /* If the caller has determined the current directory, and it differs */ - /* from what the client requested, then show the real name */ - if (pwd == NULL || strncmp (pwd, path, strlen(pwd)) == 0) { - str = apr_psprintf(p, "</H2>\n\n<HR></HR>\n\n<PRE>"); - } else { - str = apr_psprintf(p, "</H2>\n\n(%s)\n\n<HR></HR>\n\n<PRE>", 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</PRE>\n\n<HR></HR>\n\n<PRE>\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 <A HREF=\"%s\">%s %s</A>\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 <A HREF=\"%s/\">%s</A>\n", - ctx->buffer, filename, filename); - } - else { - str = apr_psprintf(p, "%s <A HREF=\"%s\">%s</A>\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, "</PRE>\n\n<HR></HR>\n\n%s\n\n</BODY>\n</HTML>\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(r->pool, - &r->parsed_uri, APR_URI_UNP_OMITPATHINFO)); - - apr_table_setn(r->err_headers_out, "WWW-Authenticate", - apr_pstrcat(r->pool, "Basic realm=\"", - apr_uri_unparse(r->pool, &r->parsed_uri, - APR_URI_UNP_OMITPASSWORD|APR_URI_UNP_OMITPATHINFO), - "\"", NULL)); - - return HTTP_UNAUTHORIZED; -} - - -/* - * Handles direct access of ftp:// URLs - * Original (Non-PASV) version from - * Troy Morrison <spiffnet@zoom.com> - * PASV added by Chuck - * Filters by [Graham Leggett <minfrin@sharp.fm>] - */ -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_off_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*/ - } - - /* Set a timeout on the socket */ - apr_setsocketopt(sock, APR_SO_TIMEOUT, (int)(r->server->timeout * APR_USEC_PER_SEC)); - - 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 "<directory-name>" <commentary> */ - /* 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 "<directory-name>" <commentary> */ - /* 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))) { - 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 975254a71f..0000000000 --- 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 3603c32b21..0000000000 --- a/modules/proxy/proxy_http.c +++ /dev/null @@ -1,984 +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 - * <http://www.apache.org/>. - * - * 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); - -typedef struct { - const char *name; - int port; - apr_sockaddr_t *addr; - apr_socket_t *sock; - int close; -} proxy_http_conn_t; - -/* - * 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"); -} - -static -apr_status_t ap_proxy_http_determine_connection(apr_pool_t *p, request_rec *r, - proxy_http_conn_t *p_conn, - conn_rec *c, - proxy_server_conf *conf, - apr_uri_t *uri, - char **url, - const char *proxyname, - apr_port_t proxyport, - char *server_portstr) { - int server_port; - apr_status_t err; - apr_sockaddr_t *uri_addr; - /* - * 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(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) { - p_conn->name = apr_pstrdup(c->pool, proxyname); - p_conn->port = proxyport; - /* see memory note above */ - err = apr_sockaddr_info_get(&p_conn->addr, p_conn->name, APR_UNSPEC, - p_conn->port, 0, c->pool); - } else { - p_conn->name = apr_pstrdup(c->pool, uri->hostname); - p_conn->port = uri->port; - p_conn->addr = uri_addr; - *url = apr_pstrcat(p, uri->path, uri->query ? "?" : "", - uri->query ? uri->query : "", - uri->fragment ? "#" : "", - uri->fragment ? uri->fragment : "", NULL); - } - - if (err != APR_SUCCESS) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - apr_pstrcat(p, "DNS lookup failure for: ", - p_conn->name, NULL)); - } - - /* Get the server port for the Via headers */ - { - server_port = ap_get_server_port(r); - if (ap_is_default_port(server_port, r)) { - strcpy(server_portstr,""); - } else { - apr_snprintf(server_portstr, sizeof(server_portstr), ":%d", - server_port); - } - } - - /* 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"); - } - return OK; -} - -static -apr_status_t ap_proxy_http_create_connection(apr_pool_t *p, request_rec *r, - proxy_http_conn_t *p_conn, - conn_rec *c, conn_rec **origin, - proxy_conn_rec *backend, - proxy_server_conf *conf, - const char *proxyname) { - int failed=0, new=0; - apr_status_t rv; - - /* 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 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 == p_conn->port) && - (backend->hostname) && - (!apr_strnatcasecmp(backend->hostname, p_conn->name))) { - 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))", - p_conn->name, backend->hostname, p_conn->port, - 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)) { - int buffer_len = 1; - char test_buffer[1]; - apr_status_t socket_status; - apr_int32_t current_timeout; - - /* use previous keepalive socket */ - *origin = backend->connection; - p_conn->sock = (*origin)->client_socket; - new = 0; - - /* reset the connection filters */ - ap_proxy_reset_output_filters(*origin); - - /* save timeout */ - apr_getsocketopt(p_conn->sock, APR_SO_TIMEOUT, ¤t_timeout); - /* set no timeout */ - apr_setsocketopt(p_conn->sock, APR_SO_TIMEOUT, 0); - socket_status = apr_recv(p_conn->sock, test_buffer, &buffer_len); - /* put back old timeout */ - apr_setsocketopt(p_conn->sock, APR_SO_TIMEOUT, current_timeout); - if ( APR_STATUS_IS_EOF(socket_status) ) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, NULL, - "proxy: HTTP: previous connection is closed"); - new = 1; - } - } - if (new) { - - /* create a new socket */ - backend->connection = NULL; - - /* see memory note above */ - if ((rv = apr_socket_create(&p_conn->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(p_conn->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 - - /* Set a timeout on the socket */ - apr_setsocketopt(p_conn->sock, APR_SO_TIMEOUT, - (int)(r->server->timeout * APR_USEC_PER_SEC)); - - 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 (p_conn->addr) { - - /* make the connection out of the socket */ - rv = apr_connect(p_conn->sock, p_conn->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", - p_conn->addr, p_conn->name); - p_conn->addr = p_conn->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(p_conn->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, p_conn->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)", p_conn->addr, - p_conn->name); - apr_socket_close(p_conn->sock); - return HTTP_INTERNAL_SERVER_ERROR; - } - backend->connection = *origin; - backend->hostname = apr_pstrdup(c->pool, p_conn->name); - backend->port = p_conn->port; - - 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); - } - return OK; -} - -static -apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r, - proxy_http_conn_t *p_conn, conn_rec *origin, - proxy_server_conf *conf, - apr_uri_t *uri, - char *url, apr_bucket_brigade *bb, - char *server_portstr) { - char buffer[HUGE_STRING_LEN]; - char *buf; - apr_bucket *e; - apr_array_header_t *headers_in_array; - apr_table_entry_t *headers_in; - int counter; - /* - * 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. - */ - p_conn->close += ap_proxy_liststr(apr_table_get(r->headers_in, - "Connection"), "close"); - ap_proxy_clear_connection(p, r->headers_in); - if (p_conn->close) { - apr_table_setn(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_setn(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_setn(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_setn(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 (counter = 0; counter < headers_in_array->nelts; counter++) { - if (headers_in[counter].key == NULL || headers_in[counter].val == NULL - - /* Clear out hop-by-hop request headers not to send - * RFC2616 13.5.1 says we should strip these headers - */ - /* Already sent */ - || !apr_strnatcasecmp(headers_in[counter].key, "Host") - - || !apr_strnatcasecmp(headers_in[counter].key, "Keep-Alive") - || !apr_strnatcasecmp(headers_in[counter].key, "TE") - || !apr_strnatcasecmp(headers_in[counter].key, "Trailer") - || !apr_strnatcasecmp(headers_in[counter].key, "Transfer-Encoding") - || !apr_strnatcasecmp(headers_in[counter].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[counter].key,"Proxy-Authorization") - || !apr_strnatcasecmp(headers_in[counter].key,"Proxy-Authenticate")) { - continue; - } - - buf = apr_pstrcat(p, headers_in[counter].key, ": ", - headers_in[counter].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 ((counter = ap_get_client_block(r, buffer, sizeof(buffer))) > 0) { - e = apr_bucket_pool_create(buffer, counter, 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); - } - } - return OK; -} - -static -apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, - proxy_http_conn_t *p_conn, - conn_rec *origin, - proxy_conn_rec *backend, - proxy_server_conf *conf, - apr_bucket_brigade *bb, - char *server_portstr) { - char buffer[HUGE_STRING_LEN]; - request_rec *rp; - apr_bucket *e; - apr_status_t rv; - int eos, len, backasswards; - int received_continue = 1; /* flag to indicate if we should - * loop over response parsing logic - * in the case that the origin told us - * to HTTP_CONTINUE - */ - - /* Get response from the remote server, and pass it up the - * filter chain - */ - - rp = ap_proxy_make_fake_req(origin, r); - - while (received_continue) { - apr_brigade_cleanup(bb); - - if (APR_SUCCESS != (rv = ap_proxy_string_read(origin, bb, buffer, sizeof(buffer), &eos))) { - apr_socket_close(p_conn->sock); - backend->connection = NULL; - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, - "proxy: error reading status line from remote " - "server %s", p_conn->name); - 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(p_conn->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); - p_conn->close += 1; - } else { - /* strip connection listed hop-by-hop headers from response */ - const char *buf; - p_conn->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)) { - p_conn->close += 1; - origin->keepalive = 0; - } - } else { - /* an http/0.9 response */ - backasswards = 1; - r->status = 200; - r->status_line = "200 OK"; - p_conn->close += 1; - } - - if ( r->status != HTTP_CONTINUE ) { - received_continue = 0; - } else { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, 0, NULL, - "proxy: HTTP: received 100 CONTINUE"); - } - - /* 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_off_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 { - p_conn->close += 1; - } - - /* if keepalive cancelled, read to EOF */ - if (p_conn->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_NONBLOCKING, &readbytes) == APR_SUCCESS) { -#if DEBUGGING - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - r->server, "proxy (PID %d): readbytes: %#x", - getpid(), readbytes); -#endif - - if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) { - ap_pass_brigade(r->output_filters, bb); - break; - } - if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS) { - /* Ack! Phbtt! Die! User aborted! */ - p_conn->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"); - } - } - return OK; -} - -static -apr_status_t ap_proxy_http_cleanup(request_rec *r, proxy_http_conn_t *p_conn, - proxy_conn_rec *backend) { - /* 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 (p_conn->close || (r->proto_num < HTTP_VERSION(1,1))) { - apr_socket_close(p_conn->sock); - backend->connection = NULL; - } - return OK; -} - -/* - * 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) -{ - int status; - char server_portstr[32]; - conn_rec *origin = NULL; - 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_brigade *bb = apr_brigade_create(p); - apr_uri_t *uri = apr_palloc(r->connection->pool, sizeof(*uri)); - proxy_http_conn_t *p_conn = apr_pcalloc(r->connection->pool, - sizeof(*p_conn)); - - /* 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 */ - status = ap_proxy_http_determine_connection(p, r, p_conn, c, conf, uri, - &url, proxyname, proxyport, - server_portstr); - if ( status != OK ) { - return status; - } - - /* Step Two: Make the Connection */ - status = ap_proxy_http_create_connection(p, r, p_conn, c, &origin, backend, - conf, proxyname); - if ( status != OK ) { - return status; - } - - /* Step Three: Send the Request */ - status = ap_proxy_http_request(p, r, p_conn, origin, conf, uri, url, bb, - server_portstr); - if ( status != OK ) { - return status; - } - - /* Step Four: Receive the Response */ - status = ap_proxy_http_process_response(p, r, p_conn, origin, backend, conf, - bb, server_portstr); - if ( status != OK ) { - return status; - } - - /* Step Five: Clean Up */ - status = ap_proxy_http_cleanup(r, p_conn, backend); - if ( status != OK ) { - return status; - } - - 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 5085778d49..0000000000 --- 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 998904399e..0000000000 --- a/modules/proxy/proxy_util.c +++ /dev/null @@ -1,1059 +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 - * <http://www.apache.org/>. - * - * 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); - -/* 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 (host[i] == '\0' && (apr_inet_addr(host) == -1)) - { - 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 *)ap_proxy_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 " - "<EM><A HREF=\"", ap_escape_uri(r->pool, r->uri), - "\">", ap_escape_html(r->pool, r->method), - " ", - ap_escape_html(r->pool, r->uri), "</A></EM>.<P>\n" - "Reason: <STRONG>", - ap_escape_html(r->pool, message), - "</STRONG>", 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; -} - -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 apr_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, ip_addr[4]; - struct in_addr addr, *ip; - 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 apr_sockaddr_t *reqaddr; - - if (apr_sockaddr_info_get(&reqaddr, host, APR_UNSPEC, 0, 0, r->pool) - != APR_SUCCESS) { -#if DEBUGGING - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "2)IP-NoMatch: hostname=%s msg=Host not found", - host); -#endif - return 0; - } - - /* Try to deal with multiple IP addr's for a host */ - /* FIXME: This needs to be able to deal with IPv6 */ - while (reqaddr) { - ip = (struct in_addr *) reqaddr->ipaddr_ptr; - if (This->addr.s_addr == (ip->s_addr & This->mask.s_addr)) { -#if DEBUGGING - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "3)IP-Match: %s[%s] <-> ", host, - inet_ntoa(*ip)); - 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] <-> ", host, - inet_ntoa(*ip)); - 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 - reqaddr = reqaddr->next; - } - } - - 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; -} - -/* Return TRUE if host represents a host name */ -PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p) -{ - struct apr_sockaddr_t *addr; - char *host = This->name; - int i; - - /* Host names must not start with a '.' */ - if (host[0] == '.') - return 0; - - /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */ - for (i = 0; apr_isalnum(host[i]) || host[i] == '-' || host[i] == '.'; ++i); - - if (host[i] != '\0' || apr_sockaddr_info_get(&addr, host, APR_UNSPEC, 0, 0, p) != APR_SUCCESS) - return 0; - - This->hostaddr = addr; - - /* Strip trailing dots */ - for (i = strlen(host) - 1; i > 0 && host[i] == '.'; --i) - host[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 - struct apr_sockaddr_t *addr = *This->hostaddr; - - /* Try to deal with multiple IP addr's for a host */ - while (addr) { - if (addr->ipaddr_ptr == ? ? ? ? ? ? ? ? ? ? ? ? ?) - return 1; - addr = addr->next; - } -#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_off_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; - } - } -} diff --git a/modules/test/mod_optional_fn_export.c b/modules/test/mod_optional_fn_export.c deleted file mode 100644 index aea030e3fc..0000000000 --- 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 - * <http://www.apache.org/>. - */ - -#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 a1950f373b..0000000000 --- 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 72222105cb..0000000000 --- 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 - * <http://www.apache.org/>. - */ - -#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 e4e3c6493d..0000000000 --- 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 - * <http://www.apache.org/>. - */ - -#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 e96418738b..0000000000 --- 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 - * <http://www.apache.org/>. - */ - -#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 3c5de7809d..0000000000 --- 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 - * <http://www.apache.org/>. - */ - -#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 84df257214..0000000000 --- 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 374f130646..0000000000 --- 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 bd179baed9..0000000000 --- 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 c1bbf0ae8f..0000000000 --- a/server/mpm/experimental/perchild/mpm.h +++ /dev/null @@ -1,99 +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 - * <http://www.apache.org/>. - * - * 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_WANT_RECLAIM_CHILD_PROCESSES -#define AP_MPM_WANT_WAIT_OR_TIMEOUT -#define AP_MPM_WANT_PROCESS_CHILD_STATUS -#define AP_MPM_WANT_SET_PIDFILE -#define AP_MPM_WANT_SET_SCOREBOARD -#define AP_MPM_WANT_SET_LOCKFILE -#define AP_MPM_WANT_SET_MAX_REQUESTS -#define AP_MPM_WANT_SET_COREDUMPDIR -#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH - -#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; - -#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 f462ea8f90..0000000000 --- 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 - * <http://www.apache.org/>. - * - * 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 e5ef157ed5..0000000000 --- a/server/mpm/experimental/perchild/perchild.c +++ /dev/null @@ -1,1772 +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 - * <http://www.apache.org/>. - * - * 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 <unistd.h> -#endif -#if APR_HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#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 <poll.h> -#include <grp.h> -#include <pwd.h> -#include <sys/stat.h> -#include <sys/un.h> -#include <setjmp.h> -#ifdef HAVE_SYS_PROCESSOR_H -#include <sys/processor.h> /* 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 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; - -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; -#endif /* NO_SERIALIZED_ACCEPT */ -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_DAEMON_USED: - *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; - case AP_MPMQ_MAX_DAEMONS: - *result = num_daemons; - 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(apr_thread_t *, 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(apr_thread_t *thd, 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; - volatile int last_pollfd = 0; - volatile int thread_just_started = 1; - int srv; - int curr_pollfd; - 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; - - 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, ap_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 */ - ap_lock_fname = apr_psprintf(_pconf, "%s.%u", - ap_server_root_relative(_pconf, ap_lock_fname), - my_pid); - rv = SAFE_ACCEPT(apr_lock_create_np(&process_accept_mutex, APR_MUTEX, - APR_CROSS_PROCESS, ap_accept_lock_mech, - ap_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_run_pre_mpm(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; - ap_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; - apr_off_t 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_off_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_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_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 command_rec perchild_cmds[] = { -UNIX_DAEMON_COMMANDS -LISTEN_COMMANDS -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_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."), -{ 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/support/dbmmanage b/support/dbmmanage deleted file mode 100644 index ad9a4aca76..0000000000 --- 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 -# <http://www.apache.org/>. -# - -#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 <DBMfile> <command> <user> <password> <groups> <comment> - -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 <<SYNTAX; -Usage: dbmmanage [enc] dbname command [username [pw [group[,group] [comment]]]] - - where enc is -d for crypt encryption (default except on Win32, Netware) - -m for MD5 encryption (default on Win32, Netware) - -s for SHA1 encryption - -p for plaintext - - command is one of: $cmds - - pw of . for update command retains the old password - pw of - (or blank) for update command prompts for the password - - groups or comment of . (or blank) for update command retains old values - groups or comment of - for update command clears the existing value - groups or comment of - for add and adduser commands is the empty value -SYNTAX -} - -sub need_sha1_crypt { - if (!eval ('require "Digest/SHA1.pm";')) { - print STDERR <<SHAERR; -dbmmanage SHA1 passwords require the interface or the module Digest::SHA1 -available from CPAN: - - http://www.cpan.org/modules/by-module/Digest/Digest-MD5-2.12.tar.gz - -Please install Digest::SHA1 and try again, or use a different crypt option: - -SHAERR - usage(); - } -} - -sub need_md5_crypt { - if (!eval ('require "Crypt/PasswdMD5.pm";')) { - print STDERR <<MD5ERR; -dbmmanage MD5 passwords require the module Crypt::PasswdMD5 available from CPAN - - http://www.cpan.org/modules/by-module/Crypt/Crypt-PasswdMD5-1.1.tar.gz - -Please install Crypt::PasswdMD5 and try again, or use a different crypt option: - -MD5ERR - usage(); - } -} - -# if your osname is in $newstyle_salt, then use new style salt (starts with '_' and contains -# four bytes of iteration count and four bytes of salt). Otherwise, just use -# the traditional two-byte salt. -# see the man page on your system to decide if you have a newer crypt() lib. -# I believe that 4.4BSD derived systems do (at least BSD/OS 2.0 does). -# The new style crypt() allows up to 20 characters of the password to be -# significant rather than only 8. -# -my $newstyle_salt_platforms = join '|', qw{bsdos}; #others? -my $newstyle_salt = $^O =~ /(?:$newstyle_salt_platforms)/; - -# Some platforms just can't crypt() for Apache -# -my $crypt_not_supported_platforms = join '|', qw{MSWin32 NetWare}; #others? -my $crypt_not_supported = $^O =~ /(?:$crypt_not_supported_platforms)/; - -my $crypt_method = "crypt"; - -if ($crypt_not_supported) { - $crypt_method = "md5"; -} - -# Some platforms won't jump through our favorite hoops -# -my $not_unix_platforms = join '|', qw{MSWin32 NetWare}; #others? -my $not_unix = $^O =~ /(?:$not_unix_platforms)/; - -if ($crypt_not_supported) { - $crypt_method = "md5"; -} - -if (@ARGV[0] eq "-d") { - shift @ARGV; - if ($crypt_not_supported) { - print STDERR - "Warning: Apache/$^O does not support crypt()ed passwords!\n\n"; - } - $crypt_method = "crypt"; -} - -if (@ARGV[0] eq "-m") { - shift @ARGV; - $crypt_method = "md5"; -} - -if (@ARGV[0] eq "-p") { - shift @ARGV; - if (!$crypt_not_supported) { - print STDERR - "Warning: Apache/$^O does not support plaintext passwords!\n\n"; - } - $crypt_method = "plain"; -} - -if (@ARGV[0] eq "-s") { - shift @ARGV; - need_sha1_crypt(); - $crypt_method = "sha1"; -} - -if ($crypt_method eq "md5") { - need_md5_crypt(); -} - -my($file,$command,$key,$crypted_pwd,$groups,$comment) = @ARGV; - -usage() unless $file and $command and defined &{$dbmc::{$command}}; - -# remove extension if any -my $chop = join '|', qw{db.? pag dir}; -$file =~ s/\.($chop)$//; - -my $is_update = $command eq "update"; -my %DB = (); -my @range = (); -my($mode, $flags) = $command =~ - /^(?:view|check)$/ ? (0644, O_RDONLY) : (0644, O_RDWR|O_CREAT); - -tie (%DB, "AnyDBM_File", $file, $flags, $mode) || die "Can't tie $file: $!"; -dbmc->$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($_ = <STDIN>) 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 e32280c912..0000000000 --- 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 -# <http://www.apache.org/>. -# -# 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 (<S>) { - $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 ab5a7322ab..0000000000 --- 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 -# <http://www.apache.org/>. -# -# logresolve.pl -# -# v 1.2 by robh @ imdb.com -# -# usage: logresolve.pl <infile >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 <luuk_de_boer@pi.net> - -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(<STDIN>) { - @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 ($_ = <STDIN>)); - - ## 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 87543ce5f4..0000000000 --- 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 "<Location /cgi-bin/phf*>" 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<BLINK>Smile, you're on Candid Camera.</BLINK>\n"; diff --git a/support/split-logfile b/support/split-logfile deleted file mode 100644 index c0f34861aa..0000000000 --- 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 -# <http://www.apache.org/>. - -# 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 = <STDIN>) { - # - # 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; |