]> granicus.if.org Git - apache/blob - modules/http/http_protocol.c
Odd comments and leftover bits from the pthreads version.
[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 <stdarg.h>
77
78 HOOK_STRUCT(
79             HOOK_LINK(post_read_request)
80             HOOK_LINK(log_transaction)
81             HOOK_LINK(http_method)
82             HOOK_LINK(default_port)
83 );
84
85 #define SET_BYTES_SENT(r) \
86   do { if (r->sent_bodyct) \
87           ap_bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
88   } while (0)
89
90
91 static int parse_byterange(char *range, long clength, long *start, long *end)
92 {
93     char *dash = strchr(range, '-');
94
95     if (!dash)
96         return 0;
97
98     if ((dash == range)) {
99         /* In the form "-5" */
100         *start = clength - atol(dash + 1);
101         *end = clength - 1;
102     }
103     else {
104         *dash = '\0';
105         dash++;
106         *start = atol(range);
107         if (*dash)
108             *end = atol(dash);
109         else                    /* "5-" */
110             *end = clength - 1;
111     }
112
113     if (*start < 0)
114         *start = 0;
115
116     if (*end >= clength)
117         *end = clength - 1;
118
119     if (*start > *end)
120         return 0;
121
122     return (*start > 0 || *end < clength - 1);
123 }
124
125 static int internal_byterange(int, long *, request_rec *, const char **, long *,
126                               long *);
127
128 API_EXPORT(int) ap_set_byterange(request_rec *r)
129 {
130     const char *range, *if_range, *match;
131     long range_start, range_end;
132
133     if (!r->clength || r->assbackwards)
134         return 0;
135
136     /* Check for Range request-header (HTTP/1.1) or Request-Range for
137      * backwards-compatibility with second-draft Luotonen/Franks
138      * byte-ranges (e.g. Netscape Navigator 2-3).
139      *
140      * We support this form, with Request-Range, and (farther down) we
141      * send multipart/x-byteranges instead of multipart/byteranges for
142      * Request-Range based requests to work around a bug in Netscape
143      * Navigator 2-3 and MSIE 3.
144      */
145
146     if (!(range = ap_table_get(r->headers_in, "Range")))
147         range = ap_table_get(r->headers_in, "Request-Range");
148
149     if (!range || strncasecmp(range, "bytes=", 6)) {
150         return 0;
151     }
152
153     /* Check the If-Range header for Etag or Date.
154      * Note that this check will return false (as required) if either
155      * of the two etags are weak.
156      */
157     if ((if_range = ap_table_get(r->headers_in, "If-Range"))) {
158         if (if_range[0] == '"') {
159             if (!(match = ap_table_get(r->headers_out, "Etag")) ||
160                 (strcmp(if_range, match) != 0))
161                 return 0;
162         }
163         else if (!(match = ap_table_get(r->headers_out, "Last-Modified")) ||
164                  (strcmp(if_range, match) != 0))
165             return 0;
166     }
167
168     if (!strchr(range, ',')) {
169         /* A single range */
170         if (!parse_byterange(ap_pstrdup(r->pool, range + 6), r->clength,
171                              &range_start, &range_end))
172             return 0;
173
174         r->byterange = 1;
175
176         ap_table_setn(r->headers_out, "Content-Range",
177             ap_psprintf(r->pool, "bytes %ld-%ld/%ld",
178                 range_start, range_end, r->clength));
179         ap_table_setn(r->headers_out, "Content-Length",
180             ap_psprintf(r->pool, "%ld", range_end - range_start + 1));
181     }
182     else {
183         /* a multiple range */
184         const char *r_range = ap_pstrdup(r->pool, range + 6);
185         long tlength = 0;
186
187         r->byterange = 2;
188         r->boundary = ap_psprintf(r->pool, "%lx%lx",
189                                 r->request_time, (long) getpid());
190         while (internal_byterange(0, &tlength, r, &r_range, NULL, NULL));
191         ap_table_setn(r->headers_out, "Content-Length",
192             ap_psprintf(r->pool, "%ld", tlength));
193     }
194
195     r->status = PARTIAL_CONTENT;
196     r->range = range + 6;
197
198     return 1;
199 }
200
201 API_EXPORT(int) ap_each_byterange(request_rec *r, long *offset, long *length)
202 {
203     return internal_byterange(1, NULL, r, &r->range, offset, length);
204 }
205
206 /* If this function is called with realreq=1, it will spit out
207  * the correct headers for a byterange chunk, and set offset and
208  * length to the positions they should be.
209  *
210  * If it is called with realreq=0, it will add to tlength the length
211  * it *would* have used with realreq=1.
212  *
213  * Either case will return 1 if it should be called again, and 0
214  * when done.
215  */
216 static int internal_byterange(int realreq, long *tlength, request_rec *r,
217                               const char **r_range, long *offset, long *length)
218 {
219     long range_start, range_end;
220     char *range;
221
222     if (!**r_range) {
223         if (r->byterange > 1) {
224             if (realreq)
225                 ap_rvputs(r, "\015\012--", r->boundary, "--\015\012", NULL);
226             else
227                 *tlength += 4 + strlen(r->boundary) + 4;
228         }
229         return 0;
230     }
231
232     range = ap_getword(r->pool, r_range, ',');
233     if (!parse_byterange(range, r->clength, &range_start, &range_end))
234         /* Skip this one */
235         return internal_byterange(realreq, tlength, r, r_range, offset,
236                                   length);
237
238     if (r->byterange > 1) {
239         const char *ct = r->content_type ? r->content_type : ap_default_type(r);
240         char ts[MAX_STRING_LEN];
241
242         ap_snprintf(ts, sizeof(ts), "%ld-%ld/%ld", range_start, range_end,
243                     r->clength);
244         if (realreq)
245             ap_rvputs(r, "\015\012--", r->boundary, "\015\012Content-type: ",
246                    ct, "\015\012Content-range: bytes ", ts, "\015\012\015\012",
247                    NULL);
248         else
249             *tlength += 4 + strlen(r->boundary) + 16 + strlen(ct) + 23 +
250                         strlen(ts) + 4;
251     }
252
253     if (realreq) {
254         *offset = range_start;
255         *length = range_end - range_start + 1;
256     }
257     else {
258         *tlength += range_end - range_start + 1;
259     }
260     return 1;
261 }
262
263 API_EXPORT(int) ap_set_content_length(request_rec *r, long clength)
264 {
265     r->clength = clength;
266     ap_table_setn(r->headers_out, "Content-Length", ap_psprintf(r->pool, "%ld", clength));
267     return 0;
268 }
269
270 API_EXPORT(int) ap_set_keepalive(request_rec *r)
271 {
272     int ka_sent = 0;
273     int wimpy = ap_find_token(r->pool,
274                            ap_table_get(r->headers_out, "Connection"), "close");
275     const char *conn = ap_table_get(r->headers_in, "Connection");
276
277     /* The following convoluted conditional determines whether or not
278      * the current connection should remain persistent after this response
279      * (a.k.a. HTTP Keep-Alive) and whether or not the output message
280      * body should use the HTTP/1.1 chunked transfer-coding.  In English,
281      *
282      *   IF  we have not marked this connection as errored;
283      *   and the response body has a defined length due to the status code
284      *       being 304 or 204, the request method being HEAD, already
285      *       having defined Content-Length or Transfer-Encoding: chunked, or
286      *       the request version being HTTP/1.1 and thus capable of being set
287      *       as chunked [we know the (r->chunked = 1) side-effect is ugly];
288      *   and the server configuration enables keep-alive;
289      *   and the server configuration has a reasonable inter-request timeout;
290      *   and there is no maximum # requests or the max hasn't been reached;
291      *   and the response status does not require a close;
292      *   and the response generator has not already indicated close;
293      *   and the client did not request non-persistence (Connection: close);
294      *   and    we haven't been configured to ignore the buggy twit
295      *       or they're a buggy twit coming through a HTTP/1.1 proxy
296      *   and    the client is requesting an HTTP/1.0-style keep-alive
297      *       or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
298      *   THEN we can be persistent, which requires more headers be output.
299      *
300      * Note that the condition evaluation order is extremely important.
301      */
302     if ((r->connection->keepalive != -1) &&
303         ((r->status == HTTP_NOT_MODIFIED) ||
304          (r->status == HTTP_NO_CONTENT) ||
305          r->header_only ||
306          ap_table_get(r->headers_out, "Content-Length") ||
307          ap_find_last_token(r->pool,
308                          ap_table_get(r->headers_out, "Transfer-Encoding"),
309                          "chunked") ||
310          ((r->proto_num >= HTTP_VERSION(1,1)) &&
311           (r->chunked = 1))) && /* THIS CODE IS CORRECT, see comment above. */
312         r->server->keep_alive &&
313         /* ZZZ change to APR keepalive timeout defined value */
314         (r->server->keep_alive_timeout > 0) &&
315         ((r->server->keep_alive_max == 0) ||
316          (r->server->keep_alive_max > r->connection->keepalives)) &&
317         !ap_status_drops_connection(r->status) &&
318         !wimpy &&
319         !ap_find_token(r->pool, conn, "close") &&
320         (!ap_table_get(r->subprocess_env, "nokeepalive") ||
321          ap_table_get(r->headers_in, "Via")) &&
322         ((ka_sent = ap_find_token(r->pool, conn, "keep-alive")) ||
323          (r->proto_num >= HTTP_VERSION(1,1)))
324        ) {
325         int left = r->server->keep_alive_max - r->connection->keepalives;
326
327         r->connection->keepalive = 1;
328         r->connection->keepalives++;
329
330         /* If they sent a Keep-Alive token, send one back */
331         if (ka_sent) {
332             if (r->server->keep_alive_max)
333                 ap_table_setn(r->headers_out, "Keep-Alive",
334                     ap_psprintf(r->pool, "timeout=%d, max=%d",
335                             r->server->keep_alive_timeout, left));
336             else
337                 ap_table_setn(r->headers_out, "Keep-Alive",
338                     ap_psprintf(r->pool, "timeout=%d",
339                             r->server->keep_alive_timeout));
340             ap_table_mergen(r->headers_out, "Connection", "Keep-Alive");
341         }
342
343         return 1;
344     }
345
346     /* Otherwise, we need to indicate that we will be closing this
347      * connection immediately after the current response.
348      *
349      * We only really need to send "close" to HTTP/1.1 clients, but we
350      * always send it anyway, because a broken proxy may identify itself
351      * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
352      * to a HTTP/1.1 client. Better safe than sorry.
353      */
354     if (!wimpy)
355         ap_table_mergen(r->headers_out, "Connection", "close");
356
357     r->connection->keepalive = 0;
358
359     return 0;
360 }
361
362 /*
363  * Return the latest rational time from a request/mtime (modification time)
364  * pair.  We return the mtime unless it's in the future, in which case we
365  * return the current time.  We use the request time as a reference in order
366  * to limit the number of calls to time().  We don't check for futurosity
367  * unless the mtime is at least as new as the reference.
368  */
369 API_EXPORT(time_t) ap_rationalize_mtime(request_rec *r, time_t mtime)
370 {
371     time_t now;
372
373     /* For all static responses, it's almost certain that the file was
374      * last modified before the beginning of the request.  So there's
375      * no reason to call time(NULL) again.  But if the response has been
376      * created on demand, then it might be newer than the time the request
377      * started.  In this event we really have to call time(NULL) again
378      * so that we can give the clients the most accurate Last-Modified.  If we
379      * were given a time in the future, we return the current time - the
380      * Last-Modified can't be in the future.
381      */
382     /* ZZZ Change time call to use time AP time thread functions. */
383     now = (mtime < r->request_time) ? r->request_time : time(NULL);
384     return (mtime > now) ? now : mtime;
385 }
386
387 API_EXPORT(int) ap_meets_conditions(request_rec *r)
388 {
389     const char *etag = ap_table_get(r->headers_out, "ETag");
390     const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
391     time_t mtime;
392
393     /* Check for conditional requests --- note that we only want to do
394      * this if we are successful so far and we are not processing a
395      * subrequest or an ErrorDocument.
396      *
397      * The order of the checks is important, since ETag checks are supposed
398      * to be more accurate than checks relative to the modification time.
399      * However, not all documents are guaranteed to *have* ETags, and some
400      * might have Last-Modified values w/o ETags, so this gets a little
401      * complicated.
402      */
403
404     if (!ap_is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
405         return OK;
406     }
407
408     /* ZZZ We are changing time(NULL) to AP time thread functions. */
409     mtime = (r->mtime != 0) ? r->mtime : time(NULL);
410
411     /* If an If-Match request-header field was given
412      * AND the field value is not "*" (meaning match anything)
413      * AND if our strong ETag does not match any entity tag in that field,
414      *     respond with a status of 412 (Precondition Failed).
415      */
416     if ((if_match = ap_table_get(r->headers_in, "If-Match")) != NULL) {
417         if (if_match[0] != '*' &&
418             (etag == NULL || etag[0] == 'W' ||
419              !ap_find_list_item(r->pool, if_match, etag))) {
420             return HTTP_PRECONDITION_FAILED;
421         }
422     }
423     else {
424         /* Else if a valid If-Unmodified-Since request-header field was given
425          * AND the requested resource has been modified since the time
426          * specified in this field, then the server MUST
427          *     respond with a status of 412 (Precondition Failed).
428          */
429         if_unmodified = ap_table_get(r->headers_in, "If-Unmodified-Since");
430         if (if_unmodified != NULL) {
431             /* ZZZ we are changing time funcs to AP time thread funcs.
432                and we need to check return values of ap_parseHTTPdate. */
433             time_t ius ;
434             if (ap_parseHTTPdate(if_unmodified, &ius) == 1
435                 && (mtime > ius)) {
436                 return HTTP_PRECONDITION_FAILED;
437             }
438         }
439     }
440
441     /* If an If-None-Match request-header field was given
442      * AND the field value is "*" (meaning match anything)
443      *     OR our ETag matches any of the entity tags in that field, fail.
444      *
445      * If the request method was GET or HEAD, failure means the server
446      *    SHOULD respond with a 304 (Not Modified) response.
447      * For all other request methods, failure means the server MUST
448      *    respond with a status of 412 (Precondition Failed).
449      *
450      * GET or HEAD allow weak etag comparison, all other methods require
451      * strong comparison.  We can only use weak if it's not a range request.
452      */
453     if_nonematch = ap_table_get(r->headers_in, "If-None-Match");
454     if (if_nonematch != NULL) {
455         if (r->method_number == M_GET) {
456             if (if_nonematch[0] == '*')
457                 return HTTP_NOT_MODIFIED;
458             if (etag != NULL) {
459                 if (ap_table_get(r->headers_in, "Range")) {
460                     if (etag[0] != 'W' &&
461                         ap_find_list_item(r->pool, if_nonematch, etag)) {
462                         return HTTP_NOT_MODIFIED;
463                     }
464                 }
465                 else if (strstr(if_nonematch, etag)) {
466                     return HTTP_NOT_MODIFIED;
467                 }
468             }
469         }
470         else if (if_nonematch[0] == '*' ||
471                  (etag != NULL &&
472                   ap_find_list_item(r->pool, if_nonematch, etag))) {
473             return HTTP_PRECONDITION_FAILED;
474         }
475     }
476     /* Else if a valid If-Modified-Since request-header field was given
477      * AND it is a GET or HEAD request
478      * AND the requested resource has not been modified since the time
479      * specified in this field, then the server MUST
480      *    respond with a status of 304 (Not Modified).
481      * A date later than the server's current request time is invalid.
482      */
483     else if ((r->method_number == M_GET)
484              && ((if_modified_since =
485                   ap_table_get(r->headers_in, "If-Modified-Since")) != NULL)) {
486         time_t ims;
487         if (ap_parseHTTPdate(if_modified_since, &ims) != 1) {
488             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
489                          r->server, "bogus if-modified-since-header");
490         }
491         else if ((ims >= mtime) && (ims <= r->request_time)) {
492             return HTTP_NOT_MODIFIED;
493         }
494     }
495     return OK;
496 }
497
498 /*
499  * Construct an entity tag (ETag) from resource information.  If it's a real
500  * file, build in some of the file characteristics.  If the modification time
501  * is newer than (request-time minus 1 second), mark the ETag as weak - it
502  * could be modified again in as short an interval.  We rationalize the
503  * modification time we're given to keep it from being in the future.
504  */
505 API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak)
506 {
507     char *etag;
508     char *weak;
509
510     /*
511      * Make an ETag header out of various pieces of information. We use
512      * the last-modified date and, if we have a real file, the
513      * length and inode number - note that this doesn't have to match
514      * the content-length (i.e. includes), it just has to be unique
515      * for the file.
516      *
517      * If the request was made within a second of the last-modified date,
518      * we send a weak tag instead of a strong one, since it could
519      * be modified again later in the second, and the validation
520      * would be incorrect.
521      */
522     
523     weak = ((r->request_time - r->mtime > 1) && !force_weak) ? "" : "W/";
524
525     if (r->finfo.st_mode != 0) {
526         etag = ap_psprintf(r->pool,
527                     "%s\"%lx-%lx-%lx\"", weak,
528                     (unsigned long) r->finfo.st_ino,
529                     (unsigned long) r->finfo.st_size,
530                     (unsigned long) r->mtime);
531     }
532     else {
533         etag = ap_psprintf(r->pool, "%s\"%lx\"", weak,
534                     (unsigned long) r->mtime);
535     }
536
537     return etag;
538 }
539
540 API_EXPORT(void) ap_set_etag(request_rec *r)
541 {
542     char *etag;
543     char *variant_etag, *vlv;
544     int vlv_weak;
545
546     if (!r->vlist_validator) {
547         etag = ap_make_etag(r, 0);
548     }
549     else {
550         /* If we have a variant list validator (vlv) due to the
551          * response being negotiated, then we create a structured
552          * entity tag which merges the variant etag with the variant
553          * list validator (vlv).  This merging makes revalidation
554          * somewhat safer, ensures that caches which can deal with
555          * Vary will (eventually) be updated if the set of variants is
556          * changed, and is also a protocol requirement for transparent
557          * content negotiation.
558          */
559
560         /* if the variant list validator is weak, we make the whole
561          * structured etag weak.  If we would not, then clients could
562          * have problems merging range responses if we have different
563          * variants with the same non-globally-unique strong etag.
564          */
565
566         vlv = r->vlist_validator;
567         vlv_weak = (vlv[0] == 'W');
568                
569         variant_etag = ap_make_etag(r, vlv_weak);
570
571         /* merge variant_etag and vlv into a structured etag */
572
573         variant_etag[strlen(variant_etag) - 1] = '\0';
574         if (vlv_weak)
575             vlv += 3;
576         else
577             vlv++;
578         etag = ap_pstrcat(r->pool, variant_etag, ";", vlv, NULL);
579     }
580
581     ap_table_setn(r->headers_out, "ETag", etag);
582 }
583
584 /*
585  * This function sets the Last-Modified output header field to the value
586  * of the mtime field in the request structure - rationalized to keep it from
587  * being in the future.
588  */
589 API_EXPORT(void) ap_set_last_modified(request_rec *r)
590 {
591     time_t mod_time = ap_rationalize_mtime(r, r->mtime);
592
593     ap_table_setn(r->headers_out, "Last-Modified",
594               ap_gm_timestr_822(r->pool, mod_time));
595 }
596
597 /* Get the method number associated with the given string, assumed to
598  * contain an HTTP method.  Returns M_INVALID if not recognized.
599  *
600  * This is the first step toward placing method names in a configurable
601  * list.  Hopefully it (and other routines) can eventually be moved to
602  * something like a mod_http_methods.c, complete with config stuff.
603  */
604 API_EXPORT(int) ap_method_number_of(const char *method)
605 {
606     switch (*method) {
607         case 'H':
608            if (strcmp(method, "HEAD") == 0)
609                return M_GET;   /* see header_only in request_rec */
610            break;
611         case 'G':
612            if (strcmp(method, "GET") == 0)
613                return M_GET;
614            break;
615         case 'P':
616            if (strcmp(method, "POST") == 0)
617                return M_POST;
618            if (strcmp(method, "PUT") == 0)
619                return M_PUT;
620            if (strcmp(method, "PATCH") == 0)
621                return M_PATCH;
622            if (strcmp(method, "PROPFIND") == 0)
623                return M_PROPFIND;
624            if (strcmp(method, "PROPPATCH") == 0)
625                return M_PROPPATCH;
626            break;
627         case 'D':
628            if (strcmp(method, "DELETE") == 0)
629                return M_DELETE;
630            break;
631         case 'C':
632            if (strcmp(method, "CONNECT") == 0)
633                return M_CONNECT;
634            if (strcmp(method, "COPY") == 0)
635                return M_COPY;
636            break;
637         case 'M':
638            if (strcmp(method, "MKCOL") == 0)
639                return M_MKCOL;
640            if (strcmp(method, "MOVE") == 0)
641                return M_MOVE;
642            break;
643         case 'O':
644            if (strcmp(method, "OPTIONS") == 0)
645                return M_OPTIONS;
646            break;
647         case 'T':
648            if (strcmp(method, "TRACE") == 0)
649                return M_TRACE;
650            break;
651         case 'L':
652            if (strcmp(method, "LOCK") == 0)
653                return M_LOCK;
654            break;
655         case 'U':
656            if (strcmp(method, "UNLOCK") == 0)
657                return M_UNLOCK;
658            break;
659     }
660     return M_INVALID;
661 }
662
663 /* Get a line of protocol input, including any continuation lines
664  * caused by MIME folding (or broken clients) if fold != 0, and place it
665  * in the buffer s, of size n bytes, without the ending newline.
666  *
667  * Returns -1 on error, or the length of s.
668  *
669  * Note: Because bgets uses 1 char for newline and 1 char for NUL,
670  *       the most we can get is (n - 2) actual characters if it
671  *       was ended by a newline, or (n - 1) characters if the line
672  *       length exceeded (n - 1).  So, if the result == (n - 1),
673  *       then the actual input line exceeded the buffer length,
674  *       and it would be a good idea for the caller to puke 400 or 414.
675  */
676 static int getline(char *s, int n, BUFF *in, int fold)
677 {
678     char *pos, next;
679     int retval;
680     int total = 0;
681
682     pos = s;
683
684     do {
685         retval = ap_bgets(pos, n, in);
686        /* retval == -1 if error, 0 if EOF */
687
688         if (retval <= 0)
689             return ((retval < 0) && (total == 0)) ? -1 : total;
690
691         /* retval is the number of characters read, not including NUL      */
692
693         n -= retval;            /* Keep track of how much of s is full     */
694         pos += (retval - 1);    /* and where s ends                        */
695         total += retval;        /* and how long s has become               */
696
697         if (*pos == '\n') {     /* Did we get a full line of input?        */
698             /*
699              * Trim any extra trailing spaces or tabs except for the first
700              * space or tab at the beginning of a blank string.  This makes
701              * it much easier to check field values for exact matches, and
702              * saves memory as well.  Terminate string at end of line.
703              */
704             while (pos > (s + 1) && (*(pos - 1) == ' ' || *(pos - 1) == '\t')) {
705                 --pos;          /* trim extra trailing spaces or tabs      */
706                 --total;        /* but not one at the beginning of line    */
707                 ++n;
708             }
709             *pos = '\0';
710             --total;
711             ++n;
712         }
713         else
714             return total;       /* if not, input line exceeded buffer size */
715
716         /* Continue appending if line folding is desired and
717          * the last line was not empty and we have room in the buffer and
718          * the next line begins with a continuation character.
719          */
720     } while (fold && (retval != 1) && (n > 1)
721                   && (next = ap_blookc(in))
722                   && ((next == ' ') || (next == '\t')));
723
724     return total;
725 }
726
727 /* parse_uri: break apart the uri
728  * Side Effects:
729  * - sets r->args to rest after '?' (or NULL if no '?')
730  * - sets r->uri to request uri (without r->args part)
731  * - sets r->hostname (if not set already) from request (scheme://host:port)
732  */
733 CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri)
734 {
735     int status = HTTP_OK;
736
737     r->unparsed_uri = ap_pstrdup(r->pool, uri);
738
739     if (r->method_number == M_CONNECT) {
740         status = ap_parse_hostinfo_components(r->pool, uri, &r->parsed_uri);
741     } else {
742         /* Simple syntax Errors in URLs are trapped by parse_uri_components(). */
743         status = ap_parse_uri_components(r->pool, uri, &r->parsed_uri);
744     }
745
746     if (ap_is_HTTP_SUCCESS(status)) {
747         /* if it has a scheme we may need to do absoluteURI vhost stuff */
748         if (r->parsed_uri.scheme
749             && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r))) {
750             r->hostname = r->parsed_uri.hostname;
751         } else if (r->method_number == M_CONNECT) {
752             r->hostname = r->parsed_uri.hostname;
753         }
754         r->args = r->parsed_uri.query;
755         r->uri = r->parsed_uri.path ? r->parsed_uri.path
756                                     : ap_pstrdup(r->pool, "/");
757 #if defined(OS2) || defined(WIN32)
758         /* Handle path translations for OS/2 and plug security hole.
759          * This will prevent "http://www.wherever.com/..\..\/" from
760          * returning a directory for the root drive.
761          */
762         {
763             char *x;
764
765             for (x = r->uri; (x = strchr(x, '\\')) != NULL; )
766                 *x = '/';
767         }
768 #endif  /* OS2 || WIN32 */
769     }
770     else {
771         r->args = NULL;
772         r->hostname = NULL;
773         r->status = status;             /* set error status */
774         r->uri = ap_pstrdup(r->pool, uri);
775     }
776 }
777
778 static int read_request_line(request_rec *r)
779 {
780     char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* getline's two extra for \n\0 */
781     const char *ll = l;
782     const char *uri;
783     conn_rec *conn = r->connection;
784     int major = 1, minor = 0;   /* Assume HTTP/1.0 if non-"HTTP" protocol */
785     int len;
786
787     /* Read past empty lines until we get a real request line,
788      * a read error, the connection closes (EOF), or we timeout.
789      *
790      * We skip empty lines because browsers have to tack a CRLF on to the end
791      * of POSTs to support old CERN webservers.  But note that we may not
792      * have flushed any previous response completely to the client yet.
793      * We delay the flush as long as possible so that we can improve
794      * performance for clients that are pipelining requests.  If a request
795      * is pipelined then we won't block during the (implicit) read() below.
796      * If the requests aren't pipelined, then the client is still waiting
797      * for the final buffer flush from us, and we will block in the implicit
798      * read().  B_SAFEREAD ensures that the BUFF layer flushes if it will
799      * have to block during a read.
800      */
801     /* TODO: re-implement SAFEREAD external to BUFF using a layer */
802     /* //ap_bsetflag(conn->client, B_SAFEREAD, 1); */
803     ap_bflush(conn->client);
804     while ((len = getline(l, sizeof(l), conn->client, 0)) <= 0) {
805         if ((len < 0) || ap_bgetflag(conn->client, B_EOF)) {
806             /* //ap_bsetflag(conn->client, B_SAFEREAD, 0); */
807             /* this is a hack to make sure that request time is set,
808              * it's not perfect, but it's better than nothing 
809              */
810             r->request_time = time(0);
811             return 0;
812         }
813     }
814     /* we've probably got something to do, ignore graceful restart requests */
815
816     /* XXX - sigwait doesn't work if the signal has been SIG_IGNed (under
817      * linux 2.0 w/ glibc 2.0, anyway), and this step isn't necessary when
818      * we're running a sigwait thread anyway. If/when unthreaded mode is
819      * put back in, we should make sure to ignore this signal iff a sigwait
820      * thread isn't used. - mvsk
821
822 #ifdef SIGWINCH
823     signal(SIGWINCH, SIG_IGN);
824 #endif
825     */
826
827     /* //ap_bsetflag(conn->client, B_SAFEREAD, 0); */
828
829     r->request_time = time(NULL);
830     r->the_request = ap_pstrdup(r->pool, l);
831     r->method = ap_getword_white(r->pool, &ll);
832     uri = ap_getword_white(r->pool, &ll);
833
834     /* Provide quick information about the request method as soon as known */
835
836     r->method_number = ap_method_number_of(r->method);
837     if (r->method_number == M_GET && r->method[0] == 'H') {
838         r->header_only = 1;
839     }
840
841     ap_parse_uri(r, uri);
842
843     /* getline returns (size of max buffer - 1) if it fills up the
844      * buffer before finding the end-of-line.  This is only going to
845      * happen if it exceeds the configured limit for a request-line.
846      */
847     if (len > r->server->limit_req_line) {
848         r->status    = HTTP_REQUEST_URI_TOO_LARGE;
849         r->proto_num = HTTP_VERSION(1,0);
850         r->protocol  = ap_pstrdup(r->pool, "HTTP/1.0");
851         return 0;
852     }
853
854     r->assbackwards = (ll[0] == '\0');
855     r->protocol = ap_pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9");
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     table *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     pool *p;
930     const char *expect;
931     int access_status;
932
933     p = ap_make_sub_pool(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, 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, 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, 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, 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, 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                     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, 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     array_header *values;
1478     char *start;
1479     char *e;
1480     char **strpp;
1481     int  i;
1482
1483     values = (array_header *)d;
1484
1485     e = ap_pstrdup(values->pool, 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     array_header *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     else {
1562         fixup_vary(r);
1563     }
1564
1565     /*
1566      * Now that we are ready to send a response, we need to combine the two
1567      * header field tables into a single table.  If we don't do this, our
1568      * later attempts to set or unset a given fieldname might be bypassed.
1569      */
1570     if (!ap_is_empty_table(r->err_headers_out))
1571         r->headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
1572                                         r->headers_out);
1573
1574     /*
1575      * Remove the 'Vary' header field if the client can't handle it.
1576      * Since this will have nasty effects on HTTP/1.1 caches, force
1577      * the response into HTTP/1.0 mode.
1578      */
1579     if (ap_table_get(r->subprocess_env, "force-no-vary") != NULL) {
1580         ap_table_unset(r->headers_out, "Vary");
1581         r->proto_num = HTTP_VERSION(1,0);
1582         ap_table_set(r->subprocess_env, "force-response-1.0", "1");
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 table 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, 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, 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, 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, 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, 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     long len_read, len_to_read;
1817     long chunk_start = 0;
1818     unsigned long max_body;
1819
1820     if (!r->read_chunked) {     /* Content-length read */
1821         len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
1822         len_read = ap_bread(r->connection->client, buffer, len_to_read);
1823         if (len_read <= 0) {
1824             if (len_read < 0)
1825                 r->connection->keepalive = -1;
1826             return len_read;
1827         }
1828         r->read_length += len_read;
1829         r->remaining -= len_read;
1830         return len_read;
1831     }
1832
1833     /*
1834      * Handle chunked reading Note: we are careful to shorten the input
1835      * bufsiz so that there will always be enough space for us to add a CRLF
1836      * (if necessary).
1837      */
1838     if (r->read_body == REQUEST_CHUNKED_PASS)
1839         bufsiz -= 2;
1840     if (bufsiz <= 0)
1841         return -1;              /* Cannot read chunked with a small buffer */
1842
1843     /* Check to see if we have already read too much request data.
1844      * For efficiency reasons, we only check this at the top of each
1845      * caller read pass, since the limit exists just to stop infinite
1846      * length requests and nobody cares if it goes over by one buffer.
1847      */
1848     max_body = ap_get_limit_req_body(r);
1849     if (max_body && (r->read_length > max_body)) {
1850         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1851             "Chunked request body is larger than the configured limit of %lu",
1852             max_body);
1853         r->connection->keepalive = -1;
1854         return -1;
1855     }
1856
1857     if (r->remaining == 0) {    /* Start of new chunk */
1858
1859         chunk_start = getline(buffer, bufsiz, r->connection->client, 0);
1860         if ((chunk_start <= 0) || (chunk_start >= (bufsiz - 1))
1861             || !ap_isxdigit(*buffer)) {
1862             r->connection->keepalive = -1;
1863             return -1;
1864         }
1865
1866         len_to_read = get_chunk_size(buffer);
1867
1868         if (len_to_read == 0) { /* Last chunk indicated, get footers */
1869             if (r->read_body == REQUEST_CHUNKED_DECHUNK) {
1870                 get_mime_headers(r);
1871                 ap_snprintf(buffer, bufsiz, "%ld", r->read_length);
1872                 ap_table_unset(r->headers_in, "Transfer-Encoding");
1873                 ap_table_setn(r->headers_in, "Content-Length",
1874                     ap_pstrdup(r->pool, buffer));
1875                 return 0;
1876             }
1877             r->remaining = -1;  /* Indicate footers in-progress */
1878         }
1879         else {
1880             r->remaining = len_to_read;
1881         }
1882         if (r->read_body == REQUEST_CHUNKED_PASS) {
1883             buffer[chunk_start++] = CR; /* Restore chunk-size line end  */
1884             buffer[chunk_start++] = LF;
1885             buffer += chunk_start;      /* and pass line on to caller   */
1886             bufsiz -= chunk_start;
1887         }
1888         else {
1889             /* REQUEST_CHUNKED_DECHUNK -- do not include the length of the
1890              * header in the return value
1891              */
1892             chunk_start = 0;
1893         }
1894     }
1895                                 /* When REQUEST_CHUNKED_PASS, we are */
1896     if (r->remaining == -1) {   /* reading footers until empty line  */
1897         len_read = chunk_start;
1898
1899         while ((bufsiz > 1) && ((len_read =
1900                   getline(buffer, bufsiz, r->connection->client, 1)) > 0)) {
1901
1902             if (len_read != (bufsiz - 1)) {
1903                 buffer[len_read++] = CR;        /* Restore footer line end  */
1904                 buffer[len_read++] = LF;
1905             }
1906             chunk_start += len_read;
1907             buffer += len_read;
1908             bufsiz -= len_read;
1909         }
1910         if (len_read < 0) {
1911             r->connection->keepalive = -1;
1912             return -1;
1913         }
1914
1915         if (len_read == 0) {    /* Indicates an empty line */
1916             buffer[0] = CR;
1917             buffer[1] = LF;
1918             chunk_start += 2;
1919             r->remaining = -2;
1920         }
1921         r->read_length += chunk_start;
1922         return chunk_start;
1923     }
1924                                 /* When REQUEST_CHUNKED_PASS, we     */
1925     if (r->remaining == -2) {   /* finished footers when last called */
1926         r->remaining = 0;       /* so now we must signal EOF         */
1927         return 0;
1928     }
1929
1930     /* Otherwise, we are in the midst of reading a chunk of data */
1931
1932     len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
1933
1934     len_read = ap_bread(r->connection->client, buffer, len_to_read);
1935     if (len_read <= 0) {
1936         r->connection->keepalive = -1;
1937         return -1;
1938     }
1939
1940     r->remaining -= len_read;
1941
1942     if (r->remaining == 0) {    /* End of chunk, get trailing CRLF */
1943         if ((c = ap_bgetc(r->connection->client)) == CR) {
1944             c = ap_bgetc(r->connection->client);
1945         }
1946         if (c != LF) {
1947             r->connection->keepalive = -1;
1948             return -1;
1949         }
1950         if (r->read_body == REQUEST_CHUNKED_PASS) {
1951             buffer[len_read++] = CR;
1952             buffer[len_read++] = LF;
1953         }
1954     }
1955     r->read_length += (chunk_start + len_read);
1956
1957     return (chunk_start + len_read);
1958 }
1959
1960 /* In HTTP/1.1, any method can have a body.  However, most GET handlers
1961  * wouldn't know what to do with a request body if they received one.
1962  * This helper routine tests for and reads any message body in the request,
1963  * simply discarding whatever it receives.  We need to do this because
1964  * failing to read the request body would cause it to be interpreted
1965  * as the next request on a persistent connection.
1966  *
1967  * Since we return an error status if the request is malformed, this
1968  * routine should be called at the beginning of a no-body handler, e.g.,
1969  *
1970  *    if ((retval = ap_discard_request_body(r)) != OK)
1971  *        return retval;
1972  */
1973 API_EXPORT(int) ap_discard_request_body(request_rec *r)
1974 {
1975     int rv;
1976
1977     if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_PASS)))
1978         return rv;
1979
1980     /* In order to avoid sending 100 Continue when we already know the
1981      * final response status, and yet not kill the connection if there is
1982      * no request body to be read, we need to duplicate the test from
1983      * ap_should_client_block() here negated rather than call it directly.
1984      */
1985     if ((r->read_length == 0) && (r->read_chunked || (r->remaining > 0))) {
1986         char dumpbuf[HUGE_STRING_LEN];
1987
1988         if (r->expecting_100) {
1989             r->connection->keepalive = -1;
1990             return OK;
1991         }
1992
1993         while ((rv = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN)) > 0)
1994             continue;
1995
1996         if (rv < 0)
1997             return HTTP_BAD_REQUEST;
1998     }
1999     return OK;
2000 }
2001
2002 /*
2003  * Send the body of a response to the client.
2004  */
2005 API_EXPORT(long) ap_send_fd(APRFile fd, request_rec *r)
2006 {
2007     return ap_send_fd_length(fd, r, -1);
2008 }
2009
2010 API_EXPORT(long) ap_send_fd_length(APRFile fd, request_rec *r, long length)
2011 {
2012     char buf[IOBUFSIZE];
2013     long total_bytes_sent = 0;
2014     register int n, w, o;
2015
2016     if (length == 0)
2017         return 0;
2018
2019     while (!ap_is_aborted(r->connection)) {
2020         if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
2021             o = length - total_bytes_sent;
2022         else
2023             o = IOBUFSIZE;
2024
2025         while ((n = read(fd, buf, o)) < 0 && 
2026                 (errno == EINTR || errno == EAGAIN) && 
2027                 !ap_is_aborted(r->connection))
2028             continue;
2029             
2030         if (n < 1) {
2031             break;
2032         }
2033         o = 0;
2034
2035         while (n && !ap_is_aborted(r->connection)) {
2036             w = ap_bwrite(r->connection->client, &buf[o], n);
2037             if (w > 0) {
2038                 total_bytes_sent += w;
2039                 n -= w;
2040                 o += w;
2041             }
2042             else if (w < 0) {
2043                 if (!ap_is_aborted(r->connection)) {
2044                     ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2045                      "client stopped connection before send body completed");
2046                     ap_bsetflag(r->connection->client, B_EOUT, 1);
2047                     r->connection->aborted = 1;
2048                 }
2049                 break;
2050             }
2051         }
2052     }
2053
2054     SET_BYTES_SENT(r);
2055     return total_bytes_sent;
2056 }
2057
2058
2059 /* TODO: re-implement ap_send_fb */
2060 #if 0
2061 /*
2062  * Send the body of a response to the client.
2063  */
2064 API_EXPORT(long) ap_send_fb(BUFF *fb, request_rec *r)
2065 {
2066     return ap_send_fb_length(fb, r, -1);
2067 }
2068
2069 API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length)
2070 {
2071     char buf[IOBUFSIZE];
2072     long total_bytes_sent = 0;
2073     register int n, w, o, len, fd;
2074     struct pollfd fds;
2075
2076     if (length == 0)
2077         return 0;
2078
2079     /* Make fb unbuffered and non-blocking */
2080     ap_bsetflag(fb, B_RD, 0);
2081     fd = ap_bfileno(fb, B_RD);
2082     ap_bnonblock(fd);
2083 #ifdef CHECK_FD_SETSIZE
2084     if (fd >= FD_SETSIZE) {
2085         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
2086             "send body: filedescriptor (%u) larger than FD_SETSIZE (%u) "
2087             "found, you probably need to rebuild Apache with a "
2088             "larger FD_SETSIZE", fd, FD_SETSIZE);
2089         return 0;
2090     }
2091 #endif
2092
2093     fds.fd = fd;
2094     fds.events = POLLIN;
2095
2096     while (!ap_is_aborted(r->connection)) {
2097 #ifdef NDELAY_PIPE_RETURNS_ZERO
2098         /* Contributed by dwd@bell-labs.com for UTS 2.1.2, where the fcntl */
2099         /*   O_NDELAY flag causes read to return 0 when there's nothing */
2100         /*   available when reading from a pipe.  That makes it tricky */
2101         /*   to detect end-of-file :-(.  This stupid bug is even documented */
2102         /*   in the read(2) man page where it says that everything but */
2103         /*   pipes return -1 and EAGAIN.  That makes it a feature, right? */
2104         int afterselect = 0;
2105 #endif
2106         if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
2107             len = length - total_bytes_sent;
2108         else
2109             len = IOBUFSIZE;
2110
2111         do {
2112             n = ap_bread(fb, buf, len);
2113 #ifdef NDELAY_PIPE_RETURNS_ZERO
2114             if ((n > 0) || (n == 0 && afterselect))
2115                 break;
2116 #else
2117             if (n >= 0)
2118                 break;
2119 #endif
2120             if (ap_is_aborted(r->connection))
2121                 break;
2122             if (n < 0 && errno != EAGAIN /* ZZZ rethink for threaded impl */)
2123                 break;
2124
2125             /* we need to block, so flush the output first */
2126             if (ap_bflush(r->connection->client) < 0) {
2127                 ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2128                     "client stopped connection before send body completed");
2129                 ap_bsetflag(r->connection->client, B_EOUT, 1);
2130                 r->connection->aborted = 1;
2131                 break;
2132             }
2133             /*
2134              * we don't care what poll says, we might as well loop back
2135              * around and try another read
2136              */
2137             /* use AP funcs */
2138             poll(&fds, 1, -1);
2139 #ifdef NDELAY_PIPE_RETURNS_ZERO
2140             afterselect = 1;
2141 #endif
2142         } while (!ap_is_aborted(r->connection));
2143
2144         if (n < 1 || ap_is_aborted(r->connection)) {
2145             break;
2146         }
2147         o = 0;
2148
2149         while (n && !ap_is_aborted(r->connection)) {
2150             w = ap_bwrite(r->connection->client, &buf[o], n);
2151             if (w > 0) {
2152                 total_bytes_sent += w;
2153                 n -= w;
2154                 o += w;
2155             }
2156             else if (w < 0) {
2157                 if (!ap_is_aborted(r->connection)) {
2158                     ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2159                        "client stopped connection before send body completed");
2160                     ap_bsetflag(r->connection->client, B_EOUT, 1);
2161                     r->connection->aborted = 1;
2162                 }
2163                 break;
2164             }
2165         }
2166     }
2167
2168     SET_BYTES_SENT(r);
2169     return total_bytes_sent;
2170 }
2171 #endif
2172
2173
2174
2175 /* The code writes MMAP_SEGMENT_SIZE bytes at a time.  This is due to Apache's
2176  * timeout model, which is a timeout per-write rather than a time for the
2177  * entire transaction to complete.  Essentially this should be small enough
2178  * so that in one Timeout period, your slowest clients should be reasonably
2179  * able to receive this many bytes.
2180  *
2181  * To take advantage of zero-copy TCP under Solaris 2.6 this should be a
2182  * multiple of 16k.  (And you need a SunATM2.0 network card.)
2183  */
2184 #ifndef MMAP_SEGMENT_SIZE
2185 #define MMAP_SEGMENT_SIZE       32768
2186 #endif
2187
2188 /* send data from an in-memory buffer */
2189 API_EXPORT(size_t) ap_send_mmap(void *mm, request_rec *r, size_t offset,
2190                              size_t length)
2191 {
2192     size_t total_bytes_sent = 0;
2193     int n, w;
2194
2195     if (length == 0)
2196         return 0;
2197
2198
2199     length += offset;
2200     while (!r->connection->aborted && offset < length) {
2201         if (length - offset > MMAP_SEGMENT_SIZE) {
2202             n = MMAP_SEGMENT_SIZE;
2203         }
2204         else {
2205             n = length - offset;
2206         }
2207
2208         while (n && !r->connection->aborted) {
2209             w = ap_bwrite(r->connection->client, (char *) mm + offset, n);
2210             if (w > 0) {
2211                 total_bytes_sent += w;
2212                 n -= w;
2213                 offset += w;
2214             }
2215             else if (w < 0) {
2216                 if (r->connection->aborted)
2217                     break;
2218                 else if (errno == EAGAIN)
2219                     continue;
2220                 else {
2221                     ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2222                      "client stopped connection before send mmap completed");
2223                     ap_bsetflag(r->connection->client, B_EOUT, 1);
2224                     r->connection->aborted = 1;
2225                     break;
2226                 }
2227             }
2228         }
2229     }
2230
2231     SET_BYTES_SENT(r);
2232     return total_bytes_sent;
2233 }
2234
2235 API_EXPORT(int) ap_rputc(int c, request_rec *r)
2236 {
2237     if (r->connection->aborted)
2238         return EOF;
2239
2240     if (ap_bputc(c, r->connection->client) < 0) {
2241         if (!r->connection->aborted) {
2242             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2243                 "client stopped connection before rputc completed");
2244             ap_bsetflag(r->connection->client, B_EOUT, 1);
2245             r->connection->aborted = 1;
2246         }
2247         return EOF;
2248     }
2249     SET_BYTES_SENT(r);
2250     return c;
2251 }
2252
2253 API_EXPORT(int) ap_rputs(const char *str, request_rec *r)
2254 {
2255     int rcode;
2256
2257     if (r->connection->aborted)
2258         return EOF;
2259     
2260     rcode = ap_bputs(str, r->connection->client);
2261     if (rcode < 0) {
2262         if (!r->connection->aborted) {
2263             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2264                 "client stopped connection before rputs completed");
2265             ap_bsetflag(r->connection->client, B_EOUT, 1);
2266             r->connection->aborted = 1;
2267         }
2268         return EOF;
2269     }
2270     SET_BYTES_SENT(r);
2271     return rcode;
2272 }
2273
2274 API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
2275 {
2276     int n;
2277
2278     if (r->connection->aborted)
2279         return EOF;
2280
2281     n = ap_bwrite(r->connection->client, buf, nbyte);
2282     if (n < 0) {
2283         if (!r->connection->aborted) {
2284             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2285                 "client stopped connection before rwrite completed");
2286             ap_bsetflag(r->connection->client, B_EOUT, 1);
2287             r->connection->aborted = 1;
2288         }
2289         return EOF;
2290     }
2291     SET_BYTES_SENT(r);
2292     return n;
2293 }
2294
2295 API_EXPORT(int) ap_vrprintf(request_rec *r, const char *fmt, va_list ap)
2296 {
2297     int n;
2298
2299     if (r->connection->aborted)
2300         return -1;
2301
2302     n = ap_vbprintf(r->connection->client, fmt, ap);
2303
2304     if (n < 0) {
2305         if (!r->connection->aborted) {
2306             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2307                 "client stopped connection before vrprintf completed");
2308             ap_bsetflag(r->connection->client, B_EOUT, 1);
2309             r->connection->aborted = 1;
2310         }
2311         return -1;
2312     }
2313     SET_BYTES_SENT(r);
2314     return n;
2315 }
2316
2317 API_EXPORT(int) ap_rprintf(request_rec *r, const char *fmt,...)
2318 {
2319     va_list vlist;
2320     int n;
2321
2322     if (r->connection->aborted)
2323         return -1;
2324
2325     va_start(vlist, fmt);
2326     n = ap_vbprintf(r->connection->client, fmt, vlist);
2327     va_end(vlist);
2328
2329     if (n < 0) {
2330         if (!r->connection->aborted) {
2331             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2332                 "client stopped connection before rprintf completed");
2333             ap_bsetflag(r->connection->client, B_EOUT, 1);
2334             r->connection->aborted = 1;
2335         }
2336         return -1;
2337     }
2338     SET_BYTES_SENT(r);
2339     return n;
2340 }
2341
2342 API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...)
2343 {
2344     va_list args;
2345     int i, j, k;
2346     const char *x;
2347     BUFF *fb = r->connection->client;
2348
2349     if (r->connection->aborted)
2350         return EOF;
2351
2352     va_start(args, r);
2353     for (k = 0;;) {
2354         x = va_arg(args, const char *);
2355         if (x == NULL)
2356             break;
2357         j = strlen(x);
2358         i = ap_bwrite(fb, x, j);
2359         if (i != j) {
2360             va_end(args);
2361             if (!r->connection->aborted) {
2362                 ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2363                     "client stopped connection before rvputs completed");
2364                 ap_bsetflag(r->connection->client, B_EOUT, 1);
2365                 r->connection->aborted = 1;
2366             }
2367             return EOF;
2368         }
2369         k += i;
2370     }
2371     va_end(args);
2372
2373     SET_BYTES_SENT(r);
2374     return k;
2375 }
2376
2377 API_EXPORT(int) ap_rflush(request_rec *r)
2378 {
2379     if (ap_bflush(r->connection->client) < 0) {
2380         if (!r->connection->aborted) {
2381             ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
2382                 "client stopped connection before rflush completed");
2383             ap_bsetflag(r->connection->client, B_EOUT, 1);
2384             r->connection->aborted = 1;
2385         }
2386         return EOF;
2387     }
2388     return 0;
2389 }
2390
2391 /* We should have named this send_canned_response, since it is used for any
2392  * response that can be generated by the server from the request record.
2393  * This includes all 204 (no content), 3xx (redirect), 4xx (client error),
2394  * and 5xx (server error) messages that have not been redirected to another
2395  * handler via the ErrorDocument feature.
2396  */
2397 void ap_send_error_response(request_rec *r, int recursive_error)
2398 {
2399     int status = r->status;
2400     int idx = ap_index_of_response(status);
2401     char *custom_response;
2402     const char *location = ap_table_get(r->headers_out, "Location");
2403
2404     /*
2405      * It's possible that the Location field might be in r->err_headers_out
2406      * instead of r->headers_out; use the latter if possible, else the
2407      * former.
2408      */
2409     if (location == NULL) {
2410         location = ap_table_get(r->err_headers_out, "Location");
2411     }
2412     /* We need to special-case the handling of 204 and 304 responses,
2413      * since they have specific HTTP requirements and do not include a
2414      * message body.  Note that being assbackwards here is not an option.
2415      */
2416     if (status == HTTP_NOT_MODIFIED) {
2417         if (!ap_is_empty_table(r->err_headers_out))
2418             r->headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
2419                                                r->headers_out);
2420         ap_basic_http_header(r);
2421         ap_set_keepalive(r);
2422
2423         ap_table_do((int (*)(void *, const char *, const char *)) ap_send_header_field,
2424                     (void *) r, r->headers_out,
2425                     "Connection",
2426                     "Keep-Alive",
2427                     "ETag",
2428                     "Content-Location",
2429                     "Expires",
2430                     "Cache-Control",
2431                     "Vary",
2432                     "Warning",
2433                     "WWW-Authenticate",
2434                     "Proxy-Authenticate",
2435                     NULL);
2436
2437         terminate_header(r);
2438
2439         return;
2440     }
2441
2442     if (status == HTTP_NO_CONTENT) {
2443         ap_send_http_header(r);
2444         ap_finalize_request_protocol(r);
2445         return;
2446     }
2447
2448     if (!r->assbackwards) {
2449         table *tmp = r->headers_out;
2450
2451         /* For all HTTP/1.x responses for which we generate the message,
2452          * we need to avoid inheriting the "normal status" header fields
2453          * that may have been set by the request handler before the
2454          * error or redirect, except for Location on external redirects.
2455          */
2456         r->headers_out = r->err_headers_out;
2457         r->err_headers_out = tmp;
2458         ap_clear_table(r->err_headers_out);
2459
2460         if (ap_is_HTTP_REDIRECT(status) || (status == HTTP_CREATED)) {
2461             if ((location != NULL) && *location) {
2462                 ap_table_setn(r->headers_out, "Location", location);
2463             }
2464             else {
2465                 location = "";   /* avoids coredump when printing, below */
2466             }
2467         }
2468
2469         r->content_language = NULL;
2470         r->content_languages = NULL;
2471         r->content_encoding = NULL;
2472         r->clength = 0;
2473         r->content_type = "text/html";
2474
2475         if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED))
2476             ap_table_setn(r->headers_out, "Allow", make_allow(r));
2477
2478         ap_send_http_header(r);
2479
2480         if (r->header_only) {
2481             ap_finalize_request_protocol(r);
2482             ap_rflush(r);
2483             return;
2484         }
2485     }
2486
2487     if ((custom_response = ap_response_code_string(r, idx))) {
2488         /*
2489          * We have a custom response output. This should only be
2490          * a text-string to write back. But if the ErrorDocument
2491          * was a local redirect and the requested resource failed
2492          * for any reason, the custom_response will still hold the
2493          * redirect URL. We don't really want to output this URL
2494          * as a text message, so first check the custom response
2495          * string to ensure that it is a text-string (using the
2496          * same test used in ap_die(), i.e. does it start with a ").
2497          * If it doesn't, we've got a recursive error, so find
2498          * the original error and output that as well.
2499          */
2500         if (custom_response[0] == '\"') {
2501             ap_rputs(custom_response + 1, r);
2502             ap_finalize_request_protocol(r);
2503             ap_rflush(r);
2504             return;
2505         }
2506         /*
2507          * Redirect failed, so get back the original error
2508          */
2509         while (r->prev && (r->prev->status != HTTP_OK))
2510             r = r->prev;
2511     }
2512     {
2513         const char *title = status_lines[idx];
2514         const char *h1;
2515         const char *error_notes;
2516
2517         /* Accept a status_line set by a module, but only if it begins
2518          * with the 3 digit status code
2519          */
2520         if (r->status_line != NULL
2521             && strlen(r->status_line) > 4       /* long enough */
2522             && ap_isdigit(r->status_line[0])
2523             && ap_isdigit(r->status_line[1])
2524             && ap_isdigit(r->status_line[2])
2525             && ap_isspace(r->status_line[3])
2526             && ap_isalnum(r->status_line[4])) {
2527             title = r->status_line;
2528         }
2529
2530         /* folks decided they didn't want the error code in the H1 text */
2531         h1 = &title[4];
2532
2533         ap_rvputs(r,
2534                   DOCTYPE_HTML_2_0
2535                   "<HTML><HEAD>\n<TITLE>", title,
2536                   "</TITLE>\n</HEAD><BODY>\n<H1>", h1, "</H1>\n",
2537                   NULL);
2538
2539         switch (status) {
2540         case HTTP_MOVED_PERMANENTLY:
2541         case HTTP_MOVED_TEMPORARILY:
2542         case HTTP_TEMPORARY_REDIRECT:
2543             ap_rvputs(r, "The document has moved <A HREF=\"",
2544                       ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
2545                       NULL);
2546             break;
2547         case HTTP_SEE_OTHER:
2548             ap_rvputs(r, "The answer to your request is located <A HREF=\"",
2549                       ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
2550                       NULL);
2551             break;
2552         case HTTP_USE_PROXY:
2553             ap_rvputs(r, "This resource is only accessible "
2554                       "through the proxy\n",
2555                       ap_escape_html(r->pool, location),
2556                       "<BR>\nYou will need to ",
2557                       "configure your client to use that proxy.<P>\n", NULL);
2558             break;
2559         case HTTP_PROXY_AUTHENTICATION_REQUIRED:
2560         case AUTH_REQUIRED:
2561             ap_rputs("This server could not verify that you\n"
2562                      "are authorized to access the document\n"
2563                      "requested.  Either you supplied the wrong\n"
2564                      "credentials (e.g., bad password), or your\n"
2565                      "browser doesn't understand how to supply\n"
2566                      "the credentials required.<P>\n", r);
2567             break;
2568         case BAD_REQUEST:
2569             ap_rputs("Your browser sent a request that "
2570                      "this server could not understand.<P>\n", r);
2571             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2572                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2573             }
2574             break;
2575         case HTTP_FORBIDDEN:
2576             ap_rvputs(r, "You don't have permission to access ",
2577                       ap_escape_html(r->pool, r->uri),
2578                       "\non this server.<P>\n", NULL);
2579             break;
2580         case NOT_FOUND:
2581             ap_rvputs(r, "The requested URL ",
2582                       ap_escape_html(r->pool, r->uri),
2583                       " was not found on this server.<P>\n", NULL);
2584             break;
2585         case METHOD_NOT_ALLOWED:
2586             ap_rvputs(r, "The requested method ", r->method,
2587                       " is not allowed "
2588                       "for the URL ", ap_escape_html(r->pool, r->uri),
2589                       ".<P>\n", NULL);
2590             break;
2591         case NOT_ACCEPTABLE:
2592             ap_rvputs(r,
2593                       "An appropriate representation of the "
2594                       "requested resource ",
2595                       ap_escape_html(r->pool, r->uri),
2596                       " could not be found on this server.<P>\n", NULL);
2597             /* fall through */
2598         case MULTIPLE_CHOICES:
2599             {
2600                 const char *list;
2601                 if ((list = ap_table_get(r->notes, "variant-list")))
2602                     ap_rputs(list, r);
2603             }
2604             break;
2605         case LENGTH_REQUIRED:
2606             ap_rvputs(r, "A request of the requested method ", r->method,
2607                       " requires a valid Content-length.<P>\n", NULL);
2608             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2609                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2610             }
2611             break;
2612         case PRECONDITION_FAILED:
2613             ap_rvputs(r, "The precondition on the request for the URL ",
2614                       ap_escape_html(r->pool, r->uri),
2615                       " evaluated to false.<P>\n", NULL);
2616             break;
2617         case HTTP_NOT_IMPLEMENTED:
2618             ap_rvputs(r, ap_escape_html(r->pool, r->method), " to ",
2619                       ap_escape_html(r->pool, r->uri),
2620                       " not supported.<P>\n", NULL);
2621             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2622                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2623             }
2624             break;
2625         case BAD_GATEWAY:
2626             ap_rputs("The proxy server received an invalid\015\012"
2627                      "response from an upstream server.<P>\015\012", r);
2628             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2629                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2630             }
2631             break;
2632         case VARIANT_ALSO_VARIES:
2633             ap_rvputs(r, "A variant for the requested resource\n<PRE>\n",
2634                       ap_escape_html(r->pool, r->uri),
2635                       "\n</PRE>\nis itself a negotiable resource. "
2636                       "This indicates a configuration error.<P>\n", NULL);
2637             break;
2638         case HTTP_REQUEST_TIME_OUT:
2639             ap_rputs("I'm tired of waiting for your request.\n", r);
2640             break;
2641         case HTTP_GONE:
2642             ap_rvputs(r, "The requested resource<BR>",
2643                       ap_escape_html(r->pool, r->uri),
2644                       "<BR>\nis no longer available on this server ",
2645                       "and there is no forwarding address.\n",
2646                       "Please remove all references to this resource.\n",
2647                       NULL);
2648             break;
2649         case HTTP_REQUEST_ENTITY_TOO_LARGE:
2650             ap_rvputs(r, "The requested resource<BR>",
2651                       ap_escape_html(r->pool, r->uri), "<BR>\n",
2652                       "does not allow request data with ", r->method,
2653                       " requests, or the amount of data provided in\n",
2654                       "the request exceeds the capacity limit.\n", NULL);
2655             break;
2656         case HTTP_REQUEST_URI_TOO_LARGE:
2657             ap_rputs("The requested URL's length exceeds the capacity\n"
2658                      "limit for this server.<P>\n", r);
2659             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2660                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2661             }
2662             break;
2663         case HTTP_UNSUPPORTED_MEDIA_TYPE:
2664             ap_rputs("The supplied request data is not in a format\n"
2665                      "acceptable for processing by this resource.\n", r);
2666             break;
2667         case HTTP_RANGE_NOT_SATISFIABLE:
2668             ap_rputs("None of the range-specifier values in the Range\n"
2669                      "request-header field overlap the current extent\n"
2670                      "of the selected resource.\n", r);
2671             break;
2672         case HTTP_EXPECTATION_FAILED:
2673             ap_rvputs(r, "The expectation given in the Expect request-header"
2674                       "\nfield could not be met by this server.<P>\n"
2675                       "The client sent<PRE>\n    Expect: ",
2676                       ap_table_get(r->headers_in, "Expect"), "\n</PRE>\n"
2677                       "but we only allow the 100-continue expectation.\n",
2678                       NULL);
2679             break;
2680         case HTTP_UNPROCESSABLE_ENTITY:
2681             ap_rputs("The server understands the media type of the\n"
2682                      "request entity, but was unable to process the\n"
2683                      "contained instructions.\n", r);
2684             break;
2685         case HTTP_LOCKED:
2686             ap_rputs("The requested resource is currently locked.\n"
2687                      "The lock must be released or proper identification\n"
2688                      "given before the method can be applied.\n", r);
2689             break;
2690         case HTTP_FAILED_DEPENDENCY:
2691             ap_rputs("The method could not be performed on the resource\n"
2692                      "because the requested action depended on another\n"
2693                      "action and that other action failed.\n", r);
2694             break;
2695         case HTTP_INSUFFICIENT_STORAGE:
2696             ap_rputs("The method could not be performed on the resource\n"
2697                      "because the server is unable to store the\n"
2698                      "representation needed to successfully complete the\n"
2699                      "request.  There is insufficient free space left in\n"
2700                      "your storage allocation.\n", r);
2701             break;
2702         case HTTP_SERVICE_UNAVAILABLE:
2703             ap_rputs("The server is temporarily unable to service your\n"
2704                      "request due to maintenance downtime or capacity\n"
2705                      "problems. Please try again later.\n", r);
2706             break;
2707         case HTTP_GATEWAY_TIME_OUT:
2708             ap_rputs("The proxy server did not receive a timely response\n"
2709                      "from the upstream server.\n", r);
2710             break;
2711         case HTTP_NOT_EXTENDED:
2712             ap_rputs("A mandatory extension policy in the request is not\n"
2713                      "accepted by the server for this resource.\n", r);
2714             break;
2715         default:            /* HTTP_INTERNAL_SERVER_ERROR */
2716             /*
2717              * This comparison to expose error-notes could be modified to
2718              * use a configuration directive and export based on that 
2719              * directive.  For now "*" is used to designate an error-notes
2720              * that is totally safe for any user to see (ie lacks paths,
2721              * database passwords, etc.)
2722              */
2723             if (((error_notes = ap_table_get(r->notes, "error-notes")) != NULL)
2724                 && (h1 = ap_table_get(r->notes, "verbose-error-to")) != NULL
2725                 && (strcmp(h1, "*") == 0)) {
2726                 ap_rvputs(r, error_notes, "<P>\n", NULL);
2727             }
2728             else {
2729                 ap_rvputs(r, "The server encountered an internal error or\n"
2730                      "misconfiguration and was unable to complete\n"
2731                      "your request.<P>\n"
2732                      "Please contact the server administrator,\n ",
2733                      ap_escape_html(r->pool, r->server->server_admin),
2734                      " and inform them of the time the error occurred,\n"
2735                      "and anything you might have done that may have\n"
2736                      "caused the error.<P>\n"
2737                      "More information about this error may be available\n"
2738                      "in the server error log.<P>\n", NULL);
2739             }
2740          /*
2741           * It would be nice to give the user the information they need to
2742           * fix the problem directly since many users don't have access to
2743           * the error_log (think University sites) even though they can easily
2744           * get this error by misconfiguring an htaccess file.  However, the
2745           * error notes tend to include the real file pathname in this case,
2746           * which some people consider to be a breach of privacy.  Until we
2747           * can figure out a way to remove the pathname, leave this commented.
2748           *
2749           * if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
2750           *     ap_rvputs(r, error_notes, "<P>\n", NULL);
2751           * }
2752           */
2753             break;
2754         }
2755
2756         if (recursive_error) {
2757             ap_rvputs(r, "<P>Additionally, a ",
2758                       status_lines[ap_index_of_response(recursive_error)],
2759                       "\nerror was encountered while trying to use an "
2760                       "ErrorDocument to handle the request.\n", NULL);
2761         }
2762         ap_rputs(ap_psignature("<HR>\n", r), r);
2763         ap_rputs("</BODY></HTML>\n", r);
2764     }
2765     ap_finalize_request_protocol(r);
2766     ap_rflush(r);
2767 }
2768
2769 IMPLEMENT_HOOK_RUN_ALL(int,post_read_request,(request_rec *r),(r),OK,DECLINED)
2770 IMPLEMENT_HOOK_RUN_ALL(int,log_transaction,(request_rec *r),(r),OK,DECLINED)
2771 IMPLEMENT_HOOK_RUN_FIRST(const char *,http_method,(const request_rec *r),(r),
2772                          NULL)
2773 IMPLEMENT_HOOK_RUN_FIRST(unsigned short,default_port,(const request_rec *r),
2774                          (r),0)