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