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