]> granicus.if.org Git - apache/blob - server/protocol.c
ap_rgetline(): completely ignore an empty bucket... previously the logic
[apache] / server / protocol.c
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  *    if any, must include the following acknowledgment:
21  *       "This product includes software developed by the
22  *        Apache Software Foundation (http://www.apache.org/)."
23  *    Alternately, this acknowledgment may appear in the software itself,
24  *    if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  *    not be used to endorse or promote products derived from this
28  *    software without prior written permission. For written
29  *    permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  *    nor may "Apache" appear in their name, without prior written
33  *    permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation.  For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  *
54  * Portions of this software are based upon public domain software
55  * originally written at the National Center for Supercomputing Applications,
56  * University of Illinois, Urbana-Champaign.
57  */
58
59 /*
60  * http_protocol.c --- routines which directly communicate with the client.
61  *
62  * Code originally by Rob McCool; much redone by Robert S. Thau
63  * and the Apache Software Foundation.
64  */
65
66 #include "apr.h"
67 #include "apr_strings.h"
68 #include "apr_buckets.h"
69 #include "apr_lib.h"
70 #include "apr_signal.h"
71
72 #define APR_WANT_STDIO          /* for sscanf */
73 #define APR_WANT_STRFUNC
74 #define APR_WANT_MEMFUNC
75 #include "apr_want.h"
76
77 #define CORE_PRIVATE
78 #include "util_filter.h"
79 #include "ap_config.h"
80 #include "httpd.h"
81 #include "http_config.h"
82 #include "http_core.h"
83 #include "http_protocol.h"
84 #include "http_main.h"
85 #include "http_request.h"
86 #include "http_vhost.h"
87 #include "http_log.h"           /* For errors detected in basic auth common
88                                  * support code... */
89 #include "util_charset.h"
90 #include "util_ebcdic.h"
91
92 #if APR_HAVE_STDARG_H
93 #include <stdarg.h>
94 #endif
95 #if APR_HAVE_UNISTD_H
96 #include <unistd.h>
97 #endif
98
99
100 APR_HOOK_STRUCT(
101             APR_HOOK_LINK(post_read_request)
102             APR_HOOK_LINK(log_transaction)
103             APR_HOOK_LINK(http_method)
104             APR_HOOK_LINK(default_port)
105 )
106
107 AP_DECLARE_DATA ap_filter_rec_t *ap_old_write_func = NULL;
108
109 /*
110  * Builds the content-type that should be sent to the client from the
111  * content-type specified.  The following rules are followed:
112  *    - if type is NULL, type is set to ap_default_type(r)
113  *    - if charset adding is disabled, stop processing and return type.
114  *    - then, if there are no parameters on type, add the default charset
115  *    - return type
116  */
117 AP_DECLARE(const char *)ap_make_content_type(request_rec *r, const char *type)
118 {
119     static const char *needcset[] = {
120         "text/plain",
121         "text/html",
122         NULL };
123     const char **pcset;
124     core_dir_config *conf =
125         (core_dir_config *)ap_get_module_config(r->per_dir_config,
126                                                 &core_module);
127
128     if (!type) {
129         type = ap_default_type(r);
130     }
131     if (conf->add_default_charset != ADD_DEFAULT_CHARSET_ON) {
132         return type;
133     }
134
135     if (ap_strcasestr(type, "charset=") != NULL) {
136         /* already has parameter, do nothing */
137         /* XXX we don't check the validity */
138         ;
139     }
140     else {
141         /* see if it makes sense to add the charset. At present,
142          * we only add it if the Content-type is one of needcset[]
143          */
144         for (pcset = needcset; *pcset ; pcset++) {
145             if (ap_strcasestr(type, *pcset) != NULL) {
146                 type = apr_pstrcat(r->pool, type, "; charset=", 
147                                    conf->add_default_charset_name, NULL);
148                 break;
149             }
150         }
151     }
152     return type;
153 }
154
155 AP_DECLARE(void) ap_set_content_length(request_rec *r, apr_off_t clength)
156 {
157     r->clength = clength;
158     apr_table_setn(r->headers_out, "Content-Length",
159                    apr_off_t_toa(r->pool, clength));
160 }
161
162 /*
163  * Return the latest rational time from a request/mtime (modification time)
164  * pair.  We return the mtime unless it's in the future, in which case we
165  * return the current time.  We use the request time as a reference in order
166  * to limit the number of calls to time().  We don't check for futurosity
167  * unless the mtime is at least as new as the reference.
168  */
169 AP_DECLARE(apr_time_t) ap_rationalize_mtime(request_rec *r, apr_time_t mtime)
170 {
171     apr_time_t now;
172
173     /* For all static responses, it's almost certain that the file was
174      * last modified before the beginning of the request.  So there's
175      * no reason to call time(NULL) again.  But if the response has been
176      * created on demand, then it might be newer than the time the request
177      * started.  In this event we really have to call time(NULL) again
178      * so that we can give the clients the most accurate Last-Modified.  If we
179      * were given a time in the future, we return the current time - the
180      * Last-Modified can't be in the future.
181      */
182     now = (mtime < r->request_time) ? r->request_time : apr_time_now();
183     return (mtime > now) ? now : mtime;
184 }
185
186 /* Get a line of protocol input, including any continuation lines
187  * caused by MIME folding (or broken clients) if fold != 0, and place it
188  * in the buffer s, of size n bytes, without the ending newline.
189  *
190  * If s is NULL, ap_rgetline will allocate necessary memory from r->pool.
191  *
192  * Returns APR_SUCCESS if there are no problems and sets *read to be
193  * the full length of s.
194  *
195  * APR_ENOSPC is returned if there is not enough buffer space.
196  * Other errors may be returned on other errors.
197  *
198  * The LF is *not* returned in the buffer.  Therefore, a *read of 0
199  * indicates that an empty line was read.
200  *
201  * Notes: Because the buffer uses 1 char for NUL, the most we can return is 
202  *        (n - 1) actual characters.  
203  *
204  *        If no LF is detected on the last line due to a dropped connection 
205  *        or a full buffer, that's considered an error.
206  */
207 AP_DECLARE(apr_status_t) ap_rgetline(char **s, apr_size_t n, 
208                                      apr_size_t *read, request_rec *r, 
209                                      int fold)
210 {
211     apr_status_t rv;
212     apr_bucket_brigade *b;
213     apr_bucket *e;
214     apr_size_t bytes_handled = 0, current_alloc = 0;
215     char *pos, *last_char = *s;
216     int do_alloc = (*s == NULL), saw_eos = 0;
217
218     b = apr_brigade_create(r->pool);
219     rv = ap_get_brigade(r->input_filters, b, AP_MODE_GETLINE,
220                         APR_BLOCK_READ, 0);
221
222     if (rv != APR_SUCCESS) {
223         return rv;
224     }
225
226     /* Something horribly wrong happened.  Someone didn't block! */
227     if (APR_BRIGADE_EMPTY(b)) {
228         return APR_EGENERAL; 
229     }
230
231     APR_BRIGADE_FOREACH(e, b) {
232         const char *str;
233         apr_size_t len;
234
235         /* If we see an EOS, don't bother doing anything more. */
236         if (APR_BUCKET_IS_EOS(e)) {
237             saw_eos = 1; 
238             break;
239         }
240
241         rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
242
243         if (rv != APR_SUCCESS) {
244             apr_brigade_destroy(b);
245             return rv;
246         }
247
248         if (len == 0) {
249             /* no use attempting a zero-byte alloc (hurts when
250              * using --with-efence --enable-pool-debug) or
251              * doing any of the other logic either
252              */
253             continue;
254         }
255         
256         /* Would this overrun our buffer?  If so, we'll die. */
257         if (n < bytes_handled + len) {
258             apr_brigade_destroy(b); 
259             return APR_ENOSPC;
260         }
261
262         /* Do we have to handle the allocation ourselves? */
263         if (do_alloc) {
264             /* We'll assume the common case where one bucket is enough. */
265             if (!*s) {
266                 current_alloc = len;
267                 *s = apr_palloc(r->pool, len);
268             }
269             else if (bytes_handled + len > current_alloc) {
270                 /* We resize to the next power of 2. */
271                 apr_size_t new_size = current_alloc;
272                 char *new_buffer;
273                 do {
274                     new_size *= 2;
275                 } while (bytes_handled + len > new_size);
276                 new_buffer = apr_palloc(r->pool, new_size);
277                 /* Copy what we already had. */
278                 memcpy(new_buffer, *s, bytes_handled);
279                 current_alloc = new_size;
280                 *s = new_buffer;
281             }
282         }
283         /* Just copy the rest of the data to the end of the old buffer. */
284         pos = *s + bytes_handled;
285         memcpy(pos, str, len);
286         last_char = pos + len - 1;
287
288         /* We've now processed that new data - update accordingly. */
289         bytes_handled += len;
290     }
291
292     /* We no longer need the returned brigade. */
293     apr_brigade_destroy(b);
294
295     /* We likely aborted early before reading anything or we read no 
296      * data.  Technically, this might be success condition.  But,
297      * probably means something is horribly wrong.  For now, we'll
298      * treat this as APR_SUCCESS, but it may be worth re-examining.
299      */
300     if (bytes_handled == 0) {
301         *read = 0;
302         return APR_SUCCESS; 
303     }
304
305     /* If we didn't get a full line of input, try again. */
306     if (*last_char != APR_ASCII_LF) {
307         /* Do we have enough space? We may be full now. */
308         if (bytes_handled < n) {
309             apr_size_t next_size, next_len;
310             char *tmp;
311      
312             /* If we're doing the allocations for them, we have to
313              * give ourselves a NULL and copy it on return.
314              */ 
315             if (do_alloc) {
316                 tmp = NULL;
317             } else {
318                 /* We're not null terminated yet. */
319                 tmp = last_char + 1;
320             }
321
322             next_size = n - bytes_handled;
323
324             rv = ap_rgetline(&tmp, next_size, &next_len, r, fold);
325
326             if (rv != APR_SUCCESS) {
327                 return rv;
328             }
329
330             if (do_alloc && next_len > 0) {
331                 char *new_buffer;
332                 apr_size_t new_size = bytes_handled + next_len;
333                 /* Again we need to alloc an extra two bytes for LF, null */
334                 new_buffer = apr_palloc(r->pool, new_size);
335                 /* Copy what we already had. */
336                 memcpy(new_buffer, *s, bytes_handled);
337                 memcpy(new_buffer + bytes_handled, tmp, next_len);
338                 current_alloc = new_size;
339                 *s = new_buffer;
340             }
341
342             bytes_handled += next_len;
343             last_char = *s + bytes_handled - 1;
344         }
345         else {
346             return APR_ENOSPC;
347         }
348     }
349
350     /* We now go backwards over any CR (if present) or white spaces.
351      *
352      * Trim any extra trailing spaces or tabs except for the first
353      * space or tab at the beginning of a blank string.  This makes
354      * it much easier to check field values for exact matches, and
355      * saves memory as well.  Terminate string at end of line.
356      */
357     pos = last_char;
358     if (pos > *s && *(pos - 1) == APR_ASCII_CR) {
359         --pos;
360     }
361
362     /* Trim any extra trailing spaces or tabs except for the first
363      * space or tab at the beginning of a blank string.  This makes
364      * it much easier to check field values for exact matches, and
365      * saves memory as well.
366      */
367     while (pos > ((*s) + 1) && 
368            (*(pos - 1) == APR_ASCII_BLANK || *(pos - 1) == APR_ASCII_TAB)) {
369         --pos;
370     }
371
372     /* Since we want to remove the LF from the line, we'll go ahead
373      * and set this last character to be the term NULL and reset 
374      * bytes_handled accordingly.
375      */
376     *pos = '\0';
377     last_char = pos;
378     bytes_handled = pos - *s;
379    
380     /* If we're folding, we have more work to do. 
381      *
382      * Note that if an EOS was seen, we know we can't have another line.
383      */
384     if (fold && bytes_handled && !saw_eos) {
385         const char *str;
386         apr_size_t len;
387
388         /* We only care about the first byte. */
389         rv = ap_get_brigade(r->input_filters, b, AP_MODE_SPECULATIVE,
390                             APR_BLOCK_READ, 1);
391
392         if (rv != APR_SUCCESS) {
393             return rv;
394         }
395
396         e = APR_BRIGADE_FIRST(b);
397
398         /* If we see an EOS, don't bother doing anything more. */
399         if (APR_BUCKET_IS_EOS(e)) {
400             *read = bytes_handled;
401             return APR_SUCCESS;
402         }
403
404         rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
405
406         if (rv != APR_SUCCESS) {
407             return rv;
408         }
409
410         /* Found one, so call ourselves again to get the next line. 
411          *
412          * FIXME: If the folding line is completely blank, should we
413          * stop folding?  Does that require also looking at the next
414          * char?
415          */
416         if (*str == APR_ASCII_BLANK || *str == APR_ASCII_TAB) {
417             /* Do we have enough space? We may be full now. */
418             if (bytes_handled < n) {
419                 apr_size_t next_size, next_len;
420                 char *tmp;
421        
422                 /* If we're doing the allocations for them, we have to
423                  * give ourselves a NULL and copy it on return.
424                  */ 
425                 if (do_alloc) {
426                     tmp = NULL;           
427                 } else { 
428                     /* We're null terminated. */
429                     tmp = last_char;
430                 }
431
432                 next_size = n - bytes_handled;
433
434                 rv = ap_rgetline(&tmp, next_size, &next_len, r, fold);
435
436                 if (rv != APR_SUCCESS) {
437                     return rv;
438                 }
439
440                 if (do_alloc && next_len > 0) {
441                     char *new_buffer;
442                     apr_size_t new_size = bytes_handled + next_len;
443                     /* Again we need to alloc an extra two bytes for LF, null */
444                     new_buffer = apr_palloc(r->pool, new_size);
445                     /* Copy what we already had. */
446                     memcpy(new_buffer, *s, bytes_handled);
447                     memcpy(new_buffer + bytes_handled, tmp, next_len);
448                     current_alloc = new_size;
449                     *s = new_buffer;
450                 }
451
452                 *read = bytes_handled + next_len;
453                 return APR_SUCCESS;
454             }
455             else {
456                 return APR_ENOSPC;
457             }
458         }
459     }
460
461     /* FIXME: Can we optimize this at all by placing it a different layer? */
462     ap_xlate_proto_from_ascii(*s, bytes_handled);
463     *read = bytes_handled;
464     return APR_SUCCESS;
465 }
466
467 AP_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold)
468 {
469     char *tmp_s = s;
470     apr_status_t rv;
471     apr_size_t len;
472
473     rv = ap_rgetline(&tmp_s, n, &len, r, fold);
474
475     /* Map the out-of-space condition to the old API. */
476     if (rv == APR_ENOSPC) {
477         return n;
478     }
479
480     /* Anything else is just bad. */
481     if (rv != APR_SUCCESS) {
482         return -1;
483     }
484
485     return (int)len;
486 }
487
488 /* parse_uri: break apart the uri
489  * Side Effects:
490  * - sets r->args to rest after '?' (or NULL if no '?')
491  * - sets r->uri to request uri (without r->args part)
492  * - sets r->hostname (if not set already) from request (scheme://host:port)
493  */
494 AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri)
495 {
496     int status = HTTP_OK;
497
498     r->unparsed_uri = apr_pstrdup(r->pool, uri);
499
500     if (r->method_number == M_CONNECT) {
501         status = apr_uri_parse_hostinfo(r->pool, uri, &r->parsed_uri);
502     }
503     else {
504         /* Simple syntax Errors in URLs are trapped by parse_uri_components(). */
505         status = apr_uri_parse(r->pool, uri, &r->parsed_uri);
506     }
507
508     if (status == APR_SUCCESS) {
509         /* if it has a scheme we may need to do absoluteURI vhost stuff */
510         if (r->parsed_uri.scheme
511             && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r))) {
512             r->hostname = r->parsed_uri.hostname;
513         }
514         else if (r->method_number == M_CONNECT) {
515             r->hostname = r->parsed_uri.hostname;
516         }
517         r->args = r->parsed_uri.query;
518         r->uri = r->parsed_uri.path ? r->parsed_uri.path
519                                     : apr_pstrdup(r->pool, "/");
520 #if defined(OS2) || defined(WIN32)
521         /* Handle path translations for OS/2 and plug security hole.
522          * This will prevent "http://www.wherever.com/..\..\/" from
523          * returning a directory for the root drive.
524          */
525         {
526             char *x;
527
528             for (x = r->uri; (x = strchr(x, '\\')) != NULL; )
529                 *x = '/';
530         }
531 #endif  /* OS2 || WIN32 */
532     }
533     else {
534         r->args = NULL;
535         r->hostname = NULL;
536         r->status = HTTP_BAD_REQUEST;             /* set error status */
537         r->uri = apr_pstrdup(r->pool, uri);
538     }
539 }
540
541 static int read_request_line(request_rec *r)
542 {
543     const char *ll;
544     const char *uri;
545     const char *pro;
546
547 #if 0
548     conn_rec *conn = r->connection;
549 #endif
550     int major = 1, minor = 0;   /* Assume HTTP/1.0 if non-"HTTP" protocol */
551     apr_size_t len;
552
553     /* Read past empty lines until we get a real request line,
554      * a read error, the connection closes (EOF), or we timeout.
555      *
556      * We skip empty lines because browsers have to tack a CRLF on to the end
557      * of POSTs to support old CERN webservers.  But note that we may not
558      * have flushed any previous response completely to the client yet.
559      * We delay the flush as long as possible so that we can improve
560      * performance for clients that are pipelining requests.  If a request
561      * is pipelined then we won't block during the (implicit) read() below.
562      * If the requests aren't pipelined, then the client is still waiting
563      * for the final buffer flush from us, and we will block in the implicit
564      * read().  B_SAFEREAD ensures that the BUFF layer flushes if it will
565      * have to block during a read.
566      */
567
568     do {
569         apr_status_t rv;
570
571         rv = ap_rgetline(&(r->the_request), DEFAULT_LIMIT_REQUEST_LINE + 2,
572                          &len, r, 0);
573
574         if (rv != APR_SUCCESS) {
575             /* We could get TIMEUP, EOF, or CONNRESET on socket timeouts,
576              * so those are common errors that we don't want to log.
577              */
578             if (!APR_STATUS_IS_TIMEUP(rv) && !APR_STATUS_IS_EOF(rv) &&
579                 !APR_STATUS_IS_ECONNRESET(rv)) {
580                 ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "read_request_line() failed");
581             }
582                 r->request_time = apr_time_now();
583             return 0;
584         }
585     } while (len <= 0);
586
587     /* we've probably got something to do, ignore graceful restart requests */
588
589     r->request_time = apr_time_now();
590     ll = r->the_request;
591     r->method = ap_getword_white(r->pool, &ll);
592
593 #if 0
594 /* XXX If we want to keep track of the Method, the protocol module should do
595  * it.  That support isn't in the scoreboard yet.  Hopefully next week 
596  * sometime.   rbb */
597     ap_update_connection_status(AP_CHILD_THREAD_FROM_ID(conn->id), "Method", r->method); 
598 #endif
599     uri = ap_getword_white(r->pool, &ll);
600
601     /* Provide quick information about the request method as soon as known */
602
603     r->method_number = ap_method_number_of(r->method);
604     if (r->method_number == M_GET && r->method[0] == 'H') {
605         r->header_only = 1;
606     }
607
608     ap_parse_uri(r, uri);
609
610     /* ap_getline returns (size of max buffer - 1) if it fills up the
611      * buffer before finding the end-of-line.  This is only going to
612      * happen if it exceeds the configured limit for a request-line.
613      */
614     if (len > r->server->limit_req_line) {
615         r->status    = HTTP_REQUEST_URI_TOO_LARGE;
616         r->proto_num = HTTP_VERSION(1,0);
617         r->protocol  = apr_pstrdup(r->pool, "HTTP/1.0");
618         return 0;
619     }
620
621     if (ll[0]) {
622         r->assbackwards = 0;
623         pro = ll;
624         len = strlen(ll);
625     } else {
626         r->assbackwards = 1;
627         pro = "HTTP/0.9";
628         len = 8;
629     }
630     r->protocol = apr_pstrmemdup(r->pool, pro, len);
631
632     /* XXX ap_update_connection_status(conn->id, "Protocol", r->protocol); */
633
634     /* Avoid sscanf in the common case */
635     if (len == 8 &&
636         pro[0] == 'H' && pro[1] == 'T' && pro[2] == 'T' && pro[3] == 'P' &&
637         pro[4] == '/' && apr_isdigit(pro[5]) && pro[6] == '.' &&
638         apr_isdigit(pro[7])) {
639         r->proto_num = HTTP_VERSION(pro[5] - '0', pro[7] - '0');
640     } else if (2 == sscanf(r->protocol, "HTTP/%u.%u", &major, &minor)
641                && minor < HTTP_VERSION(1,0))    /* don't allow HTTP/0.1000 */
642         r->proto_num = HTTP_VERSION(major, minor);
643     else
644         r->proto_num = HTTP_VERSION(1,0);
645
646     return 1;
647 }
648
649 static void get_mime_headers(request_rec *r)
650 {
651     char* field;
652     char *value;
653     apr_size_t len;
654     int fields_read = 0;
655     apr_table_t *tmp_headers;
656
657     /* We'll use apr_table_overlap later to merge these into r->headers_in. */
658     tmp_headers = apr_table_make(r->pool, 50);
659
660     /*
661      * Read header lines until we get the empty separator line, a read error,
662      * the connection closes (EOF), reach the server limit, or we timeout.
663      */
664     while(1) {
665         apr_status_t rv;
666
667         field = NULL;
668         rv = ap_rgetline(&field, DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2,
669                          &len, r, 1);
670
671         /* ap_rgetline returns APR_ENOSPC if it fills up the buffer before 
672          * finding the end-of-line.  This is only going to happen if it 
673          * exceeds the configured limit for a field size.
674          */
675         if (rv == APR_ENOSPC || len > r->server->limit_req_fieldsize) {
676             r->status = HTTP_BAD_REQUEST;
677             apr_table_setn(r->notes, "error-notes",
678                 apr_pstrcat(r->pool,
679                             "Size of a request header field "
680                             "exceeds server limit.<br />\n"
681                             "<pre>\n",
682                             ap_escape_html(r->pool, field),
683                             "</pre>\n", NULL));
684             return;
685         }
686
687         if (rv != APR_SUCCESS) {
688             ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "get_mime_headers() failed");
689             return;
690         }
691
692         /* Found a blank line, stop. */
693         if (len == 0) {
694             break;
695         }
696
697         if (r->server->limit_req_fields &&
698             (++fields_read > r->server->limit_req_fields)) {
699             r->status = HTTP_BAD_REQUEST;
700             apr_table_setn(r->notes, "error-notes",
701                            "The number of request header fields exceeds "
702                            "this server's limit.");
703             return;
704         }
705
706         if (!(value = strchr(field, ':'))) {    /* Find the colon separator */
707             r->status = HTTP_BAD_REQUEST;       /* or abort the bad request */
708             apr_table_setn(r->notes, "error-notes",
709                            apr_pstrcat(r->pool,
710                                        "Request header field is missing "
711                                        "colon separator.<br />\n"
712                                        "<pre>\n",
713                                        ap_escape_html(r->pool, field),
714                                        "</pre>\n", NULL));
715             return;
716         }
717
718         *value = '\0';
719         ++value;
720         while (*value == ' ' || *value == '\t') {
721             ++value;            /* Skip to start of value   */
722         }
723
724         apr_table_addn(tmp_headers, field, value);
725     }
726
727     apr_table_overlap(r->headers_in, tmp_headers, APR_OVERLAP_TABLES_MERGE);
728 }
729
730 request_rec *ap_read_request(conn_rec *conn)
731 {
732     request_rec *r;
733     apr_pool_t *p;
734     const char *expect;
735     int access_status;
736
737     apr_pool_create(&p, conn->pool);
738     r = apr_pcalloc(p, sizeof(request_rec));
739     r->pool            = p;
740     r->connection      = conn;
741     r->server          = conn->base_server;
742
743     r->user            = NULL;
744     r->ap_auth_type    = NULL;
745
746     r->allowed_methods = ap_make_method_list(p, 2);
747
748     r->headers_in      = apr_table_make(r->pool, 25);
749     r->subprocess_env  = apr_table_make(r->pool, 25);
750     r->headers_out     = apr_table_make(r->pool, 12);
751     r->err_headers_out = apr_table_make(r->pool, 5);
752     r->notes           = apr_table_make(r->pool, 5);
753
754     r->request_config  = ap_create_request_config(r->pool);
755     /* Must be set before we run create request hook */
756     r->output_filters  = conn->output_filters;
757     r->input_filters   = conn->input_filters;
758     ap_run_create_request(r);
759     r->per_dir_config  = r->server->lookup_defaults;
760
761     r->sent_bodyct     = 0;                      /* bytect isn't for body */
762
763     r->read_length     = 0;
764     r->read_body       = REQUEST_NO_BODY;
765
766     r->status          = HTTP_REQUEST_TIME_OUT;  /* Until we get a request */
767     r->the_request     = NULL;
768
769     /* Get the request... */
770     if (!read_request_line(r)) {
771         if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
772             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
773                           "request failed: URI too long");
774             ap_send_error_response(r, 0);
775             ap_run_log_transaction(r);
776             return r;
777         }
778         return NULL;
779     }
780
781     if (!r->assbackwards) {
782         get_mime_headers(r);
783         if (r->status != HTTP_REQUEST_TIME_OUT) {
784             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
785                           "request failed: error reading the headers");
786             ap_send_error_response(r, 0);
787             ap_run_log_transaction(r);
788             return r;
789         }
790     }
791     else {
792         if (r->header_only) {
793             /*
794              * Client asked for headers only with HTTP/0.9, which doesn't send
795              * headers! Have to dink things just to make sure the error message
796              * comes through...
797              */
798             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
799                           "client sent invalid HTTP/0.9 request: HEAD %s",
800                           r->uri);
801             r->header_only = 0;
802             r->status = HTTP_BAD_REQUEST;
803             ap_send_error_response(r, 0);
804             ap_run_log_transaction(r);
805             return r;
806         }
807     }
808
809     r->status = HTTP_OK;                         /* Until further notice. */
810
811     /* update what we think the virtual host is based on the headers we've
812      * now read. may update status.
813      */
814     ap_update_vhost_from_headers(r);
815
816     /* we may have switched to another server */
817     r->per_dir_config = r->server->lookup_defaults;
818
819     if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1,1))) ||
820         ((r->proto_num == HTTP_VERSION(1,1)) &&
821          !apr_table_get(r->headers_in, "Host"))) {
822         /*
823          * Client sent us an HTTP/1.1 or later request without telling us the
824          * hostname, either with a full URL or a Host: header. We therefore
825          * need to (as per the 1.1 spec) send an error.  As a special case,
826          * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain
827          * a Host: header, and the server MUST respond with 400 if it doesn't.
828          */
829         r->status = HTTP_BAD_REQUEST;
830         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
831                       "client sent HTTP/1.1 request without hostname "
832                       "(see RFC2616 section 14.23): %s", r->uri);
833     }
834     if (r->status != HTTP_OK) {
835         ap_send_error_response(r, 0);
836         ap_run_log_transaction(r);
837         return r;
838     }
839     if (((expect = apr_table_get(r->headers_in, "Expect")) != NULL) &&
840         (expect[0] != '\0')) {
841         /*
842          * The Expect header field was added to HTTP/1.1 after RFC 2068
843          * as a means to signal when a 100 response is desired and,
844          * unfortunately, to signal a poor man's mandatory extension that
845          * the server must understand or return 417 Expectation Failed.
846          */
847         if (strcasecmp(expect, "100-continue") == 0) {
848             r->expecting_100 = 1;
849         }
850         else {
851             r->status = HTTP_EXPECTATION_FAILED;
852             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
853                           "client sent an unrecognized expectation value of "
854                           "Expect: %s", expect);
855             ap_send_error_response(r, 0);
856             (void) ap_discard_request_body(r);
857             ap_run_log_transaction(r);
858             return r;
859         }
860     }
861
862     ap_add_input_filter("HTTP_IN", NULL, r, r->connection);
863
864     if ((access_status = ap_run_post_read_request(r))) {
865         ap_die(access_status, r);
866         ap_run_log_transaction(r);
867         return NULL;
868     }
869
870     return r;
871 }
872
873 /*
874  * A couple of other functions which initialize some of the fields of
875  * a request structure, as appropriate for adjuncts of one kind or another
876  * to a request in progress.  Best here, rather than elsewhere, since
877  * *someone* has to set the protocol-specific fields...
878  */
879
880 void ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r)
881 {
882     rnew->the_request     = r->the_request;  /* Keep original request-line */
883
884     rnew->assbackwards    = 1;   /* Don't send headers from this. */
885     rnew->no_local_copy   = 1;   /* Don't try to send HTTP_NOT_MODIFIED for a
886                                   * fragment. */
887     rnew->method          = "GET";
888     rnew->method_number   = M_GET;
889     rnew->protocol        = "INCLUDED";
890
891     rnew->status          = HTTP_OK;
892
893     rnew->headers_in      = r->headers_in;
894     rnew->subprocess_env  = apr_table_copy(rnew->pool, r->subprocess_env);
895     rnew->headers_out     = apr_table_make(rnew->pool, 5);
896     rnew->err_headers_out = apr_table_make(rnew->pool, 5);
897     rnew->notes           = apr_table_make(rnew->pool, 5);
898
899     rnew->expecting_100   = r->expecting_100;
900     rnew->read_length     = r->read_length;
901     rnew->read_body       = REQUEST_NO_BODY;
902
903     rnew->main = (request_rec *) r;
904 }
905
906 static void end_output_stream(request_rec *r)
907 {
908     apr_bucket_brigade *bb;
909     apr_bucket *b;
910
911     bb = apr_brigade_create(r->pool);
912     b = apr_bucket_eos_create();
913     APR_BRIGADE_INSERT_TAIL(bb, b);
914     ap_pass_brigade(r->output_filters, bb);
915 }
916
917 void ap_finalize_sub_req_protocol(request_rec *sub)
918 {
919     end_output_stream(sub); 
920 }
921
922 /* finalize_request_protocol is called at completion of sending the
923  * response.  Its sole purpose is to send the terminating protocol
924  * information for any wrappers around the response message body
925  * (i.e., transfer encodings).  It should have been named finalize_response.
926  */
927 AP_DECLARE(void) ap_finalize_request_protocol(request_rec *r)
928 {
929     while (r->next) {
930         r = r->next;
931     }
932     /* tell the filter chain there is no more content coming */
933     if (!r->eos_sent) {
934         end_output_stream(r);
935     }
936
937
938 /*
939  * Support for the Basic authentication protocol, and a bit for Digest.
940  */
941
942 AP_DECLARE(void) ap_note_auth_failure(request_rec *r)
943 {
944     const char *type = ap_auth_type(r);
945     if (type) {
946         if (!strcasecmp(type, "Basic"))
947             ap_note_basic_auth_failure(r);
948         else if (!strcasecmp(type, "Digest"))
949             ap_note_digest_auth_failure(r);
950     }
951     else {
952         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
953                       0, r, "need AuthType to note auth failure: %s", r->uri);
954     }
955 }
956
957 AP_DECLARE(void) ap_note_basic_auth_failure(request_rec *r)
958 {
959     const char *type = ap_auth_type(r);
960     /* if there is no AuthType configure or it is something other than
961      * Basic, let ap_note_auth_failure() deal with it
962      */
963     if (!type || strcasecmp(type, "Basic"))
964         ap_note_auth_failure(r);
965     else
966         apr_table_setn(r->err_headers_out,
967                   (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" : "WWW-Authenticate",
968                   apr_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r), "\"",
969                           NULL));
970 }
971
972 AP_DECLARE(void) ap_note_digest_auth_failure(request_rec *r)
973 {
974     apr_table_setn(r->err_headers_out,
975             (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" : "WWW-Authenticate",
976             apr_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%llx\"",
977                 ap_auth_name(r), r->request_time));
978 }
979
980 AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
981 {
982     const char *auth_line = apr_table_get(r->headers_in,
983                                       (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization"
984                                                   : "Authorization");
985     const char *t;
986
987     if (!(t = ap_auth_type(r)) || strcasecmp(t, "Basic"))
988         return DECLINED;
989
990     if (!ap_auth_name(r)) {
991         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
992                       0, r, "need AuthName: %s", r->uri);
993         return HTTP_INTERNAL_SERVER_ERROR;
994     }
995
996     if (!auth_line) {
997         ap_note_basic_auth_failure(r);
998         return HTTP_UNAUTHORIZED;
999     }
1000
1001     if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) {
1002         /* Client tried to authenticate using wrong auth scheme */
1003         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
1004                       "client used wrong authentication scheme: %s", r->uri);
1005         ap_note_basic_auth_failure(r);
1006         return HTTP_UNAUTHORIZED;
1007     }
1008
1009     while (*auth_line== ' ' || *auth_line== '\t') {
1010         auth_line++;
1011     }
1012
1013     t = ap_pbase64decode(r->pool, auth_line);
1014     /* Note that this allocation has to be made from r->connection->pool
1015      * because it has the lifetime of the connection.  The other allocations
1016      * are temporary and can be tossed away any time.
1017      */
1018     r->user = ap_getword_nulls (r->pool, &t, ':');
1019     r->ap_auth_type = "Basic";
1020
1021     *pw = t;
1022
1023     return OK;
1024 }
1025
1026 struct content_length_ctx {
1027     apr_bucket_brigade *saved;
1028     int compute_len;
1029     apr_size_t curr_len;
1030 };
1031
1032 /* This filter computes the content length, but it also computes the number
1033  * of bytes sent to the client.  This means that this filter will always run
1034  * through all of the buckets in all brigades 
1035  */
1036 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter(ap_filter_t *f,
1037                                                               apr_bucket_brigade *b)
1038 {
1039     request_rec *r = f->r;
1040     struct content_length_ctx *ctx;
1041     apr_status_t rv;
1042     apr_bucket *e;
1043     int eos = 0, flush = 0, partial_send_okay = 0;
1044     apr_bucket_brigade *more, *split;
1045     apr_read_type_e eblock = APR_NONBLOCK_READ;
1046
1047     ctx = f->ctx;
1048     if (!ctx) { /* first time through */
1049         f->ctx = ctx = apr_pcalloc(r->pool, sizeof(struct content_length_ctx));
1050         ctx->compute_len = 1;   /* Assume we will compute the length */
1051     }
1052
1053     /* Humm, is this check the best it can be? 
1054      * - protocol >= HTTP/1.1 implies support for chunking 
1055      * - non-keepalive implies the end of byte stream will be signaled
1056      *    by a connection close
1057      * In both cases, we can send bytes to the client w/o needing to
1058      * compute content-length. 
1059      * Todo: 
1060      * We should be able to force connection close from this filter
1061      * when we see we are buffering too much. 
1062      */
1063     if ((r->proto_num >= HTTP_VERSION(1,1)) ||
1064         (!f->r->connection->keepalive)) {
1065         partial_send_okay = 1;
1066     }
1067
1068     more = b;
1069     while (more) {
1070         b = more;
1071         more = NULL;
1072         split = NULL;
1073         flush = 0;
1074
1075         APR_BRIGADE_FOREACH(e, b) {
1076             const char *ignored;
1077             apr_size_t len;
1078             len = 0;
1079             if (APR_BUCKET_IS_EOS(e)) {
1080                 eos = 1;
1081             }
1082             else if (APR_BUCKET_IS_FLUSH(e)) {
1083                 if (partial_send_okay) {
1084                     split = b;
1085                     more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
1086                     break;
1087                 }
1088             }
1089             else if ((ctx->curr_len > 4*AP_MIN_BYTES_TO_WRITE)) {
1090                 /* If we've accumulated more than 4xAP_MIN_BYTES_TO_WRITE and 
1091                  * the client supports chunked encoding, send what we have 
1092                  * and come back for more.
1093                  */
1094                 if (partial_send_okay) {
1095                     split = b;
1096                     more = apr_brigade_split(b, e);
1097                     break;
1098                 }
1099             }
1100             if (e->length == -1) { /* if length unknown */
1101                 rv = apr_bucket_read(e, &ignored, &len, eblock);
1102                 if (rv == APR_SUCCESS) {
1103                     /* Attempt a nonblocking read next time through */
1104                     eblock = APR_NONBLOCK_READ;
1105                 }
1106                 else if (APR_STATUS_IS_EAGAIN(rv)) {
1107                     /* Make the next read blocking.  If the client supports chunked
1108                      * encoding, flush the filter stack to the network.
1109                      */
1110                     eblock = APR_BLOCK_READ;
1111                     if (partial_send_okay) {
1112                         split = b;
1113                         more = apr_brigade_split(b, e);
1114                         flush = 1;
1115                         break;
1116                     }
1117                 }
1118                 else if (rv != APR_EOF) {
1119                     ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, 
1120                         "ap_content_length_filter: apr_bucket_read() failed");
1121                     return rv;
1122                 }
1123             }
1124             else {
1125                 len = e->length;
1126             }
1127             ctx->curr_len += len;
1128             r->bytes_sent += len;
1129         }
1130
1131         if (split) {
1132             ctx->compute_len = 0;  /* Ooops, can't compute the length now */
1133             ctx->curr_len = 0;
1134             if (ctx->saved) {
1135                 APR_BRIGADE_CONCAT(ctx->saved, split);
1136                 apr_brigade_destroy(split);
1137                 split = ctx->saved;
1138                 ctx->saved = NULL;
1139             }
1140             if (flush) {
1141                 rv = ap_fflush(f->next, split);
1142             }
1143             else {
1144                 rv = ap_pass_brigade(f->next, split);
1145             }
1146             if (rv != APR_SUCCESS)
1147                 return rv;
1148         }
1149     }
1150
1151     if ((ctx->curr_len < AP_MIN_BYTES_TO_WRITE) && !eos) {
1152         return ap_save_brigade(f, &ctx->saved, &b, (r->main) ? r->main->pool : r->pool);
1153     }
1154
1155     if (ctx->compute_len) {
1156         /* save the brigade; we can't pass any data to the next
1157          * filter until we have the entire content length
1158          */
1159         if (!eos) {
1160             return ap_save_brigade(f, &ctx->saved, &b, r->pool);
1161         }
1162         ap_set_content_length(r, r->bytes_sent);
1163     }
1164     if (ctx->saved) {
1165         APR_BRIGADE_CONCAT(ctx->saved, b);
1166         apr_brigade_destroy(b);
1167         b = ctx->saved;
1168         ctx->saved = NULL;
1169     }
1170
1171     ctx->curr_len = 0;
1172     return ap_pass_brigade(f->next, b);
1173 }
1174
1175 /*
1176  * Send the body of a response to the client.
1177  */
1178 AP_DECLARE(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r, apr_off_t offset, 
1179                                     apr_size_t len, apr_size_t *nbytes) 
1180 {
1181     apr_bucket_brigade *bb = NULL;
1182     apr_bucket *b;
1183     apr_status_t rv;
1184
1185     bb = apr_brigade_create(r->pool);
1186     b = apr_bucket_file_create(fd, offset, len, r->pool);
1187     APR_BRIGADE_INSERT_TAIL(bb, b);
1188
1189     rv = ap_pass_brigade(r->output_filters, bb);
1190     if (rv != APR_SUCCESS) {
1191         *nbytes = 0; /* no way to tell how many were actually sent */
1192     }
1193     else {
1194         *nbytes = len;
1195     }
1196
1197     return rv;
1198 }
1199
1200 #if APR_HAS_MMAP
1201 /* send data from an in-memory buffer */
1202 AP_DECLARE(size_t) ap_send_mmap(apr_mmap_t *mm, request_rec *r, size_t offset,
1203                              size_t length)
1204 {
1205     apr_bucket_brigade *bb = NULL;
1206     apr_bucket *b;
1207
1208     bb = apr_brigade_create(r->pool);
1209     b = apr_bucket_mmap_create(mm, offset, length);
1210     APR_BRIGADE_INSERT_TAIL(bb, b);
1211     ap_pass_brigade(r->output_filters, bb);
1212
1213     return mm->size; /* XXX - change API to report apr_status_t? */
1214 }
1215 #endif /* APR_HAS_MMAP */
1216
1217 typedef struct {
1218     apr_bucket_brigade *bb;
1219 } old_write_filter_ctx;
1220
1221 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter(
1222     ap_filter_t *f, apr_bucket_brigade *bb)
1223 {
1224     old_write_filter_ctx *ctx = f->ctx;
1225
1226     AP_DEBUG_ASSERT(ctx);
1227
1228     if (ctx->bb != 0) {
1229         /* whatever is coming down the pipe (we don't care), we
1230          * can simply insert our buffered data at the front and
1231          * pass the whole bundle down the chain. 
1232          */
1233         APR_BRIGADE_CONCAT(ctx->bb, bb);
1234     }
1235
1236     return ap_pass_brigade(f->next, ctx->bb);
1237 }
1238
1239 static apr_status_t buffer_output(request_rec *r,
1240                                   const char *str, apr_size_t len)
1241 {
1242     ap_filter_t *f;
1243     old_write_filter_ctx *ctx;
1244
1245     if (len == 0)
1246         return APR_SUCCESS;
1247
1248     /* future optimization: record some flags in the request_rec to
1249      * say whether we've added our filter, and whether it is first.
1250      */
1251
1252     /* this will typically exit on the first test */
1253     for (f = r->output_filters; f != NULL; f = f->next)
1254         if (ap_old_write_func == f->frec)
1255             break;
1256     if (f == NULL) {
1257         /* our filter hasn't been added yet */
1258         ctx = apr_pcalloc(r->pool, sizeof(*ctx));
1259         ap_add_output_filter("OLD_WRITE", ctx, r, r->connection);
1260         f = r->output_filters;
1261     }
1262
1263     /* if the first filter is not our buffering filter, then we have to
1264      * deliver the content through the normal filter chain */
1265     if (f != r->output_filters) {
1266         apr_bucket_brigade *bb = apr_brigade_create(r->pool);
1267         apr_bucket *b = apr_bucket_transient_create(str, len);
1268         APR_BRIGADE_INSERT_TAIL(bb, b);
1269
1270         return ap_pass_brigade(r->output_filters, bb);
1271     }
1272
1273     /* grab the context from our filter */
1274     ctx = r->output_filters->ctx;
1275
1276     if (ctx->bb == NULL) {
1277         ctx->bb = apr_brigade_create(r->pool);
1278     }
1279
1280     return ap_fwrite(f->next, ctx->bb, str, len);
1281 }
1282
1283 AP_DECLARE(int) ap_rputc(int c, request_rec *r)
1284 {
1285     char c2 = (char)c;
1286
1287     if (r->connection->aborted) {
1288         return -1;
1289     }
1290
1291     if (buffer_output(r, &c2, 1) != APR_SUCCESS)
1292         return -1;
1293
1294     return c;
1295 }
1296
1297 AP_DECLARE(int) ap_rputs(const char *str, request_rec *r)
1298 {
1299     apr_size_t len;
1300
1301     if (r->connection->aborted)
1302         return -1;
1303
1304     if (buffer_output(r, str, len = strlen(str)) != APR_SUCCESS)
1305         return -1;
1306
1307     return len;
1308 }
1309
1310 AP_DECLARE(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
1311 {
1312     if (r->connection->aborted)
1313         return -1;
1314
1315     if (buffer_output(r, buf, nbyte) != APR_SUCCESS)
1316         return -1;
1317
1318     return nbyte;
1319 }
1320
1321 struct ap_vrprintf_data {
1322     apr_vformatter_buff_t vbuff;
1323     request_rec *r;
1324     char *buff;
1325 };
1326
1327 static apr_status_t r_flush(apr_vformatter_buff_t *buff)
1328 {
1329     /* callback function passed to ap_vformatter to be called when
1330      * vformatter needs to write into buff and buff.curpos > buff.endpos */
1331
1332     /* ap_vrprintf_data passed as a apr_vformatter_buff_t, which is then
1333      * "downcast" to an ap_vrprintf_data */
1334     struct ap_vrprintf_data *vd = (struct ap_vrprintf_data*)buff;
1335
1336     if (vd->r->connection->aborted)
1337         return -1;
1338
1339     /* r_flush is called when vbuff is completely full */
1340     if (buffer_output(vd->r, vd->buff, AP_IOBUFSIZE)) {
1341         return -1;
1342     }
1343
1344     /* reset the buffer position */
1345     vd->vbuff.curpos = vd->buff;
1346     vd->vbuff.endpos = vd->buff + AP_IOBUFSIZE;
1347
1348     return APR_SUCCESS;
1349 }
1350
1351 AP_DECLARE(int) ap_vrprintf(request_rec *r, const char *fmt, va_list va)
1352 {
1353     apr_size_t written;
1354     struct ap_vrprintf_data vd;
1355     char vrprintf_buf[AP_IOBUFSIZE];
1356
1357     vd.vbuff.curpos = vrprintf_buf;
1358     vd.vbuff.endpos = vrprintf_buf + AP_IOBUFSIZE;
1359     vd.r = r;
1360     vd.buff = vrprintf_buf;
1361
1362     if (r->connection->aborted)
1363         return -1;
1364
1365     written = apr_vformatter(r_flush, &vd.vbuff, fmt, va);
1366     /* tack on null terminator on remaining string */
1367     *(vd.vbuff.curpos) = '\0';
1368
1369     if (written != -1) {
1370         int n = vd.vbuff.curpos - vrprintf_buf;
1371
1372         /* last call to buffer_output, to finish clearing the buffer */
1373         if (buffer_output(r, vrprintf_buf,n) != APR_SUCCESS)
1374             return -1;
1375
1376         written += n;
1377     }
1378
1379     return written;
1380 }
1381
1382 AP_DECLARE_NONSTD(int) ap_rprintf(request_rec *r, const char *fmt, ...)
1383 {
1384     va_list va;
1385     int n;
1386
1387     if (r->connection->aborted)
1388         return -1;
1389
1390     va_start(va, fmt);
1391     n = ap_vrprintf(r, fmt, va);
1392     va_end(va);
1393
1394     return n;
1395 }
1396
1397 AP_DECLARE_NONSTD(int) ap_rvputs(request_rec *r, ...)
1398 {
1399     va_list va;
1400     const char *s;
1401     apr_size_t len;
1402     apr_size_t written = 0;
1403
1404     if (r->connection->aborted)
1405         return -1;
1406
1407     /* ### TODO: if the total output is large, put all the strings
1408        ### into a single brigade, rather than flushing each time we
1409        ### fill the buffer */
1410     va_start(va, r);
1411     while (1) {
1412         s = va_arg(va, const char *);
1413         if (s == NULL)
1414             break;
1415
1416         len = strlen(s);
1417         if (buffer_output(r, s, len) != APR_SUCCESS) {
1418             return -1;
1419         }
1420
1421         written += len;
1422     }
1423     va_end(va);
1424
1425     return written;
1426 }
1427
1428 AP_DECLARE(int) ap_rflush(request_rec *r)
1429 {
1430     apr_bucket_brigade *bb;
1431     apr_bucket *b;
1432
1433     bb = apr_brigade_create(r->pool);
1434     b = apr_bucket_flush_create();
1435     APR_BRIGADE_INSERT_TAIL(bb, b);
1436     if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS)
1437         return -1;
1438     return 0;
1439 }
1440
1441 /*
1442  * This function sets the Last-Modified output header field to the value
1443  * of the mtime field in the request structure - rationalized to keep it from
1444  * being in the future.
1445  */
1446 AP_DECLARE(void) ap_set_last_modified(request_rec *r)
1447 {
1448     if (!r->assbackwards) {
1449         apr_time_t mod_time = ap_rationalize_mtime(r, r->mtime);
1450         char *datestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
1451         apr_rfc822_date(datestr, mod_time);
1452         apr_table_setn(r->headers_out, "Last-Modified", datestr);
1453     }
1454 }
1455
1456 AP_IMPLEMENT_HOOK_RUN_ALL(int,post_read_request,
1457                           (request_rec *r),(r),OK,DECLINED)
1458 AP_IMPLEMENT_HOOK_RUN_ALL(int,log_transaction,
1459                           (request_rec *r),(r),OK,DECLINED)
1460 AP_IMPLEMENT_HOOK_RUN_FIRST(const char *,http_method,
1461                             (const request_rec *r),(r),NULL)
1462 AP_IMPLEMENT_HOOK_RUN_FIRST(unsigned short,default_port,
1463                             (const request_rec *r),(r),0)