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