]> granicus.if.org Git - apache/blob - modules/http/http_protocol.c
Change ap_bread's interface to no longer require errno.
[apache] / modules / http / http_protocol.c
1 /* ====================================================================
2  * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  *    software must display the following acknowledgment:
18  *    "This product includes software developed by the Apache Group
19  *    for use in the Apache HTTP server project (http://www.apache.org/)."
20  *
21  * 4. The names "Apache Server" and "Apache Group" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For written permission, please contact
24  *    apache@apache.org.
25  *
26  * 5. Products derived from this software may not be called "Apache"
27  *    nor may "Apache" appear in their names without prior written
28  *    permission of the Apache Group.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  *    acknowledgment:
32  *    "This product includes software developed by the Apache Group
33  *    for use in the Apache HTTP server project (http://www.apache.org/)."
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Group and was originally based
51  * on public domain software written at the National Center for
52  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
53  * For more information on the Apache Group and the Apache HTTP server
54  * project, please see <http://www.apache.org/>.
55  *
56  */
57
58 /*
59  * http_protocol.c --- routines which directly communicate with the client.
60  *
61  * Code originally by Rob McCool; much redone by Robert S. Thau
62  * and the Apache Group.
63  */
64
65 #define CORE_PRIVATE
66 #include "httpd.h"
67 #include "http_config.h"
68 #include "http_core.h"
69 #include "http_protocol.h"
70 #include "http_main.h"
71 #include "http_request.h"
72 #include "http_vhost.h"
73 #include "http_log.h"           /* For errors detected in basic auth common
74                                  * support code... */
75 #include "util_date.h"          /* For parseHTTPdate and BAD_DATE */
76 #include "mpm_status.h"
77 #include <stdarg.h>
78
79 HOOK_STRUCT(
80             HOOK_LINK(post_read_request)
81             HOOK_LINK(log_transaction)
82             HOOK_LINK(http_method)
83             HOOK_LINK(default_port)
84 )
85
86 #define SET_BYTES_SENT(r) \
87   do { if (r->sent_bodyct) \
88           ap_bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
89   } while (0)
90
91
92 static int parse_byterange(char *range, long clength, long *start, long *end)
93 {
94     char *dash = strchr(range, '-');
95
96     if (!dash)
97         return 0;
98
99     if ((dash == range)) {
100         /* In the form "-5" */
101         *start = clength - atol(dash + 1);
102         *end = clength - 1;
103     }
104     else {
105         *dash = '\0';
106         dash++;
107         *start = atol(range);
108         if (*dash)
109             *end = atol(dash);
110         else                    /* "5-" */
111             *end = clength - 1;
112     }
113
114     if (*start < 0)
115         *start = 0;
116
117     if (*end >= clength)
118         *end = clength - 1;
119
120     if (*start > *end)
121         return 0;
122
123     return (*start > 0 || *end < clength - 1);
124 }
125
126 static int internal_byterange(int, long *, request_rec *, const char **,
127                               ap_off_t *, long *);
128
129 API_EXPORT(int) ap_set_byterange(request_rec *r)
130 {
131     const char *range, *if_range, *match;
132     long range_start, range_end;
133
134     if (!r->clength || r->assbackwards)
135         return 0;
136
137     /* Check for Range request-header (HTTP/1.1) or Request-Range for
138      * backwards-compatibility with second-draft Luotonen/Franks
139      * byte-ranges (e.g. Netscape Navigator 2-3).
140      *
141      * We support this form, with Request-Range, and (farther down) we
142      * send multipart/x-byteranges instead of multipart/byteranges for
143      * Request-Range based requests to work around a bug in Netscape
144      * Navigator 2-3 and MSIE 3.
145      */
146
147     if (!(range = ap_table_get(r->headers_in, "Range")))
148         range = ap_table_get(r->headers_in, "Request-Range");
149
150     if (!range || strncasecmp(range, "bytes=", 6)) {
151         return 0;
152     }
153
154     /* Check the If-Range header for Etag or Date.
155      * Note that this check will return false (as required) if either
156      * of the two etags are weak.
157      */
158     if ((if_range = ap_table_get(r->headers_in, "If-Range"))) {
159         if (if_range[0] == '"') {
160             if (!(match = ap_table_get(r->headers_out, "Etag")) ||
161                 (strcmp(if_range, match) != 0))
162                 return 0;
163         }
164         else if (!(match = ap_table_get(r->headers_out, "Last-Modified")) ||
165                  (strcmp(if_range, match) != 0))
166             return 0;
167     }
168
169     if (!strchr(range, ',')) {
170         /* A single range */
171         if (!parse_byterange(ap_pstrdup(r->pool, range + 6), r->clength,
172                              &range_start, &range_end))
173             return 0;
174
175         r->byterange = 1;
176
177         ap_table_setn(r->headers_out, "Content-Range",
178             ap_psprintf(r->pool, "bytes %ld-%ld/%ld",
179                 range_start, range_end, r->clength));
180         ap_table_setn(r->headers_out, "Content-Length",
181             ap_psprintf(r->pool, "%ld", range_end - range_start + 1));
182     }
183     else {
184         /* a multiple range */
185         const char *r_range = ap_pstrdup(r->pool, range + 6);
186         long tlength = 0;
187
188         r->byterange = 2;
189         r->boundary = ap_psprintf(r->pool, "%lx%lx",
190                                 r->request_time, (long) getpid());
191         while (internal_byterange(0, &tlength, r, &r_range, NULL, NULL));
192         ap_table_setn(r->headers_out, "Content-Length",
193             ap_psprintf(r->pool, "%ld", tlength));
194     }
195
196     r->status = PARTIAL_CONTENT;
197     r->range = range + 6;
198
199     return 1;
200 }
201
202 API_EXPORT(int) ap_each_byterange(request_rec *r, ap_off_t *offset,
203                                   long *length)
204 {
205     return internal_byterange(1, NULL, r, &r->range, offset, length);
206 }
207
208 /* If this function is called with realreq=1, it will spit out
209  * the correct headers for a byterange chunk, and set offset and
210  * length to the positions they should be.
211  *
212  * If it is called with realreq=0, it will add to tlength the length
213  * it *would* have used with realreq=1.
214  *
215  * Either case will return 1 if it should be called again, and 0
216  * when done.
217  */
218 static int internal_byterange(int realreq, long *tlength, request_rec *r,
219                               const char **r_range, ap_off_t *offset,
220                               long *length)
221 {
222     long range_start, range_end;
223     char *range;
224
225     if (!**r_range) {
226         if (r->byterange > 1) {
227             if (realreq)
228                 ap_rvputs(r, "\015\012--", r->boundary, "--\015\012", NULL);
229             else
230                 *tlength += 4 + strlen(r->boundary) + 4;
231         }
232         return 0;
233     }
234
235     range = ap_getword(r->pool, r_range, ',');
236     if (!parse_byterange(range, r->clength, &range_start, &range_end))
237         /* Skip this one */
238         return internal_byterange(realreq, tlength, r, r_range, offset,
239                                   length);
240
241     if (r->byterange > 1) {
242         const char *ct = r->content_type ? r->content_type : ap_default_type(r);
243         char ts[MAX_STRING_LEN];
244
245         ap_snprintf(ts, sizeof(ts), "%ld-%ld/%ld", range_start, range_end,
246                     r->clength);
247         if (realreq)
248             ap_rvputs(r, "\015\012--", r->boundary, "\015\012Content-type: ",
249                    ct, "\015\012Content-range: bytes ", ts, "\015\012\015\012",
250                    NULL);
251         else
252             *tlength += 4 + strlen(r->boundary) + 16 + strlen(ct) + 23 +
253                         strlen(ts) + 4;
254     }
255
256     if (realreq) {
257         *offset = range_start;
258         *length = range_end - range_start + 1;
259     }
260     else {
261         *tlength += range_end - range_start + 1;
262     }
263     return 1;
264 }
265
266 API_EXPORT(int) ap_set_content_length(request_rec *r, long clength)
267 {
268     r->clength = clength;
269     ap_table_setn(r->headers_out, "Content-Length", ap_psprintf(r->pool, "%ld", clength));
270     return 0;
271 }
272
273 API_EXPORT(int) ap_set_keepalive(request_rec *r)
274 {
275     int ka_sent = 0;
276     int wimpy = ap_find_token(r->pool,
277                            ap_table_get(r->headers_out, "Connection"), "close");
278     const char *conn = ap_table_get(r->headers_in, "Connection");
279
280     /* The following convoluted conditional determines whether or not
281      * the current connection should remain persistent after this response
282      * (a.k.a. HTTP Keep-Alive) and whether or not the output message
283      * body should use the HTTP/1.1 chunked transfer-coding.  In English,
284      *
285      *   IF  we have not marked this connection as errored;
286      *   and the response body has a defined length due to the status code
287      *       being 304 or 204, the request method being HEAD, already
288      *       having defined Content-Length or Transfer-Encoding: chunked, or
289      *       the request version being HTTP/1.1 and thus capable of being set
290      *       as chunked [we know the (r->chunked = 1) side-effect is ugly];
291      *   and the server configuration enables keep-alive;
292      *   and the server configuration has a reasonable inter-request timeout;
293      *   and there is no maximum # requests or the max hasn't been reached;
294      *   and the response status does not require a close;
295      *   and the response generator has not already indicated close;
296      *   and the client did not request non-persistence (Connection: close);
297      *   and    we haven't been configured to ignore the buggy twit
298      *       or they're a buggy twit coming through a HTTP/1.1 proxy
299      *   and    the client is requesting an HTTP/1.0-style keep-alive
300      *       or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
301      *   THEN we can be persistent, which requires more headers be output.
302      *
303      * Note that the condition evaluation order is extremely important.
304      */
305     if ((r->connection->keepalive != -1) &&
306         ((r->status == HTTP_NOT_MODIFIED) ||
307          (r->status == HTTP_NO_CONTENT) ||
308          r->header_only ||
309          ap_table_get(r->headers_out, "Content-Length") ||
310          ap_find_last_token(r->pool,
311                          ap_table_get(r->headers_out, "Transfer-Encoding"),
312                          "chunked") ||
313          ((r->proto_num >= HTTP_VERSION(1,1)) &&
314           (r->chunked = 1))) && /* THIS CODE IS CORRECT, see comment above. */
315         r->server->keep_alive &&
316         /* ZZZ change to APR keepalive timeout defined value */
317         (r->server->keep_alive_timeout > 0) &&
318         ((r->server->keep_alive_max == 0) ||
319          (r->server->keep_alive_max > r->connection->keepalives)) &&
320         !ap_status_drops_connection(r->status) &&
321         !wimpy &&
322         !ap_find_token(r->pool, conn, "close") &&
323         (!ap_table_get(r->subprocess_env, "nokeepalive") ||
324          ap_table_get(r->headers_in, "Via")) &&
325         ((ka_sent = ap_find_token(r->pool, conn, "keep-alive")) ||
326          (r->proto_num >= HTTP_VERSION(1,1)))
327        ) {
328         int left = r->server->keep_alive_max - r->connection->keepalives;
329
330         r->connection->keepalive = 1;
331         r->connection->keepalives++;
332
333         /* If they sent a Keep-Alive token, send one back */
334         if (ka_sent) {
335             if (r->server->keep_alive_max)
336                 ap_table_setn(r->headers_out, "Keep-Alive",
337                     ap_psprintf(r->pool, "timeout=%d, max=%d",
338                             r->server->keep_alive_timeout, left));
339             else
340                 ap_table_setn(r->headers_out, "Keep-Alive",
341                     ap_psprintf(r->pool, "timeout=%d",
342                             r->server->keep_alive_timeout));
343             ap_table_mergen(r->headers_out, "Connection", "Keep-Alive");
344         }
345
346         return 1;
347     }
348
349     /* Otherwise, we need to indicate that we will be closing this
350      * connection immediately after the current response.
351      *
352      * We only really need to send "close" to HTTP/1.1 clients, but we
353      * always send it anyway, because a broken proxy may identify itself
354      * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
355      * to a HTTP/1.1 client. Better safe than sorry.
356      */
357     if (!wimpy)
358         ap_table_mergen(r->headers_out, "Connection", "close");
359
360     r->connection->keepalive = 0;
361
362     return 0;
363 }
364
365 /*
366  * Return the latest rational time from a request/mtime (modification time)
367  * pair.  We return the mtime unless it's in the future, in which case we
368  * return the current time.  We use the request time as a reference in order
369  * to limit the number of calls to time().  We don't check for futurosity
370  * unless the mtime is at least as new as the reference.
371  */
372 API_EXPORT(time_t) ap_rationalize_mtime(request_rec *r, time_t mtime)
373 {
374     time_t now;
375
376     /* For all static responses, it's almost certain that the file was
377      * last modified before the beginning of the request.  So there's
378      * no reason to call time(NULL) again.  But if the response has been
379      * created on demand, then it might be newer than the time the request
380      * started.  In this event we really have to call time(NULL) again
381      * so that we can give the clients the most accurate Last-Modified.  If we
382      * were given a time in the future, we return the current time - the
383      * Last-Modified can't be in the future.
384      */
385     /* ZZZ Change time call to use time AP time thread functions. */
386     now = (mtime < r->request_time) ? r->request_time : time(NULL);
387     return (mtime > now) ? now : mtime;
388 }
389
390 API_EXPORT(int) ap_meets_conditions(request_rec *r)
391 {
392     const char *etag = ap_table_get(r->headers_out, "ETag");
393     const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
394     time_t mtime;
395
396     /* Check for conditional requests --- note that we only want to do
397      * this if we are successful so far and we are not processing a
398      * subrequest or an ErrorDocument.
399      *
400      * The order of the checks is important, since ETag checks are supposed
401      * to be more accurate than checks relative to the modification time.
402      * However, not all documents are guaranteed to *have* ETags, and some
403      * might have Last-Modified values w/o ETags, so this gets a little
404      * complicated.
405      */
406
407     if (!ap_is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
408         return OK;
409     }
410
411     /* ZZZ We are changing time(NULL) to AP time thread functions. */
412     mtime = (r->mtime != 0) ? r->mtime : time(NULL);
413
414     /* If an If-Match request-header field was given
415      * AND the field value is not "*" (meaning match anything)
416      * AND if our strong ETag does not match any entity tag in that field,
417      *     respond with a status of 412 (Precondition Failed).
418      */
419     if ((if_match = ap_table_get(r->headers_in, "If-Match")) != NULL) {
420         if (if_match[0] != '*' &&
421             (etag == NULL || etag[0] == 'W' ||
422              !ap_find_list_item(r->pool, if_match, etag))) {
423             return HTTP_PRECONDITION_FAILED;
424         }
425     }
426     else {
427         /* Else if a valid If-Unmodified-Since request-header field was given
428          * AND the requested resource has been modified since the time
429          * specified in this field, then the server MUST
430          *     respond with a status of 412 (Precondition Failed).
431          */
432         if_unmodified = ap_table_get(r->headers_in, "If-Unmodified-Since");
433         if (if_unmodified != NULL) {
434             time_t ius = ap_parseHTTPdate(if_unmodified);
435
436             if ((ius != BAD_DATE) && (mtime > ius)) {
437                 return HTTP_PRECONDITION_FAILED;
438             }
439         }
440     }
441
442     /* If an If-None-Match request-header field was given
443      * AND the field value is "*" (meaning match anything)
444      *     OR our ETag matches any of the entity tags in that field, fail.
445      *
446      * If the request method was GET or HEAD, failure means the server
447      *    SHOULD respond with a 304 (Not Modified) response.
448      * For all other request methods, failure means the server MUST
449      *    respond with a status of 412 (Precondition Failed).
450      *
451      * GET or HEAD allow weak etag comparison, all other methods require
452      * strong comparison.  We can only use weak if it's not a range request.
453      */
454     if_nonematch = ap_table_get(r->headers_in, "If-None-Match");
455     if (if_nonematch != NULL) {
456         if (r->method_number == M_GET) {
457             if (if_nonematch[0] == '*')
458                 return HTTP_NOT_MODIFIED;
459             if (etag != NULL) {
460                 if (ap_table_get(r->headers_in, "Range")) {
461                     if (etag[0] != 'W' &&
462                         ap_find_list_item(r->pool, if_nonematch, etag)) {
463                         return HTTP_NOT_MODIFIED;
464                     }
465                 }
466                 else if (strstr(if_nonematch, etag)) {
467                     return HTTP_NOT_MODIFIED;
468                 }
469             }
470         }
471         else if (if_nonematch[0] == '*' ||
472                  (etag != NULL &&
473                   ap_find_list_item(r->pool, if_nonematch, etag))) {
474             return HTTP_PRECONDITION_FAILED;
475         }
476     }
477     /* Else if a valid If-Modified-Since request-header field was given
478      * AND it is a GET or HEAD request
479      * AND the requested resource has not been modified since the time
480      * specified in this field, then the server MUST
481      *    respond with a status of 304 (Not Modified).
482      * A date later than the server's current request time is invalid.
483      */
484     else if ((r->method_number == M_GET)
485              && ((if_modified_since =
486                   ap_table_get(r->headers_in, "If-Modified-Since")) != NULL)) {
487         time_t ims = ap_parseHTTPdate(if_modified_since);
488
489         if ((ims >= mtime) && (ims <= r->request_time)) {
490             return HTTP_NOT_MODIFIED;
491         }
492     }
493     return OK;
494 }
495
496 /*
497  * Construct an entity tag (ETag) from resource information.  If it's a real
498  * file, build in some of the file characteristics.  If the modification time
499  * is newer than (request-time minus 1 second), mark the ETag as weak - it
500  * could be modified again in as short an interval.  We rationalize the
501  * modification time we're given to keep it from being in the future.
502  */
503 API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak)
504 {
505     char *etag;
506     char *weak;
507
508     /*
509      * Make an ETag header out of various pieces of information. We use
510      * the last-modified date and, if we have a real file, the
511      * length and inode number - note that this doesn't have to match
512      * the content-length (i.e. includes), it just has to be unique
513      * for the file.
514      *
515      * If the request was made within a second of the last-modified date,
516      * we send a weak tag instead of a strong one, since it could
517      * be modified again later in the second, and the validation
518      * would be incorrect.
519      */
520     
521     weak = ((r->request_time - r->mtime > 1) && !force_weak) ? "" : "W/";
522
523     if (r->finfo.st_mode != 0) {
524         etag = ap_psprintf(r->pool,
525                     "%s\"%lx-%lx-%lx\"", weak,
526                     (unsigned long) r->finfo.st_ino,
527                     (unsigned long) r->finfo.st_size,
528                     (unsigned long) r->mtime);
529     }
530     else {
531         etag = ap_psprintf(r->pool, "%s\"%lx\"", weak,
532                     (unsigned long) r->mtime);
533     }
534
535     return etag;
536 }
537
538 API_EXPORT(void) ap_set_etag(request_rec *r)
539 {
540     char *etag;
541     char *variant_etag, *vlv;
542     int vlv_weak;
543
544     if (!r->vlist_validator) {
545         etag = ap_make_etag(r, 0);
546     }
547     else {
548         /* If we have a variant list validator (vlv) due to the
549          * response being negotiated, then we create a structured
550          * entity tag which merges the variant etag with the variant
551          * list validator (vlv).  This merging makes revalidation
552          * somewhat safer, ensures that caches which can deal with
553          * Vary will (eventually) be updated if the set of variants is
554          * changed, and is also a protocol requirement for transparent
555          * content negotiation.
556          */
557
558         /* if the variant list validator is weak, we make the whole
559          * structured etag weak.  If we would not, then clients could
560          * have problems merging range responses if we have different
561          * variants with the same non-globally-unique strong etag.
562          */
563
564         vlv = r->vlist_validator;
565         vlv_weak = (vlv[0] == 'W');
566                
567         variant_etag = ap_make_etag(r, vlv_weak);
568
569         /* merge variant_etag and vlv into a structured etag */
570
571         variant_etag[strlen(variant_etag) - 1] = '\0';
572         if (vlv_weak)
573             vlv += 3;
574         else
575             vlv++;
576         etag = ap_pstrcat(r->pool, variant_etag, ";", vlv, NULL);
577     }
578
579     ap_table_setn(r->headers_out, "ETag", etag);
580 }
581
582 /*
583  * This function sets the Last-Modified output header field to the value
584  * of the mtime field in the request structure - rationalized to keep it from
585  * being in the future.
586  */
587 API_EXPORT(void) ap_set_last_modified(request_rec *r)
588 {
589     time_t mod_time = ap_rationalize_mtime(r, r->mtime);
590
591     ap_table_setn(r->headers_out, "Last-Modified",
592               ap_gm_timestr_822(r->pool, mod_time));
593 }
594
595 /* Get the method number associated with the given string, assumed to
596  * contain an HTTP method.  Returns M_INVALID if not recognized.
597  *
598  * This is the first step toward placing method names in a configurable
599  * list.  Hopefully it (and other routines) can eventually be moved to
600  * something like a mod_http_methods.c, complete with config stuff.
601  */
602 API_EXPORT(int) ap_method_number_of(const char *method)
603 {
604     switch (*method) {
605         case 'H':
606            if (strcmp(method, "HEAD") == 0)
607                return M_GET;   /* see header_only in request_rec */
608            break;
609         case 'G':
610            if (strcmp(method, "GET") == 0)
611                return M_GET;
612            break;
613         case 'P':
614            if (strcmp(method, "POST") == 0)
615                return M_POST;
616            if (strcmp(method, "PUT") == 0)
617                return M_PUT;
618            if (strcmp(method, "PATCH") == 0)
619                return M_PATCH;
620            if (strcmp(method, "PROPFIND") == 0)
621                return M_PROPFIND;
622            if (strcmp(method, "PROPPATCH") == 0)
623                return M_PROPPATCH;
624            break;
625         case 'D':
626            if (strcmp(method, "DELETE") == 0)
627                return M_DELETE;
628            break;
629         case 'C':
630            if (strcmp(method, "CONNECT") == 0)
631                return M_CONNECT;
632            if (strcmp(method, "COPY") == 0)
633                return M_COPY;
634            break;
635         case 'M':
636            if (strcmp(method, "MKCOL") == 0)
637                return M_MKCOL;
638            if (strcmp(method, "MOVE") == 0)
639                return M_MOVE;
640            break;
641         case 'O':
642            if (strcmp(method, "OPTIONS") == 0)
643                return M_OPTIONS;
644            break;
645         case 'T':
646            if (strcmp(method, "TRACE") == 0)
647                return M_TRACE;
648            break;
649         case 'L':
650            if (strcmp(method, "LOCK") == 0)
651                return M_LOCK;
652            break;
653         case 'U':
654            if (strcmp(method, "UNLOCK") == 0)
655                return M_UNLOCK;
656            break;
657     }
658     return M_INVALID;
659 }
660
661 /* Get a line of protocol input, including any continuation lines
662  * caused by MIME folding (or broken clients) if fold != 0, and place it
663  * in the buffer s, of size n bytes, without the ending newline.
664  *
665  * Returns -1 on error, or the length of s.
666  *
667  * Note: Because bgets uses 1 char for newline and 1 char for NUL,
668  *       the most we can get is (n - 2) actual characters if it
669  *       was ended by a newline, or (n - 1) characters if the line
670  *       length exceeded (n - 1).  So, if the result == (n - 1),
671  *       then the actual input line exceeded the buffer length,
672  *       and it would be a good idea for the caller to puke 400 or 414.
673  */
674 static int getline(char *s, int n, BUFF *in, int fold)
675 {
676     char *pos, next;
677     int retval;
678     int total = 0;
679
680     pos = s;
681
682     do {
683         retval = ap_bgets(pos, n, in);
684        /* retval == -1 if error, 0 if EOF */
685
686         if (retval <= 0)
687             return ((retval < 0) && (total == 0)) ? -1 : total;
688
689         /* retval is the number of characters read, not including NUL      */
690
691         n -= retval;            /* Keep track of how much of s is full     */
692         pos += (retval - 1);    /* and where s ends                        */
693         total += retval;        /* and how long s has become               */
694
695         if (*pos == '\n') {     /* Did we get a full line of input?        */
696             /*
697              * Trim any extra trailing spaces or tabs except for the first
698              * space or tab at the beginning of a blank string.  This makes
699              * it much easier to check field values for exact matches, and
700              * saves memory as well.  Terminate string at end of line.
701              */
702             while (pos > (s + 1) && (*(pos - 1) == ' ' || *(pos - 1) == '\t')) {
703                 --pos;          /* trim extra trailing spaces or tabs      */
704                 --total;        /* but not one at the beginning of line    */
705                 ++n;
706             }
707             *pos = '\0';
708             --total;
709             ++n;
710         }
711         else
712             return total;       /* if not, input line exceeded buffer size */
713
714         /* Continue appending if line folding is desired and
715          * the last line was not empty and we have room in the buffer and
716          * the next line begins with a continuation character.
717          */
718     } while (fold && (retval != 1) && (n > 1)
719                   && (next = ap_blookc(in))
720                   && ((next == ' ') || (next == '\t')));
721
722     return total;
723 }
724
725 /* parse_uri: break apart the uri
726  * Side Effects:
727  * - sets r->args to rest after '?' (or NULL if no '?')
728  * - sets r->uri to request uri (without r->args part)
729  * - sets r->hostname (if not set already) from request (scheme://host:port)
730  */
731 CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri)
732 {
733     int status = HTTP_OK;
734
735     r->unparsed_uri = ap_pstrdup(r->pool, uri);
736
737     if (r->method_number == M_CONNECT) {
738         status = ap_parse_hostinfo_components(r->pool, uri, &r->parsed_uri);
739     } else {
740         /* Simple syntax Errors in URLs are trapped by parse_uri_components(). */
741         status = ap_parse_uri_components(r->pool, uri, &r->parsed_uri);
742     }
743
744     if (ap_is_HTTP_SUCCESS(status)) {
745         /* if it has a scheme we may need to do absoluteURI vhost stuff */
746         if (r->parsed_uri.scheme
747             && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r))) {
748             r->hostname = r->parsed_uri.hostname;
749         } else if (r->method_number == M_CONNECT) {
750             r->hostname = r->parsed_uri.hostname;
751         }
752         r->args = r->parsed_uri.query;
753         r->uri = r->parsed_uri.path ? r->parsed_uri.path
754                                     : ap_pstrdup(r->pool, "/");
755 #if defined(OS2) || defined(WIN32)
756         /* Handle path translations for OS/2 and plug security hole.
757          * This will prevent "http://www.wherever.com/..\..\/" from
758          * returning a directory for the root drive.
759          */
760         {
761             char *x;
762
763             for (x = r->uri; (x = strchr(x, '\\')) != NULL; )
764                 *x = '/';
765         }
766 #endif  /* OS2 || WIN32 */
767     }
768     else {
769         r->args = NULL;
770         r->hostname = NULL;
771         r->status = status;             /* set error status */
772         r->uri = ap_pstrdup(r->pool, uri);
773     }
774 }
775
776 static int read_request_line(request_rec *r)
777 {
778     char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* getline's two extra for \n\0 */
779     const char *ll = l;
780     const char *uri;
781     conn_rec *conn = r->connection;
782     int major = 1, minor = 0;   /* Assume HTTP/1.0 if non-"HTTP" protocol */
783     int len;
784
785     /* Read past empty lines until we get a real request line,
786      * a read error, the connection closes (EOF), or we timeout.
787      *
788      * We skip empty lines because browsers have to tack a CRLF on to the end
789      * of POSTs to support old CERN webservers.  But note that we may not
790      * have flushed any previous response completely to the client yet.
791      * We delay the flush as long as possible so that we can improve
792      * performance for clients that are pipelining requests.  If a request
793      * is pipelined then we won't block during the (implicit) read() below.
794      * If the requests aren't pipelined, then the client is still waiting
795      * for the final buffer flush from us, and we will block in the implicit
796      * read().  B_SAFEREAD ensures that the BUFF layer flushes if it will
797      * have to block during a read.
798      */
799     /* TODO: reimplement SAFEREAD external to BUFF using a layer */
800     /* //ap_bsetflag(conn->client, B_SAFEREAD, 1); */
801     ap_bflush(conn->client);
802     while ((len = getline(l, sizeof(l), conn->client, 0)) <= 0) {
803         if ((len < 0) || ap_bgetflag(conn->client, B_EOF)) {
804             /* //ap_bsetflag(conn->client, B_SAFEREAD, 0); */
805             /* this is a hack to make sure that request time is set,
806              * it's not perfect, but it's better than nothing 
807              */
808             r->request_time = time(0);
809             return 0;
810         }
811     }
812     /* we've probably got something to do, ignore graceful restart requests */
813
814     /* XXX - sigwait doesn't work if the signal has been SIG_IGNed (under
815      * linux 2.0 w/ glibc 2.0, anyway), and this step isn't necessary when
816      * we're running a sigwait thread anyway. If/when unthreaded mode is
817      * put back in, we should make sure to ignore this signal iff a sigwait
818      * thread isn't used. - mvsk
819
820 #ifdef SIGWINCH
821     signal(SIGWINCH, SIG_IGN);
822 #endif
823     */
824
825     /* //ap_bsetflag(conn->client, B_SAFEREAD, 0); */
826
827     r->request_time = time(NULL);
828     r->the_request = ap_pstrdup(r->pool, l);
829     r->method = ap_getword_white(r->pool, &ll);
830     ap_update_connection_status(conn->id, "Method", r->method);
831     uri = ap_getword_white(r->pool, &ll);
832
833     /* Provide quick information about the request method as soon as known */
834
835     r->method_number = ap_method_number_of(r->method);
836     if (r->method_number == M_GET && r->method[0] == 'H') {
837         r->header_only = 1;
838     }
839
840     ap_parse_uri(r, uri);
841
842     /* getline returns (size of max buffer - 1) if it fills up the
843      * buffer before finding the end-of-line.  This is only going to
844      * happen if it exceeds the configured limit for a request-line.
845      */
846     if (len > r->server->limit_req_line) {
847         r->status    = HTTP_REQUEST_URI_TOO_LARGE;
848         r->proto_num = HTTP_VERSION(1,0);
849         r->protocol  = ap_pstrdup(r->pool, "HTTP/1.0");
850         return 0;
851     }
852
853     r->assbackwards = (ll[0] == '\0');
854     r->protocol = ap_pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9");
855     ap_update_connection_status(conn->id, "Protocol", r->protocol);
856
857     if (2 == sscanf(r->protocol, "HTTP/%u.%u", &major, &minor)
858       && minor < HTTP_VERSION(1,0))     /* don't allow HTTP/0.1000 */
859         r->proto_num = HTTP_VERSION(major, minor);
860     else
861         r->proto_num = HTTP_VERSION(1,0);
862
863     return 1;
864 }
865
866 static void get_mime_headers(request_rec *r)
867 {
868     char field[DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2]; /* getline's two extra */
869     conn_rec *c = r->connection;
870     char *value;
871     char *copy;
872     int len;
873     unsigned int fields_read = 0;
874     ap_table_t *tmp_headers;
875
876     /* We'll use ap_overlap_tables later to merge these into r->headers_in. */
877     tmp_headers = ap_make_table(r->pool, 50);
878
879     /*
880      * Read header lines until we get the empty separator line, a read error,
881      * the connection closes (EOF), reach the server limit, or we timeout.
882      */
883     while ((len = getline(field, sizeof(field), c->client, 1)) > 0) {
884
885         if (r->server->limit_req_fields &&
886             (++fields_read > r->server->limit_req_fields)) {
887             r->status = HTTP_BAD_REQUEST;
888             ap_table_setn(r->notes, "error-notes",
889                           "The number of request header fields exceeds "
890                           "this server's limit.<P>\n");
891             return;
892         }
893         /* getline returns (size of max buffer - 1) if it fills up the
894          * buffer before finding the end-of-line.  This is only going to
895          * happen if it exceeds the configured limit for a field size.
896          */
897         if (len > r->server->limit_req_fieldsize) {
898             r->status = HTTP_BAD_REQUEST;
899             ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
900                 "Size of a request header field exceeds server limit.<P>\n"
901                 "<PRE>\n", field, "</PRE>\n", NULL));
902             return;
903         }
904         copy = ap_palloc(r->pool, len + 1);
905         memcpy(copy, field, len + 1);
906
907         if (!(value = strchr(copy, ':'))) {     /* Find the colon separator */
908             r->status = HTTP_BAD_REQUEST;       /* or abort the bad request */
909             ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
910                 "Request header field is missing colon separator.<P>\n"
911                 "<PRE>\n", copy, "</PRE>\n", NULL));
912             return;
913         }
914
915         *value = '\0';
916         ++value;
917         while (*value == ' ' || *value == '\t')
918             ++value;            /* Skip to start of value   */
919
920         ap_table_addn(tmp_headers, copy, value);
921     }
922
923     ap_overlap_tables(r->headers_in, tmp_headers, AP_OVERLAP_TABLES_MERGE);
924 }
925
926 request_rec *ap_read_request(conn_rec *conn)
927 {
928     request_rec *r;
929     ap_context_t *p;
930     const char *expect;
931     int access_status;
932
933     ap_create_context(&p, conn->pool);
934     r = ap_pcalloc(p, sizeof(request_rec));
935     r->pool            = p;
936     r->connection      = conn;
937     r->server          = conn->base_server;
938
939     conn->keptalive    = conn->keepalive == 1;
940     conn->keepalive    = 0;
941
942     r->user            = NULL;
943     r->ap_auth_type    = NULL;
944
945     r->headers_in      = ap_make_table(r->pool, 50);
946     r->subprocess_env  = ap_make_table(r->pool, 50);
947     r->headers_out     = ap_make_table(r->pool, 12);
948     r->err_headers_out = ap_make_table(r->pool, 5);
949     r->notes           = ap_make_table(r->pool, 5);
950
951     r->request_config  = ap_create_request_config(r->pool);
952     r->per_dir_config  = r->server->lookup_defaults;
953
954     r->sent_bodyct     = 0;                      /* bytect isn't for body */
955
956     r->read_length     = 0;
957     r->read_body       = REQUEST_NO_BODY;
958
959     r->status          = HTTP_REQUEST_TIME_OUT;  /* Until we get a request */
960     r->the_request     = NULL;
961
962 #ifdef CHARSET_EBCDIC
963     ap_bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 1);
964 #endif
965
966     ap_bsetopt(conn->client, BO_TIMEOUT,
967         conn->keptalive
968             ? &r->server->keep_alive_timeout
969             : &r->server->timeout);
970
971     /* Get the request... */
972     if (!read_request_line(r)) {
973         if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
974             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
975                          "request failed: URI too long");
976             ap_send_error_response(r, 0);
977             ap_run_log_transaction(r);
978             return r;
979         }
980         return NULL;
981     }
982     if (r->connection->keptalive) {
983         ap_bsetopt(r->connection->client, BO_TIMEOUT,
984             &r->server->timeout);
985     }
986     if (!r->assbackwards) {
987         get_mime_headers(r);
988         if (r->status != HTTP_REQUEST_TIME_OUT) {
989             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
990                          "request failed: error reading the headers");
991             ap_send_error_response(r, 0);
992             ap_run_log_transaction(r);
993             return r;
994         }
995     }
996     else {
997         if (r->header_only) {
998             /*
999              * Client asked for headers only with HTTP/0.9, which doesn't send
1000              * headers! Have to dink things just to make sure the error message
1001              * comes through...
1002              */
1003             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
1004                           "client sent invalid HTTP/0.9 request: HEAD %s",
1005                           r->uri);
1006             r->header_only = 0;
1007             r->status = HTTP_BAD_REQUEST;
1008             ap_send_error_response(r, 0);
1009             ap_run_log_transaction(r);
1010             return r;
1011         }
1012     }
1013
1014     r->status = HTTP_OK;                         /* Until further notice. */
1015
1016     /* update what we think the virtual host is based on the headers we've
1017      * now read
1018      */
1019     ap_update_vhost_from_headers(r);
1020
1021     /* we may have switched to another server */
1022     r->per_dir_config = r->server->lookup_defaults;
1023
1024     conn->keptalive = 0;        /* We now have a request to play with */
1025
1026     if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1,1))) ||
1027         ((r->proto_num == HTTP_VERSION(1,1)) &&
1028          !ap_table_get(r->headers_in, "Host"))) {
1029         /*
1030          * Client sent us an HTTP/1.1 or later request without telling us the
1031          * hostname, either with a full URL or a Host: header. We therefore
1032          * need to (as per the 1.1 spec) send an error.  As a special case,
1033          * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain
1034          * a Host: header, and the server MUST respond with 400 if it doesn't.
1035          */
1036         r->status = HTTP_BAD_REQUEST;
1037         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
1038                       "client sent HTTP/1.1 request without hostname "
1039                       "(see RFC2068 section 9, and 14.23): %s", r->uri);
1040         ap_send_error_response(r, 0);
1041         ap_run_log_transaction(r);
1042         return r;
1043     }
1044     if (((expect = ap_table_get(r->headers_in, "Expect")) != NULL) &&
1045         (expect[0] != '\0')) {
1046         /*
1047          * The Expect header field was added to HTTP/1.1 after RFC 2068
1048          * as a means to signal when a 100 response is desired and,
1049          * unfortunately, to signal a poor man's mandatory extension that
1050          * the server must understand or return 417 Expectation Failed.
1051          */
1052         if (strcasecmp(expect, "100-continue") == 0) {
1053             r->expecting_100 = 1;
1054         }
1055         else {
1056             r->status = HTTP_EXPECTATION_FAILED;
1057             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
1058                           "client sent an unrecognized expectation value of "
1059                           "Expect: %s", expect);
1060             ap_send_error_response(r, 0);
1061             (void) ap_discard_request_body(r);
1062             ap_run_log_transaction(r);
1063             return r;
1064         }
1065     }
1066
1067     if ((access_status = ap_run_post_read_request(r))) {
1068         ap_die(access_status, r);
1069         ap_run_log_transaction(r);
1070         return NULL;
1071     }
1072
1073     return r;
1074 }
1075
1076 /*
1077  * A couple of other functions which initialize some of the fields of
1078  * a request structure, as appropriate for adjuncts of one kind or another
1079  * to a request in progress.  Best here, rather than elsewhere, since
1080  * *someone* has to set the protocol-specific fields...
1081  */
1082
1083 void ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r)
1084 {
1085     rnew->the_request     = r->the_request;  /* Keep original request-line */
1086
1087     rnew->assbackwards    = 1;   /* Don't send headers from this. */
1088     rnew->no_local_copy   = 1;   /* Don't try to send USE_LOCAL_COPY for a
1089                                   * fragment. */
1090     rnew->method          = "GET";
1091     rnew->method_number   = M_GET;
1092     rnew->protocol        = "INCLUDED";
1093
1094     rnew->status          = HTTP_OK;
1095
1096     rnew->headers_in      = r->headers_in;
1097     rnew->subprocess_env  = ap_copy_table(rnew->pool, r->subprocess_env);
1098     rnew->headers_out     = ap_make_table(rnew->pool, 5);
1099     rnew->err_headers_out = ap_make_table(rnew->pool, 5);
1100     rnew->notes           = ap_make_table(rnew->pool, 5);
1101
1102     rnew->expecting_100   = r->expecting_100;
1103     rnew->read_length     = r->read_length;
1104     rnew->read_body       = REQUEST_NO_BODY;
1105
1106     rnew->main = (request_rec *) r;
1107 }
1108
1109 void ap_finalize_sub_req_protocol(request_rec *sub)
1110 {
1111     SET_BYTES_SENT(sub->main);
1112 }
1113
1114 /*
1115  * Support for the Basic authentication protocol, and a bit for Digest.
1116  */
1117
1118 API_EXPORT(void) ap_note_auth_failure(request_rec *r)
1119 {
1120     if (!strcasecmp(ap_auth_type(r), "Basic"))
1121         ap_note_basic_auth_failure(r);
1122     else if (!strcasecmp(ap_auth_type(r), "Digest"))
1123         ap_note_digest_auth_failure(r);
1124 }
1125
1126 API_EXPORT(void) ap_note_basic_auth_failure(request_rec *r)
1127 {
1128     if (strcasecmp(ap_auth_type(r), "Basic"))
1129         ap_note_auth_failure(r);
1130     else
1131         ap_table_setn(r->err_headers_out,
1132                   r->proxyreq ? "Proxy-Authenticate" : "WWW-Authenticate",
1133                   ap_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r), "\"",
1134                           NULL));
1135 }
1136
1137 API_EXPORT(void) ap_note_digest_auth_failure(request_rec *r)
1138 {
1139     ap_table_setn(r->err_headers_out,
1140             r->proxyreq ? "Proxy-Authenticate" : "WWW-Authenticate",
1141             ap_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%lu\"",
1142                 ap_auth_name(r), r->request_time));
1143 }
1144
1145 API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
1146 {
1147     const char *auth_line = ap_table_get(r->headers_in,
1148                                       r->proxyreq ? "Proxy-Authorization"
1149                                                   : "Authorization");
1150     const char *t;
1151
1152     if (!(t = ap_auth_type(r)) || strcasecmp(t, "Basic"))
1153         return DECLINED;
1154
1155     if (!ap_auth_name(r)) {
1156         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
1157                     0, r, "need AuthName: %s", r->uri);
1158         return SERVER_ERROR;
1159     }
1160
1161     if (!auth_line) {
1162         ap_note_basic_auth_failure(r);
1163         return AUTH_REQUIRED;
1164     }
1165
1166     if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) {
1167         /* Client tried to authenticate using wrong auth scheme */
1168         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
1169                     "client used wrong authentication scheme: %s", r->uri);
1170         ap_note_basic_auth_failure(r);
1171         return AUTH_REQUIRED;
1172     }
1173
1174     /* CHARSET_EBCDIC Issue's here ?!? Compare with 32/9 instead
1175      * as we are operating on an octed stream ?
1176      */
1177     while (*auth_line== ' ' || *auth_line== '\t')
1178         auth_line++;
1179
1180     t = ap_pbase64decode(r->pool, auth_line);
1181     /* Note that this allocation has to be made from r->connection->pool
1182      * because it has the lifetime of the connection.  The other allocations
1183      * are temporary and can be tossed away any time.
1184      */
1185     r->user = ap_getword_nulls (r->pool, &t, ':');
1186     r->ap_auth_type = "Basic";
1187
1188     *pw = t;
1189
1190     return OK;
1191 }
1192
1193 /* New Apache routine to map status codes into array indicies
1194  *  e.g.  100 -> 0,  101 -> 1,  200 -> 2 ...
1195  * The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
1196  * and must be listed in order.
1197  */
1198
1199 #ifdef UTS21
1200 /* The second const triggers an assembler bug on UTS 2.1.
1201  * Another workaround is to move some code out of this file into another,
1202  *   but this is easier.  Dave Dykstra, 3/31/99 
1203  */
1204 static const char * status_lines[RESPONSE_CODES] =
1205 #else
1206 static const char * const status_lines[RESPONSE_CODES] =
1207 #endif
1208 {
1209     "100 Continue",
1210     "101 Switching Protocols",
1211     "102 Processing",
1212 #define LEVEL_200  3
1213     "200 OK",
1214     "201 Created",
1215     "202 Accepted",
1216     "203 Non-Authoritative Information",
1217     "204 No Content",
1218     "205 Reset Content",
1219     "206 Partial Content",
1220     "207 Multi-Status",
1221 #define LEVEL_300 11
1222     "300 Multiple Choices",
1223     "301 Moved Permanently",
1224     "302 Found",
1225     "303 See Other",
1226     "304 Not Modified",
1227     "305 Use Proxy",
1228     "306 unused",
1229     "307 Temporary Redirect",
1230 #define LEVEL_400 19
1231     "400 Bad Request",
1232     "401 Authorization Required",
1233     "402 Payment Required",
1234     "403 Forbidden",
1235     "404 Not Found",
1236     "405 Method Not Allowed",
1237     "406 Not Acceptable",
1238     "407 Proxy Authentication Required",
1239     "408 Request Time-out",
1240     "409 Conflict",
1241     "410 Gone",
1242     "411 Length Required",
1243     "412 Precondition Failed",
1244     "413 Request Entity Too Large",
1245     "414 Request-URI Too Large",
1246     "415 Unsupported Media Type",
1247     "416 Requested Range Not Satisfiable",
1248     "417 Expectation Failed",
1249     "418 unused",
1250     "419 unused",
1251     "420 unused",
1252     "421 unused",
1253     "422 Unprocessable Entity",
1254     "423 Locked",
1255     "424 Failed Dependency",
1256 #define LEVEL_500 44
1257     "500 Internal Server Error",
1258     "501 Method Not Implemented",
1259     "502 Bad Gateway",
1260     "503 Service Temporarily Unavailable",
1261     "504 Gateway Time-out",
1262     "505 HTTP Version Not Supported",
1263     "506 Variant Also Negotiates",
1264     "507 Insufficient Storage",
1265     "508 unused",
1266     "509 unused",
1267     "510 Not Extended"
1268 };
1269
1270 /* The index is found by its offset from the x00 code of each level.
1271  * Although this is fast, it will need to be replaced if some nutcase
1272  * decides to define a high-numbered code before the lower numbers.
1273  * If that sad event occurs, replace the code below with a linear search
1274  * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1];
1275  */
1276 API_EXPORT(int) ap_index_of_response(int status)
1277 {
1278     static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400,
1279     LEVEL_500, RESPONSE_CODES};
1280     int i, pos;
1281
1282     if (status < 100)           /* Below 100 is illegal for HTTP status */
1283         return LEVEL_500;
1284
1285     for (i = 0; i < 5; i++) {
1286         status -= 100;
1287         if (status < 100) {
1288             pos = (status + shortcut[i]);
1289             if (pos < shortcut[i + 1])
1290                 return pos;
1291             else
1292                 return LEVEL_500;       /* status unknown (falls in gap) */
1293         }
1294     }
1295     return LEVEL_500;           /* 600 or above is also illegal */
1296 }
1297
1298 /* Send a single HTTP header field to the client.  Note that this function
1299  * is used in calls to table_do(), so their interfaces are co-dependent.
1300  * In other words, don't change this one without checking table_do in alloc.c.
1301  * It returns true unless there was a write error of some kind.
1302  */
1303 API_EXPORT_NONSTD(int) ap_send_header_field(request_rec *r,
1304     const char *fieldname, const char *fieldval)
1305 {
1306     return (0 < ap_rvputs(r, fieldname, ": ", fieldval, "\015\012", NULL));
1307 }
1308
1309 API_EXPORT(void) ap_basic_http_header(request_rec *r)
1310 {
1311     char *protocol;
1312 #ifdef CHARSET_EBCDIC
1313     int convert = ap_bgetflag(r->connection->client, B_EBCDIC2ASCII);
1314 #endif /*CHARSET_EBCDIC*/
1315
1316     if (r->assbackwards)
1317         return;
1318
1319     if (!r->status_line)
1320         r->status_line = status_lines[ap_index_of_response(r->status)];
1321
1322     /* mod_proxy is only HTTP/1.0, so avoid sending HTTP/1.1 error response;
1323      * kluge around broken browsers when indicated by force-response-1.0
1324      */
1325     if (r->proxyreq
1326         || (r->proto_num == HTTP_VERSION(1,0)
1327             && ap_table_get(r->subprocess_env, "force-response-1.0"))) {
1328
1329         protocol = "HTTP/1.0";
1330         r->connection->keepalive = -1;
1331     }
1332     else
1333         protocol = SERVER_PROTOCOL;
1334
1335 #ifdef CHARSET_EBCDIC
1336     ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, 1);
1337 #endif /*CHARSET_EBCDIC*/
1338
1339     /* Output the HTTP/1.x Status-Line and the Date and Server fields */
1340
1341     ap_rvputs(r, protocol, " ", r->status_line, "\015\012", NULL);
1342
1343     ap_send_header_field(r, "Date", ap_gm_timestr_822(r->pool, r->request_time));
1344     ap_send_header_field(r, "Server", ap_get_server_version());
1345
1346     ap_table_unset(r->headers_out, "Date");        /* Avoid bogosity */
1347     ap_table_unset(r->headers_out, "Server");
1348 #ifdef CHARSET_EBCDIC
1349     if (!convert)
1350         ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert);
1351 #endif /*CHARSET_EBCDIC*/
1352 }
1353
1354 /* Navigator versions 2.x, 3.x and 4.0 betas up to and including 4.0b2
1355  * have a header parsing bug.  If the terminating \r\n occur starting
1356  * at offset 256, 257 or 258 of output then it will not properly parse
1357  * the headers.  Curiously it doesn't exhibit this problem at 512, 513.
1358  * We are guessing that this is because their initial read of a new request
1359  * uses a 256 byte buffer, and subsequent reads use a larger buffer.
1360  * So the problem might exist at different offsets as well.
1361  *
1362  * This should also work on keepalive connections assuming they use the
1363  * same small buffer for the first read of each new request.
1364  *
1365  * At any rate, we check the bytes written so far and, if we are about to
1366  * tickle the bug, we instead insert a bogus padding header.  Since the bug
1367  * manifests as a broken image in Navigator, users blame the server.  :(
1368  * It is more expensive to check the User-Agent than it is to just add the
1369  * bytes, so we haven't used the BrowserMatch feature here.
1370  */
1371 static void terminate_header(request_rec *r)
1372 {
1373     long int bs;
1374
1375     ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
1376     if (bs >= 255 && bs <= 257)
1377         ap_rputs("X-Pad: avoid browser bug\015\012", r);
1378
1379     ap_rputs("\015\012", r);  /* Send the terminating empty line */
1380 }
1381
1382 /* Build the Allow field-value from the request handler method mask.
1383  * Note that we always allow TRACE, since it is handled below.
1384  */
1385 static char *make_allow(request_rec *r)
1386 {
1387     return 2 + ap_pstrcat(r->pool,
1388                    (r->allowed & (1 << M_GET))       ? ", GET, HEAD" : "",
1389                    (r->allowed & (1 << M_POST))      ? ", POST"      : "",
1390                    (r->allowed & (1 << M_PUT))       ? ", PUT"       : "",
1391                    (r->allowed & (1 << M_DELETE))    ? ", DELETE"    : "",
1392                    (r->allowed & (1 << M_CONNECT))   ? ", CONNECT"   : "",
1393                    (r->allowed & (1 << M_OPTIONS))   ? ", OPTIONS"   : "",
1394                    (r->allowed & (1 << M_PATCH))     ? ", PATCH"     : "",
1395                    (r->allowed & (1 << M_PROPFIND))  ? ", PROPFIND"  : "",
1396                    (r->allowed & (1 << M_PROPPATCH)) ? ", PROPPATCH" : "",
1397                    (r->allowed & (1 << M_MKCOL))     ? ", MKCOL"     : "",
1398                    (r->allowed & (1 << M_COPY))      ? ", COPY"      : "",
1399                    (r->allowed & (1 << M_MOVE))      ? ", MOVE"      : "",
1400                    (r->allowed & (1 << M_LOCK))      ? ", LOCK"      : "",
1401                    (r->allowed & (1 << M_UNLOCK))    ? ", UNLOCK"    : "",
1402                    ", TRACE",
1403                    NULL);
1404 }
1405
1406 API_EXPORT(int) ap_send_http_trace(request_rec *r)
1407 {
1408     int rv;
1409
1410     /* Get the original request */
1411     while (r->prev)
1412         r = r->prev;
1413
1414     if ((rv = ap_setup_client_block(r, REQUEST_NO_BODY)))
1415         return rv;
1416
1417     r->content_type = "message/http";
1418     ap_send_http_header(r);
1419
1420     /* Now we recreate the request, and echo it back */
1421
1422     ap_rvputs(r, r->the_request, "\015\012", NULL);
1423
1424     ap_table_do((int (*) (void *, const char *, const char *))
1425                 ap_send_header_field, (void *) r, r->headers_in, NULL);
1426     ap_rputs("\015\012", r);
1427
1428     return OK;
1429 }
1430
1431 int ap_send_http_options(request_rec *r)
1432 {
1433     const long int zero = 0L;
1434
1435     if (r->assbackwards)
1436         return DECLINED;
1437
1438     ap_basic_http_header(r);
1439
1440     ap_table_setn(r->headers_out, "Content-Length", "0");
1441     ap_table_setn(r->headers_out, "Allow", make_allow(r));
1442     ap_set_keepalive(r);
1443
1444     ap_table_do((int (*) (void *, const char *, const char *)) ap_send_header_field,
1445              (void *) r, r->headers_out, NULL);
1446
1447     terminate_header(r);
1448
1449     ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
1450
1451     return OK;
1452 }
1453
1454 /*
1455  * Here we try to be compatible with clients that want multipart/x-byteranges
1456  * instead of multipart/byteranges (also see above), as per HTTP/1.1. We
1457  * look for the Request-Range header (e.g. Netscape 2 and 3) as an indication
1458  * that the browser supports an older protocol. We also check User-Agent
1459  * for Microsoft Internet Explorer 3, which needs this as well.
1460  */
1461 static int use_range_x(request_rec *r)
1462 {
1463     const char *ua;
1464     return (ap_table_get(r->headers_in, "Request-Range") ||
1465             ((ua = ap_table_get(r->headers_in, "User-Agent"))
1466              && strstr(ua, "MSIE 3")));
1467 }
1468
1469 /* This routine is called by ap_table_do and merges all instances of
1470  * the passed field values into a single array that will be further
1471  * processed by some later routine.  Originally intended to help split
1472  * and recombine multiple Vary fields, though it is generic to any field
1473  * consisting of comma/space-separated tokens.
1474  */
1475 static int uniq_field_values(void *d, const char *key, const char *val)
1476 {
1477     ap_array_header_t *values;
1478     char *start;
1479     char *e;
1480     char **strpp;
1481     int  i;
1482
1483     values = (ap_array_header_t *)d;
1484
1485     e = ap_pstrdup(values->cont, val);
1486
1487     do {
1488         /* Find a non-empty fieldname */
1489
1490         while (*e == ',' || ap_isspace(*e)) {
1491             ++e;
1492         }
1493         if (*e == '\0') {
1494             break;
1495         }
1496         start = e;
1497         while (*e != '\0' && *e != ',' && !ap_isspace(*e)) {
1498             ++e;
1499         }
1500         if (*e != '\0') {
1501             *e++ = '\0';
1502         }
1503
1504         /* Now add it to values if it isn't already represented.
1505          * Could be replaced by a ap_array_strcasecmp() if we had one.
1506          */
1507         for (i = 0, strpp = (char **) values->elts; i < values->nelts;
1508              ++i, ++strpp) {
1509             if (*strpp && strcasecmp(*strpp, start) == 0) {
1510                 break;
1511             }
1512         }
1513         if (i == values->nelts) {  /* if not found */
1514            *(char **)ap_push_array(values) = start;
1515         }
1516     } while (*e != '\0');
1517
1518     return 1;
1519 }
1520
1521 /*
1522  * Since some clients choke violently on multiple Vary fields, or
1523  * Vary fields with duplicate tokens, combine any multiples and remove
1524  * any duplicates.
1525  */
1526 static void fixup_vary(request_rec *r)
1527 {
1528     ap_array_header_t *varies;
1529
1530     varies = ap_make_array(r->pool, 5, sizeof(char *));
1531
1532     /* Extract all Vary fields from the headers_out, separate each into
1533      * its comma-separated fieldname values, and then add them to varies
1534      * if not already present in the array.
1535      */
1536     ap_table_do((int (*)(void *, const char *, const char *))uniq_field_values,
1537                 (void *) varies, r->headers_out, "Vary", NULL);
1538
1539     /* If we found any, replace old Vary fields with unique-ified value */
1540
1541     if (varies->nelts > 0) {
1542         ap_table_setn(r->headers_out, "Vary",
1543                       ap_array_pstrcat(r->pool, varies, ','));
1544     }
1545 }
1546
1547 API_EXPORT(void) ap_send_http_header(request_rec *r)
1548 {
1549     int i;
1550     const long int zero = 0L;
1551 #ifdef CHARSET_EBCDIC
1552     int convert = ap_bgetflag(r->connection->client, B_EBCDIC2ASCII);
1553 #endif /*CHARSET_EBCDIC*/
1554
1555     if (r->assbackwards) {
1556         if (!r->main)
1557             ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
1558         r->sent_bodyct = 1;
1559         return;
1560     }
1561
1562     /*
1563      * Now that we are ready to send a response, we need to combine the two
1564      * header field tables into a single table.  If we don't do this, our
1565      * later attempts to set or unset a given fieldname might be bypassed.
1566      */
1567     if (!ap_is_empty_table(r->err_headers_out))
1568         r->headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
1569                                         r->headers_out);
1570
1571     /*
1572      * Remove the 'Vary' header field if the client can't handle it.
1573      * Since this will have nasty effects on HTTP/1.1 caches, force
1574      * the response into HTTP/1.0 mode.
1575      */
1576     if (ap_table_get(r->subprocess_env, "force-no-vary") != NULL) {
1577         ap_table_unset(r->headers_out, "Vary");
1578         r->proto_num = HTTP_VERSION(1,0);
1579         ap_table_set(r->subprocess_env, "force-response-1.0", "1");
1580     }
1581     else {
1582         fixup_vary(r);
1583     }
1584
1585     ap_basic_http_header(r);
1586
1587 #ifdef CHARSET_EBCDIC
1588     ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, 1);
1589 #endif /*CHARSET_EBCDIC*/
1590
1591     ap_set_keepalive(r);
1592
1593     if (r->chunked) {
1594         ap_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
1595         ap_table_unset(r->headers_out, "Content-Length");
1596     }
1597
1598     if (r->byterange > 1)
1599         ap_table_setn(r->headers_out, "Content-Type",
1600                   ap_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/",
1601                           "byteranges; boundary=", r->boundary, NULL));
1602     else if (r->content_type)
1603         ap_table_setn(r->headers_out, "Content-Type", r->content_type);
1604     else
1605         ap_table_setn(r->headers_out, "Content-Type", ap_default_type(r));
1606
1607     if (r->content_encoding)
1608         ap_table_setn(r->headers_out, "Content-Encoding", r->content_encoding);
1609
1610     if (r->content_languages && r->content_languages->nelts) {
1611         for (i = 0; i < r->content_languages->nelts; ++i) {
1612             ap_table_mergen(r->headers_out, "Content-Language",
1613                         ((char **) (r->content_languages->elts))[i]);
1614         }
1615     }
1616     else if (r->content_language)
1617         ap_table_setn(r->headers_out, "Content-Language", r->content_language);
1618
1619     /*
1620      * Control cachability for non-cachable responses if not already set by
1621      * some other part of the server configuration.
1622      */
1623     if (r->no_cache && !ap_table_get(r->headers_out, "Expires"))
1624         ap_table_addn(r->headers_out, "Expires",
1625                   ap_gm_timestr_822(r->pool, r->request_time));
1626
1627     /* Send the entire ap_table_t of header fields, terminated by an empty line. */
1628
1629     ap_table_do((int (*) (void *, const char *, const char *)) ap_send_header_field,
1630              (void *) r, r->headers_out, NULL);
1631
1632     terminate_header(r);
1633
1634
1635     ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
1636     r->sent_bodyct = 1;         /* Whatever follows is real body stuff... */
1637
1638     /* Set buffer flags for the body */
1639     if (r->chunked)
1640         ap_bsetflag(r->connection->client, B_CHUNK, 1);
1641 #ifdef CHARSET_EBCDIC
1642     if (!convert)
1643         ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert);
1644 #endif /*CHARSET_EBCDIC*/
1645 }
1646
1647 /* finalize_request_protocol is called at completion of sending the
1648  * response.  It's sole purpose is to send the terminating protocol
1649  * information for any wrappers around the response message body
1650  * (i.e., transfer encodings).  It should have been named finalize_response.
1651  */
1652 API_EXPORT(void) ap_finalize_request_protocol(request_rec *r)
1653 {
1654     if (r->chunked && !r->connection->aborted) {
1655         /*
1656          * Turn off chunked encoding --- we can only do this once.
1657          */
1658         r->chunked = 0;
1659         ap_bsetflag(r->connection->client, B_CHUNK, 0);
1660
1661         ap_rputs("0\015\012", r);
1662         /* If we had footer "headers", we'd send them now */
1663         ap_rputs("\015\012", r);
1664     }
1665 }
1666
1667 /* Here we deal with getting the request message body from the client.
1668  * Whether or not the request contains a body is signaled by the presence
1669  * of a non-zero Content-Length or by a Transfer-Encoding: chunked.
1670  *
1671  * Note that this is more complicated than it was in Apache 1.1 and prior
1672  * versions, because chunked support means that the module does less.
1673  *
1674  * The proper procedure is this:
1675  *
1676  * 1. Call setup_client_block() near the beginning of the request
1677  *    handler. This will set up all the necessary properties, and will
1678  *    return either OK, or an error code. If the latter, the module should
1679  *    return that error code. The second parameter selects the policy to
1680  *    apply if the request message indicates a body, and how a chunked
1681  *    transfer-coding should be interpreted. Choose one of
1682  *
1683  *    REQUEST_NO_BODY          Send 413 error if message has any body
1684  *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
1685  *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
1686  *    REQUEST_CHUNKED_PASS     Pass the chunks to me without removal.
1687  *
1688  *    In order to use the last two options, the caller MUST provide a buffer
1689  *    large enough to hold a chunk-size line, including any extensions.
1690  *
1691  * 2. When you are ready to read a body (if any), call should_client_block().
1692  *    This will tell the module whether or not to read input. If it is 0,
1693  *    the module should assume that there is no message body to read.
1694  *    This step also sends a 100 Continue response to HTTP/1.1 clients,
1695  *    so should not be called until the module is *definitely* ready to
1696  *    read content. (otherwise, the point of the 100 response is defeated).
1697  *    Never call this function more than once.
1698  *
1699  * 3. Finally, call get_client_block in a loop. Pass it a buffer and its size.
1700  *    It will put data into the buffer (not necessarily a full buffer), and
1701  *    return the length of the input block. When it is done reading, it will
1702  *    return 0 if EOF, or -1 if there was an error.
1703  *    If an error occurs on input, we force an end to keepalive.
1704  */
1705
1706 API_EXPORT(int) ap_setup_client_block(request_rec *r, int read_policy)
1707 {
1708     const char *tenc = ap_table_get(r->headers_in, "Transfer-Encoding");
1709     const char *lenp = ap_table_get(r->headers_in, "Content-Length");
1710     unsigned long max_body;
1711
1712     r->read_body = read_policy;
1713     r->read_chunked = 0;
1714     r->remaining = 0;
1715
1716     if (tenc) {
1717         if (strcasecmp(tenc, "chunked")) {
1718             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
1719                         "Unknown Transfer-Encoding %s", tenc);
1720             return HTTP_NOT_IMPLEMENTED;
1721         }
1722         if (r->read_body == REQUEST_CHUNKED_ERROR) {
1723             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
1724                         "chunked Transfer-Encoding forbidden: %s", r->uri);
1725             return (lenp) ? HTTP_BAD_REQUEST : HTTP_LENGTH_REQUIRED;
1726         }
1727
1728         r->read_chunked = 1;
1729     }
1730     else if (lenp) {
1731         const char *pos = lenp;
1732
1733         while (ap_isdigit(*pos) || ap_isspace(*pos))
1734             ++pos;
1735         if (*pos != '\0') {
1736             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
1737                         "Invalid Content-Length %s", lenp);
1738             return HTTP_BAD_REQUEST;
1739         }
1740
1741         r->remaining = atol(lenp);
1742     }
1743
1744     if ((r->read_body == REQUEST_NO_BODY) &&
1745         (r->read_chunked || (r->remaining > 0))) {
1746         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
1747                     "%s with body is not allowed for %s", r->method, r->uri);
1748         return HTTP_REQUEST_ENTITY_TOO_LARGE;
1749     }
1750
1751     max_body = ap_get_limit_req_body(r);
1752     if (max_body && (r->remaining > max_body)) {
1753         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
1754           "Request content-length of %s is larger than the configured "
1755           "limit of %lu", lenp, max_body);
1756         return HTTP_REQUEST_ENTITY_TOO_LARGE;
1757     }
1758
1759     return OK;
1760 }
1761
1762 API_EXPORT(int) ap_should_client_block(request_rec *r)
1763 {
1764     /* First check if we have already read the request body */
1765
1766     if (r->read_length || (!r->read_chunked && (r->remaining <= 0)))
1767         return 0;
1768
1769     if (r->expecting_100 && r->proto_num >= HTTP_VERSION(1,1)) {
1770         /* sending 100 Continue interim response */
1771         ap_rvputs(r, SERVER_PROTOCOL, " ", status_lines[0], "\015\012\015\012",
1772                   NULL);
1773         ap_rflush(r);
1774     }
1775
1776     return 1;
1777 }
1778
1779 static long get_chunk_size(char *b)
1780 {
1781     long chunksize = 0;
1782
1783     while (ap_isxdigit(*b)) {
1784         int xvalue = 0;
1785
1786         if (*b >= '0' && *b <= '9')
1787             xvalue = *b - '0';
1788         else if (*b >= 'A' && *b <= 'F')
1789             xvalue = *b - 'A' + 0xa;
1790         else if (*b >= 'a' && *b <= 'f')
1791             xvalue = *b - 'a' + 0xa;
1792
1793         chunksize = (chunksize << 4) | xvalue;
1794         ++b;
1795     }
1796
1797     return chunksize;
1798 }
1799
1800 /* get_client_block is called in a loop to get the request message body.
1801  * This is quite simple if the client includes a content-length
1802  * (the normal case), but gets messy if the body is chunked. Note that
1803  * r->remaining is used to maintain state across calls and that
1804  * r->read_length is the total number of bytes given to the caller
1805  * across all invocations.  It is messy because we have to be careful not
1806  * to read past the data provided by the client, since these reads block.
1807  * Returns 0 on End-of-body, -1 on error or premature chunk end.
1808  *
1809  * Reading the chunked encoding requires a buffer size large enough to
1810  * hold a chunk-size line, including any extensions. For now, we'll leave
1811  * that to the caller, at least until we can come up with a better solution.
1812  */
1813 API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz)
1814 {
1815     int c;
1816     ap_size_t len_to_read;
1817     ap_ssize_t len_read;
1818     long chunk_start = 0;
1819     unsigned long max_body;
1820     ap_status_t rv;
1821
1822     if (!r->read_chunked) {     /* Content-length read */
1823         len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
1824         rv = ap_bread(r->connection->client, buffer, len_to_read, &len_read);
1825         if (len_read == 0) {    /* error or eof */
1826             if (rv != APR_SUCCESS) {
1827                 r->connection->keepalive = -1;
1828                 return -1;
1829             }
1830             return 0;
1831         }
1832         r->read_length += len_read;
1833         r->remaining -= len_read;
1834         return len_read;
1835     }
1836
1837     /*
1838      * Handle chunked reading Note: we are careful to shorten the input
1839      * bufsiz so that there will always be enough space for us to add a CRLF
1840      * (if necessary).
1841      */
1842     if (r->read_body == REQUEST_CHUNKED_PASS)
1843         bufsiz -= 2;
1844     if (bufsiz <= 0)
1845         return -1;              /* Cannot read chunked with a small buffer */
1846
1847     /* Check to see if we have already read too much request data.
1848      * For efficiency reasons, we only check this at the top of each
1849      * caller read pass, since the limit exists just to stop infinite
1850      * length requests and nobody cares if it goes over by one buffer.
1851      */
1852     max_body = ap_get_limit_req_body(r);
1853     if (max_body && (r->read_length > max_body)) {
1854         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
1855             "Chunked request body is larger than the configured limit of %lu",
1856             max_body);
1857         r->connection->keepalive = -1;
1858         return -1;
1859     }
1860
1861     if (r->remaining == 0) {    /* Start of new chunk */
1862
1863         chunk_start = getline(buffer, bufsiz, r->connection->client, 0);
1864         if ((chunk_start <= 0) || (chunk_start >= (bufsiz - 1))
1865             || !ap_isxdigit(*buffer)) {
1866             r->connection->keepalive = -1;
1867             return -1;
1868         }
1869
1870         len_to_read = get_chunk_size(buffer);
1871
1872         if (len_to_read == 0) { /* Last chunk indicated, get footers */
1873             if (r->read_body == REQUEST_CHUNKED_DECHUNK) {
1874                 get_mime_headers(r);
1875                 ap_snprintf(buffer, bufsiz, "%ld", r->read_length);
1876                 ap_table_unset(r->headers_in, "Transfer-Encoding");
1877                 ap_table_setn(r->headers_in, "Content-Length",
1878                     ap_pstrdup(r->pool, buffer));
1879                 return 0;
1880             }
1881             r->remaining = -1;  /* Indicate footers in-progress */
1882         }
1883         else {
1884             r->remaining = len_to_read;
1885         }
1886         if (r->read_body == REQUEST_CHUNKED_PASS) {
1887             buffer[chunk_start++] = CR; /* Restore chunk-size line end  */
1888             buffer[chunk_start++] = LF;
1889             buffer += chunk_start;      /* and pass line on to caller   */
1890             bufsiz -= chunk_start;
1891         }
1892         else {
1893             /* REQUEST_CHUNKED_DECHUNK -- do not include the length of the
1894              * header in the return value
1895              */
1896             chunk_start = 0;
1897         }
1898     }
1899                                 /* When REQUEST_CHUNKED_PASS, we are */
1900     if (r->remaining == -1) {   /* reading footers until empty line  */
1901         len_read = chunk_start;
1902
1903         while ((bufsiz > 1) && ((len_read =
1904                   getline(buffer, bufsiz, r->connection->client, 1)) > 0)) {
1905
1906             if (len_read != (bufsiz - 1)) {
1907                 buffer[len_read++] = CR;        /* Restore footer line end  */
1908                 buffer[len_read++] = LF;
1909             }
1910             chunk_start += len_read;
1911             buffer += len_read;
1912             bufsiz -= len_read;
1913         }
1914         if (len_read < 0) {
1915             r->connection->keepalive = -1;
1916             return -1;
1917         }
1918
1919         if (len_read == 0) {    /* Indicates an empty line */
1920             buffer[0] = CR;
1921             buffer[1] = LF;
1922             chunk_start += 2;
1923             r->remaining = -2;
1924         }
1925         r->read_length += chunk_start;
1926         return chunk_start;
1927     }
1928                                 /* When REQUEST_CHUNKED_PASS, we     */
1929     if (r->remaining == -2) {   /* finished footers when last called */
1930         r->remaining = 0;       /* so now we must signal EOF         */
1931         return 0;
1932     }
1933
1934     /* Otherwise, we are in the midst of reading a chunk of data */
1935
1936     len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
1937
1938     (void) ap_bread(r->connection->client, buffer, len_to_read, &len_read);
1939     if (len_read == 0) {        /* error or eof */
1940         r->connection->keepalive = -1;
1941         return -1;
1942     }
1943
1944     r->remaining -= len_read;
1945
1946     if (r->remaining == 0) {    /* End of chunk, get trailing CRLF */
1947         if ((c = ap_bgetc(r->connection->client)) == CR) {
1948             c = ap_bgetc(r->connection->client);
1949         }
1950         if (c != LF) {
1951             r->connection->keepalive = -1;
1952             return -1;
1953         }
1954         if (r->read_body == REQUEST_CHUNKED_PASS) {
1955             buffer[len_read++] = CR;
1956             buffer[len_read++] = LF;
1957         }
1958     }
1959     r->read_length += (chunk_start + len_read);
1960
1961     return (chunk_start + len_read);
1962 }
1963
1964 /* In HTTP/1.1, any method can have a body.  However, most GET handlers
1965  * wouldn't know what to do with a request body if they received one.
1966  * This helper routine tests for and reads any message body in the request,
1967  * simply discarding whatever it receives.  We need to do this because
1968  * failing to read the request body would cause it to be interpreted
1969  * as the next request on a persistent connection.
1970  *
1971  * Since we return an error status if the request is malformed, this
1972  * routine should be called at the beginning of a no-body handler, e.g.,
1973  *
1974  *    if ((retval = ap_discard_request_body(r)) != OK)
1975  *        return retval;
1976  */
1977 API_EXPORT(int) ap_discard_request_body(request_rec *r)
1978 {
1979     int rv;
1980
1981     if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_PASS)))
1982         return rv;
1983
1984     /* In order to avoid sending 100 Continue when we already know the
1985      * final response status, and yet not kill the connection if there is
1986      * no request body to be read, we need to duplicate the test from
1987      * ap_should_client_block() here negated rather than call it directly.
1988      */
1989     if ((r->read_length == 0) && (r->read_chunked || (r->remaining > 0))) {
1990         char dumpbuf[HUGE_STRING_LEN];
1991
1992         if (r->expecting_100) {
1993             r->connection->keepalive = -1;
1994             return OK;
1995         }
1996
1997         while ((rv = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN)) > 0)
1998             continue;
1999
2000         if (rv < 0)
2001             return HTTP_BAD_REQUEST;
2002     }
2003     return OK;
2004 }
2005
2006 /*
2007  * Send the body of a response to the client.
2008  */
2009 API_EXPORT(long) ap_send_fd(ap_file_t *fd, request_rec *r)
2010 {
2011     return ap_send_fd_length(fd, r, -1);
2012 }
2013
2014 API_EXPORT(long) ap_send_fd_length(ap_file_t *fd, request_rec *r, long length)
2015 {
2016     char buf[IOBUFSIZE];
2017     long total_bytes_sent = 0;
2018     register int w, o;
2019     ap_ssize_t n;
2020     ap_status_t status;
2021
2022     if (length == 0)
2023         return 0;
2024
2025     while (!ap_is_aborted(r->connection)) {
2026         if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
2027             o = length - total_bytes_sent;
2028         else
2029             o = IOBUFSIZE;
2030         
2031         n = o;
2032         do {
2033             status = ap_read(fd, buf, &n);
2034         } while (status == APR_EINTR && !ap_is_aborted(r->connection) &&
2035                  (n < 1));
2036
2037         if (n < 1) {
2038             break;
2039         }
2040
2041         o = 0;
2042
2043         while (n && !ap_is_aborted(r->connection)) {
2044             w = ap_bwrite(r->connection->client, &buf[o], n);
2045             if (w > 0) {
2046                 total_bytes_sent += w;
2047                 n -= w;
2048                 o += w;
2049             }
2050             else if (w < 0) {
2051                 if (!ap_is_aborted(r->connection)) {
2052                     ap_log_rerror(APLOG_MARK, APLOG_INFO, errno, r,
2053                      "client stopped connection before send body completed");
2054                     ap_bsetflag(r->connection->client, B_EOUT, 1);
2055                     r->connection->aborted = 1;
2056                 }
2057                 break;
2058             }
2059         }
2060     }
2061
2062     SET_BYTES_SENT(r);
2063     return total_bytes_sent;
2064 }
2065
2066 /*
2067  * Send the body of a response to the client.
2068  */
2069 API_EXPORT(long) ap_send_fb(BUFF *fb, request_rec *r)
2070 {
2071     return ap_send_fb_length(fb, r, -1);
2072 }
2073
2074 API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length)
2075 {
2076     char buf[IOBUFSIZE];
2077     long total_bytes_sent = 0;
2078     long zero_timeout = 0;
2079     int w, o;
2080     ap_ssize_t n;
2081     ap_status_t rv;
2082
2083     if (length == 0) {
2084         return 0;
2085     }
2086
2087     /* This function tries to as much as possible through non-blocking
2088      * reads so that it can do writes while waiting for the CGI to
2089      * produce more data. This way, the CGI's output gets to the client
2090      * as soon as possible */
2091
2092     ap_bsetopt(fb, BO_TIMEOUT, &zero_timeout);
2093     while (!ap_is_aborted(r->connection)) {
2094         rv = ap_bread(fb, buf, sizeof(buf), &n);
2095         if (n == 0) {
2096             if (rv == APR_SUCCESS) {    /* eof */
2097                 (void) ap_rflush(r);
2098                 break;
2099             }
2100             if (rv != APR_EAGAIN) {
2101                 r->connection->aborted = 1;
2102                 break;
2103             }
2104             /* next read will block, so flush the client now */
2105             if (ap_rflush(r) == EOF) {
2106                 break;
2107             }
2108
2109             ap_bsetopt(fb, BO_TIMEOUT, &r->server->timeout);
2110             rv = ap_bread(fb, buf, sizeof(buf), &n);
2111             if (n == 0) {
2112                 if (rv == APR_SUCCESS) {        /* eof */
2113                     (void) ap_rflush(r);
2114                 }
2115                 r->connection->aborted = 1;
2116                 break;
2117             }
2118             ap_bsetopt(fb, BO_TIMEOUT, &zero_timeout);
2119         }
2120         
2121         o = 0;
2122         while (n && !ap_is_aborted(r->connection)) {
2123             w = ap_bwrite(r->connection->client, &buf[o], n);
2124             if (w > 0) {
2125                 total_bytes_sent += w;
2126                 n -= w;
2127                 o += w;
2128             }
2129             else if (w < 0) {
2130                 if (!ap_is_aborted(r->connection)) {
2131                     ap_log_rerror(APLOG_MARK, APLOG_INFO, errno, r,
2132                         "client stopped connection before rflush completed");
2133                     ap_bsetflag(r->connection->client, B_EOUT, 1);
2134                     r->connection->aborted = 1;
2135                 }
2136                 break;
2137             }
2138         }
2139     }
2140     SET_BYTES_SENT(r);
2141     return total_bytes_sent;
2142 }
2143
2144 /* The code writes MMAP_SEGMENT_SIZE bytes at a time.  This is due to Apache's
2145  * timeout model, which is a timeout per-write rather than a time for the
2146  * entire transaction to complete.  Essentially this should be small enough
2147  * so that in one Timeout period, your slowest clients should be reasonably
2148  * able to receive this many bytes.
2149  *
2150  * To take advantage of zero-copy TCP under Solaris 2.6 this should be a
2151  * multiple of 16k.  (And you need a SunATM2.0 network card.)
2152  */
2153 #ifndef MMAP_SEGMENT_SIZE
2154 #define MMAP_SEGMENT_SIZE       32768
2155 #endif
2156
2157 /* send data from an in-memory buffer */
2158 API_EXPORT(size_t) ap_send_mmap(void *mm, request_rec *r, size_t offset,
2159                              size_t length)
2160 {
2161     size_t total_bytes_sent = 0;
2162     int n, w;
2163
2164     if (length == 0)
2165         return 0;
2166
2167
2168     length += offset;
2169     while (!r->connection->aborted && offset < length) {
2170         if (length - offset > MMAP_SEGMENT_SIZE) {
2171             n = MMAP_SEGMENT_SIZE;
2172         }
2173         else {
2174             n = length - offset;
2175         }
2176
2177         while (n && !r->connection->aborted) {
2178             w = ap_bwrite(r->connection->client, (char *) mm + offset, n);
2179             if (w > 0) {
2180                 total_bytes_sent += w;
2181                 n -= w;
2182                 offset += w;
2183             }
2184             else if (w < 0) {
2185                 if (r->connection->aborted)
2186                     break;
2187                 else if (errno == EAGAIN)
2188                     continue;
2189                 else {
2190                     ap_log_rerror(APLOG_MARK, APLOG_INFO, errno, r,
2191                      "client stopped connection before send mmap completed");
2192                     ap_bsetflag(r->connection->client, B_EOUT, 1);
2193                     r->connection->aborted = 1;
2194                     break;
2195                 }
2196             }
2197         }
2198     }
2199
2200     SET_BYTES_SENT(r);
2201     return total_bytes_sent;
2202 }
2203
2204 API_EXPORT(int) ap_rputc(int c, request_rec *r)
2205 {
2206     if (r->connection->aborted)
2207         return EOF;
2208
2209     if (ap_bputc(c, r->connection->client) < 0) {
2210         if (!r->connection->aborted) {
2211             ap_log_rerror(APLOG_MARK, APLOG_INFO, errno, r,
2212                 "client stopped connection before rputc completed");
2213             ap_bsetflag(r->connection->client, B_EOUT, 1);
2214             r->connection->aborted = 1;
2215         }
2216         return EOF;
2217     }
2218     SET_BYTES_SENT(r);
2219     return c;
2220 }
2221
2222 API_EXPORT(int) ap_rputs(const char *str, request_rec *r)
2223 {
2224     int rcode;
2225
2226     if (r->connection->aborted)
2227         return EOF;
2228     
2229     rcode = ap_bputs(str, r->connection->client);
2230     if (rcode < 0) {
2231         if (!r->connection->aborted) {
2232             ap_log_rerror(APLOG_MARK, APLOG_INFO, errno, r,
2233                 "client stopped connection before rputs completed");
2234             ap_bsetflag(r->connection->client, B_EOUT, 1);
2235             r->connection->aborted = 1;
2236         }
2237         return EOF;
2238     }
2239     SET_BYTES_SENT(r);
2240     return rcode;
2241 }
2242
2243 API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
2244 {
2245     int n;
2246
2247     if (r->connection->aborted)
2248         return EOF;
2249
2250     n = ap_bwrite(r->connection->client, buf, nbyte);
2251     if (n < 0) {
2252         if (!r->connection->aborted) {
2253             ap_log_rerror(APLOG_MARK, APLOG_INFO, errno, r,
2254                 "client stopped connection before rwrite completed");
2255             ap_bsetflag(r->connection->client, B_EOUT, 1);
2256             r->connection->aborted = 1;
2257         }
2258         return EOF;
2259     }
2260     SET_BYTES_SENT(r);
2261     return n;
2262 }
2263
2264 API_EXPORT(int) ap_vrprintf(request_rec *r, const char *fmt, va_list ap)
2265 {
2266     int n;
2267
2268     if (r->connection->aborted)
2269         return -1;
2270
2271     n = ap_vbprintf(r->connection->client, fmt, ap);
2272
2273     if (n < 0) {
2274         if (!r->connection->aborted) {
2275             ap_log_rerror(APLOG_MARK, APLOG_INFO, errno, r,
2276                 "client stopped connection before vrprintf completed");
2277             ap_bsetflag(r->connection->client, B_EOUT, 1);
2278             r->connection->aborted = 1;
2279         }
2280         return -1;
2281     }
2282     SET_BYTES_SENT(r);
2283     return n;
2284 }
2285
2286 API_EXPORT(int) ap_rprintf(request_rec *r, const char *fmt,...)
2287 {
2288     va_list vlist;
2289     int n;
2290
2291     if (r->connection->aborted)
2292         return -1;
2293
2294     va_start(vlist, fmt);
2295     n = ap_vbprintf(r->connection->client, fmt, vlist);
2296     va_end(vlist);
2297
2298     if (n < 0) {
2299         if (!r->connection->aborted) {
2300             ap_log_rerror(APLOG_MARK, APLOG_INFO, errno, r,
2301                 "client stopped connection before rprintf completed");
2302             ap_bsetflag(r->connection->client, B_EOUT, 1);
2303             r->connection->aborted = 1;
2304         }
2305         return -1;
2306     }
2307     SET_BYTES_SENT(r);
2308     return n;
2309 }
2310
2311 API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...)
2312 {
2313     va_list args;
2314     int i, j, k;
2315     const char *x;
2316     BUFF *fb = r->connection->client;
2317
2318     if (r->connection->aborted)
2319         return EOF;
2320
2321     va_start(args, r);
2322     for (k = 0;;) {
2323         x = va_arg(args, const char *);
2324         if (x == NULL)
2325             break;
2326         j = strlen(x);
2327         i = ap_bwrite(fb, x, j);
2328         if (i != j) {
2329             va_end(args);
2330             if (!r->connection->aborted) {
2331                 ap_log_rerror(APLOG_MARK, APLOG_INFO, errno, r,
2332                     "client stopped connection before rvputs completed");
2333                 ap_bsetflag(r->connection->client, B_EOUT, 1);
2334                 r->connection->aborted = 1;
2335             }
2336             return EOF;
2337         }
2338         k += i;
2339     }
2340     va_end(args);
2341
2342     SET_BYTES_SENT(r);
2343     return k;
2344 }
2345
2346 API_EXPORT(int) ap_rflush(request_rec *r)
2347 {
2348     ap_status_t rv;
2349
2350     if ((rv = ap_bflush(r->connection->client)) != APR_SUCCESS) {
2351         if (!ap_is_aborted(r->connection)) {
2352             ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, r,
2353                 "client stopped connection before rflush completed");
2354             ap_bsetflag(r->connection->client, B_EOUT, 1);
2355             r->connection->aborted = 1;
2356         }
2357         errno = rv;
2358         return EOF;
2359     }
2360     return 0;
2361 }
2362
2363 /* We should have named this send_canned_response, since it is used for any
2364  * response that can be generated by the server from the request record.
2365  * This includes all 204 (no content), 3xx (redirect), 4xx (client error),
2366  * and 5xx (server error) messages that have not been redirected to another
2367  * handler via the ErrorDocument feature.
2368  */
2369 void ap_send_error_response(request_rec *r, int recursive_error)
2370 {
2371     int status = r->status;
2372     int idx = ap_index_of_response(status);
2373     char *custom_response;
2374     const char *location = ap_table_get(r->headers_out, "Location");
2375
2376     /*
2377      * It's possible that the Location field might be in r->err_headers_out
2378      * instead of r->headers_out; use the latter if possible, else the
2379      * former.
2380      */
2381     if (location == NULL) {
2382         location = ap_table_get(r->err_headers_out, "Location");
2383     }
2384     /* We need to special-case the handling of 204 and 304 responses,
2385      * since they have specific HTTP requirements and do not include a
2386      * message body.  Note that being assbackwards here is not an option.
2387      */
2388     if (status == HTTP_NOT_MODIFIED) {
2389         if (!ap_is_empty_table(r->err_headers_out))
2390             r->headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
2391                                                r->headers_out);
2392         ap_basic_http_header(r);
2393         ap_set_keepalive(r);
2394
2395         ap_table_do((int (*)(void *, const char *, const char *)) ap_send_header_field,
2396                     (void *) r, r->headers_out,
2397                     "Connection",
2398                     "Keep-Alive",
2399                     "ETag",
2400                     "Content-Location",
2401                     "Expires",
2402                     "Cache-Control",
2403                     "Vary",
2404                     "Warning",
2405                     "WWW-Authenticate",
2406                     "Proxy-Authenticate",
2407                     NULL);
2408
2409         terminate_header(r);
2410
2411         return;
2412     }
2413
2414     if (status == HTTP_NO_CONTENT) {
2415         ap_send_http_header(r);
2416         ap_finalize_request_protocol(r);
2417         return;
2418     }
2419
2420     if (!r->assbackwards) {
2421         ap_table_t *tmp = r->headers_out;
2422
2423         /* For all HTTP/1.x responses for which we generate the message,
2424          * we need to avoid inheriting the "normal status" header fields
2425          * that may have been set by the request handler before the
2426          * error or redirect, except for Location on external redirects.
2427          */
2428         r->headers_out = r->err_headers_out;
2429         r->err_headers_out = tmp;
2430         ap_clear_table(r->err_headers_out);
2431
2432         if (ap_is_HTTP_REDIRECT(status) || (status == HTTP_CREATED)) {
2433             if ((location != NULL) && *location) {
2434                 ap_table_setn(r->headers_out, "Location", location);
2435             }
2436             else {
2437                 location = "";   /* avoids coredump when printing, below */
2438             }
2439         }
2440
2441         r->content_language = NULL;
2442         r->content_languages = NULL;
2443         r->content_encoding = NULL;
2444         r->clength = 0;
2445         r->content_type = "text/html";
2446
2447         if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED))
2448             ap_table_setn(r->headers_out, "Allow", make_allow(r));
2449
2450         ap_send_http_header(r);
2451
2452         if (r->header_only) {
2453             ap_finalize_request_protocol(r);
2454             ap_rflush(r);
2455             return;
2456         }
2457     }
2458
2459     if ((custom_response = ap_response_code_string(r, idx))) {
2460         /*
2461          * We have a custom response output. This should only be
2462          * a text-string to write back. But if the ErrorDocument
2463          * was a local redirect and the requested resource failed
2464          * for any reason, the custom_response will still hold the
2465          * redirect URL. We don't really want to output this URL
2466          * as a text message, so first check the custom response
2467          * string to ensure that it is a text-string (using the
2468          * same test used in ap_die(), i.e. does it start with a ").
2469          * If it doesn't, we've got a recursive error, so find
2470          * the original error and output that as well.
2471          */
2472         if (custom_response[0] == '\"') {
2473             ap_rputs(custom_response + 1, r);
2474             ap_finalize_request_protocol(r);
2475             ap_rflush(r);
2476             return;
2477         }
2478         /*
2479          * Redirect failed, so get back the original error
2480          */
2481         while (r->prev && (r->prev->status != HTTP_OK))
2482             r = r->prev;
2483     }
2484     {
2485         const char *title = status_lines[idx];
2486         const char *h1;
2487         const char *error_notes;
2488
2489         /* Accept a status_line set by a module, but only if it begins
2490          * with the 3 digit status code
2491          */
2492         if (r->status_line != NULL
2493             && strlen(r->status_line) > 4       /* long enough */
2494             && ap_isdigit(r->status_line[0])
2495             && ap_isdigit(r->status_line[1])
2496             && ap_isdigit(r->status_line[2])
2497             && ap_isspace(r->status_line[3])
2498             && ap_isalnum(r->status_line[4])) {
2499             title = r->status_line;
2500         }
2501
2502         /* folks decided they didn't want the error code in the H1 text */
2503         h1 = &title[4];
2504
2505         ap_rvputs(r,
2506                   DOCTYPE_HTML_2_0
2507                   "<HTML><HEAD>\n<TITLE>", title,
2508                   "</TITLE>\n</HEAD><BODY>\n<H1>", h1, "</H1>\n",
2509                   NULL);
2510
2511         switch (status) {
2512         case HTTP_MOVED_PERMANENTLY:
2513         case HTTP_MOVED_TEMPORARILY:
2514         case HTTP_TEMPORARY_REDIRECT:
2515             ap_rvputs(r, "The document has moved <A HREF=\"",
2516                       ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
2517                       NULL);
2518             break;
2519         case HTTP_SEE_OTHER:
2520             ap_rvputs(r, "The answer to your request is located <A HREF=\"",
2521                       ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
2522                       NULL);
2523             break;
2524         case HTTP_USE_PROXY:
2525             ap_rvputs(r, "This resource is only accessible "
2526                       "through the proxy\n",
2527                       ap_escape_html(r->pool, location),
2528                       "<BR>\nYou will need to ",
2529                       "configure your client to use that proxy.<P>\n", NULL);
2530             break;
2531         case HTTP_PROXY_AUTHENTICATION_REQUIRED:
2532         case AUTH_REQUIRED:
2533             ap_rputs("This server could not verify that you\n"
2534                      "are authorized to access the document\n"
2535                      "requested.  Either you supplied the wrong\n"
2536                      "credentials (e.g., bad password), or your\n"
2537                      "browser doesn't understand how to supply\n"
2538                      "the credentials required.<P>\n", r);
2539             break;
2540         case BAD_REQUEST:
2541             ap_rputs("Your browser sent a request that "
2542                      "this server could not understand.<P>\n", r);
2543             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2544                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2545             }
2546             break;
2547         case HTTP_FORBIDDEN:
2548             ap_rvputs(r, "You don't have permission to access ",
2549                       ap_escape_html(r->pool, r->uri),
2550                       "\non this server.<P>\n", NULL);
2551             break;
2552         case NOT_FOUND:
2553             ap_rvputs(r, "The requested URL ",
2554                       ap_escape_html(r->pool, r->uri),
2555                       " was not found on this server.<P>\n", NULL);
2556             break;
2557         case METHOD_NOT_ALLOWED:
2558             ap_rvputs(r, "The requested method ", r->method,
2559                       " is not allowed "
2560                       "for the URL ", ap_escape_html(r->pool, r->uri),
2561                       ".<P>\n", NULL);
2562             break;
2563         case NOT_ACCEPTABLE:
2564             ap_rvputs(r,
2565                       "An appropriate representation of the "
2566                       "requested resource ",
2567                       ap_escape_html(r->pool, r->uri),
2568                       " could not be found on this server.<P>\n", NULL);
2569             /* fall through */
2570         case MULTIPLE_CHOICES:
2571             {
2572                 const char *list;
2573                 if ((list = ap_table_get(r->notes, "variant-list")))
2574                     ap_rputs(list, r);
2575             }
2576             break;
2577         case LENGTH_REQUIRED:
2578             ap_rvputs(r, "A request of the requested method ", r->method,
2579                       " requires a valid Content-length.<P>\n", NULL);
2580             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2581                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2582             }
2583             break;
2584         case PRECONDITION_FAILED:
2585             ap_rvputs(r, "The precondition on the request for the URL ",
2586                       ap_escape_html(r->pool, r->uri),
2587                       " evaluated to false.<P>\n", NULL);
2588             break;
2589         case HTTP_NOT_IMPLEMENTED:
2590             ap_rvputs(r, ap_escape_html(r->pool, r->method), " to ",
2591                       ap_escape_html(r->pool, r->uri),
2592                       " not supported.<P>\n", NULL);
2593             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2594                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2595             }
2596             break;
2597         case BAD_GATEWAY:
2598             ap_rputs("The proxy server received an invalid\015\012"
2599                      "response from an upstream server.<P>\015\012", r);
2600             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2601                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2602             }
2603             break;
2604         case VARIANT_ALSO_VARIES:
2605             ap_rvputs(r, "A variant for the requested resource\n<PRE>\n",
2606                       ap_escape_html(r->pool, r->uri),
2607                       "\n</PRE>\nis itself a negotiable resource. "
2608                       "This indicates a configuration error.<P>\n", NULL);
2609             break;
2610         case HTTP_REQUEST_TIME_OUT:
2611             ap_rputs("I'm tired of waiting for your request.\n", r);
2612             break;
2613         case HTTP_GONE:
2614             ap_rvputs(r, "The requested resource<BR>",
2615                       ap_escape_html(r->pool, r->uri),
2616                       "<BR>\nis no longer available on this server ",
2617                       "and there is no forwarding address.\n",
2618                       "Please remove all references to this resource.\n",
2619                       NULL);
2620             break;
2621         case HTTP_REQUEST_ENTITY_TOO_LARGE:
2622             ap_rvputs(r, "The requested resource<BR>",
2623                       ap_escape_html(r->pool, r->uri), "<BR>\n",
2624                       "does not allow request data with ", r->method,
2625                       " requests, or the amount of data provided in\n",
2626                       "the request exceeds the capacity limit.\n", NULL);
2627             break;
2628         case HTTP_REQUEST_URI_TOO_LARGE:
2629             ap_rputs("The requested URL's length exceeds the capacity\n"
2630                      "limit for this server.<P>\n", r);
2631             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2632                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2633             }
2634             break;
2635         case HTTP_UNSUPPORTED_MEDIA_TYPE:
2636             ap_rputs("The supplied request data is not in a format\n"
2637                      "acceptable for processing by this resource.\n", r);
2638             break;
2639         case HTTP_RANGE_NOT_SATISFIABLE:
2640             ap_rputs("None of the range-specifier values in the Range\n"
2641                      "request-header field overlap the current extent\n"
2642                      "of the selected resource.\n", r);
2643             break;
2644         case HTTP_EXPECTATION_FAILED:
2645             ap_rvputs(r, "The expectation given in the Expect request-header"
2646                       "\nfield could not be met by this server.<P>\n"
2647                       "The client sent<PRE>\n    Expect: ",
2648                       ap_table_get(r->headers_in, "Expect"), "\n</PRE>\n"
2649                       "but we only allow the 100-continue expectation.\n",
2650                       NULL);
2651             break;
2652         case HTTP_UNPROCESSABLE_ENTITY:
2653             ap_rputs("The server understands the media type of the\n"
2654                      "request entity, but was unable to process the\n"
2655                      "contained instructions.\n", r);
2656             break;
2657         case HTTP_LOCKED:
2658             ap_rputs("The requested resource is currently locked.\n"
2659                      "The lock must be released or proper identification\n"
2660                      "given before the method can be applied.\n", r);
2661             break;
2662         case HTTP_FAILED_DEPENDENCY:
2663             ap_rputs("The method could not be performed on the resource\n"
2664                      "because the requested action depended on another\n"
2665                      "action and that other action failed.\n", r);
2666             break;
2667         case HTTP_INSUFFICIENT_STORAGE:
2668             ap_rputs("The method could not be performed on the resource\n"
2669                      "because the server is unable to store the\n"
2670                      "representation needed to successfully complete the\n"
2671                      "request.  There is insufficient free space left in\n"
2672                      "your storage allocation.\n", r);
2673             break;
2674         case HTTP_SERVICE_UNAVAILABLE:
2675             ap_rputs("The server is temporarily unable to service your\n"
2676                      "request due to maintenance downtime or capacity\n"
2677                      "problems. Please try again later.\n", r);
2678             break;
2679         case HTTP_GATEWAY_TIME_OUT:
2680             ap_rputs("The proxy server did not receive a timely response\n"
2681                      "from the upstream server.\n", r);
2682             break;
2683         case HTTP_NOT_EXTENDED:
2684             ap_rputs("A mandatory extension policy in the request is not\n"
2685                      "accepted by the server for this resource.\n", r);
2686             break;
2687         default:            /* HTTP_INTERNAL_SERVER_ERROR */
2688             /*
2689              * This comparison to expose error-notes could be modified to
2690              * use a configuration directive and export based on that 
2691              * directive.  For now "*" is used to designate an error-notes
2692              * that is totally safe for any user to see (ie lacks paths,
2693              * database passwords, etc.)
2694              */
2695             if (((error_notes = ap_table_get(r->notes, "error-notes")) != NULL)
2696                 && (h1 = ap_table_get(r->notes, "verbose-error-to")) != NULL
2697                 && (strcmp(h1, "*") == 0)) {
2698                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2699             }
2700             else {
2701                 ap_rvputs(r, "The server encountered an internal error or\n"
2702                      "misconfiguration and was unable to complete\n"
2703                      "your request.<P>\n"
2704                      "Please contact the server administrator,\n ",
2705                      ap_escape_html(r->pool, r->server->server_admin),
2706                      " and inform them of the time the error occurred,\n"
2707                      "and anything you might have done that may have\n"
2708                      "caused the error.<P>\n"
2709                      "More information about this error may be available\n"
2710                      "in the server error log.<P>\n", NULL);
2711             }
2712          /*
2713           * It would be nice to give the user the information they need to
2714           * fix the problem directly since many users don't have access to
2715           * the error_log (think University sites) even though they can easily
2716           * get this error by misconfiguring an htaccess file.  However, the
2717           * error notes tend to include the real file pathname in this case,
2718           * which some people consider to be a breach of privacy.  Until we
2719           * can figure out a way to remove the pathname, leave this commented.
2720           *
2721           * if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2722           *     ap_rvputs(r, error_notes, "<P>\n", NULL);
2723           * }
2724           */
2725             break;
2726         }
2727
2728         if (recursive_error) {
2729             ap_rvputs(r, "<P>Additionally, a ",
2730                       status_lines[ap_index_of_response(recursive_error)],
2731                       "\nerror was encountered while trying to use an "
2732                       "ErrorDocument to handle the request.\n", NULL);
2733         }
2734         ap_rputs(ap_psignature("<HR>\n", r), r);
2735         ap_rputs("</BODY></HTML>\n", r);
2736     }
2737     ap_finalize_request_protocol(r);
2738     ap_rflush(r);
2739 }
2740
2741 IMPLEMENT_HOOK_RUN_ALL(int,post_read_request,(request_rec *r),(r),OK,DECLINED)
2742 IMPLEMENT_HOOK_RUN_ALL(int,log_transaction,(request_rec *r),(r),OK,DECLINED)
2743 IMPLEMENT_HOOK_RUN_FIRST(const char *,http_method,(const request_rec *r),(r),
2744                          NULL)
2745 IMPLEMENT_HOOK_RUN_FIRST(unsigned short,default_port,(const request_rec *r),
2746                          (r),0)