]> granicus.if.org Git - apache/blob - modules/http/http_filters.c
No functional Change: Removing trailing whitespace. This also
[apache] / modules / http / http_filters.c
1 /* Copyright 1999-2005 The Apache Software Foundation or its licensors, as
2  * applicable.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * http_filter.c --- HTTP routines which either filters or deal with filters.
19  */
20
21 #include "apr.h"
22 #include "apr_strings.h"
23 #include "apr_buckets.h"
24 #include "apr_lib.h"
25 #include "apr_signal.h"
26
27 #define APR_WANT_STDIO          /* for sscanf */
28 #define APR_WANT_STRFUNC
29 #define APR_WANT_MEMFUNC
30 #include "apr_want.h"
31
32 #define CORE_PRIVATE
33 #include "util_filter.h"
34 #include "ap_config.h"
35 #include "httpd.h"
36 #include "http_config.h"
37 #include "http_core.h"
38 #include "http_protocol.h"
39 #include "http_main.h"
40 #include "http_request.h"
41 #include "http_vhost.h"
42 #include "http_log.h"           /* For errors detected in basic auth common
43                                  * support code... */
44 #include "apr_date.h"           /* For apr_date_parse_http and APR_DATE_BAD */
45 #include "util_charset.h"
46 #include "util_ebcdic.h"
47 #include "util_time.h"
48
49 #include "mod_core.h"
50
51 #if APR_HAVE_STDARG_H
52 #include <stdarg.h>
53 #endif
54 #if APR_HAVE_UNISTD_H
55 #include <unistd.h>
56 #endif
57
58 static long get_chunk_size(char *);
59
60 typedef struct http_filter_ctx {
61     apr_off_t remaining;
62     apr_off_t limit;
63     apr_off_t limit_used;
64     enum {
65         BODY_NONE,
66         BODY_LENGTH,
67         BODY_CHUNK
68     } state;
69     int eos_sent;
70 } http_ctx_t;
71
72 /* This is the HTTP_INPUT filter for HTTP requests and responses from
73  * proxied servers (mod_proxy).  It handles chunked and content-length
74  * bodies.  This can only be inserted/used after the headers
75  * are successfully parsed.
76  */
77 apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
78                             ap_input_mode_t mode, apr_read_type_e block,
79                             apr_off_t readbytes)
80 {
81     apr_bucket *e;
82     http_ctx_t *ctx = f->ctx;
83     apr_status_t rv;
84     apr_off_t totalread;
85
86     /* just get out of the way of things we don't want. */
87     if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) {
88         return ap_get_brigade(f->next, b, mode, block, readbytes);
89     }
90
91     if (!ctx) {
92         const char *tenc, *lenp;
93         f->ctx = ctx = apr_palloc(f->r->pool, sizeof(*ctx));
94         ctx->state = BODY_NONE;
95         ctx->remaining = 0;
96         ctx->limit_used = 0;
97         ctx->eos_sent = 0;
98
99         /* LimitRequestBody does not apply to proxied responses.
100          * Consider implementing this check in its own filter.
101          * Would adding a directive to limit the size of proxied
102          * responses be useful?
103          */
104         if (!f->r->proxyreq) {
105             ctx->limit = ap_get_limit_req_body(f->r);
106         }
107         else {
108             ctx->limit = 0;
109         }
110
111         tenc = apr_table_get(f->r->headers_in, "Transfer-Encoding");
112         lenp = apr_table_get(f->r->headers_in, "Content-Length");
113
114         if (tenc) {
115             if (!strcasecmp(tenc, "chunked")) {
116                 ctx->state = BODY_CHUNK;
117             }
118         }
119         else if (lenp) {
120             char *endstr;
121
122             ctx->state = BODY_LENGTH;
123             errno = 0;
124
125             /* Protects against over/underflow, non-digit chars in the
126              * string (excluding leading space) (the endstr checks)
127              * and a negative number. */
128             if (apr_strtoff(&ctx->remaining, lenp, &endstr, 10)
129                 || endstr == lenp || *endstr || ctx->remaining < 0) {
130                 apr_bucket_brigade *bb;
131
132                 ctx->remaining = 0;
133                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,
134                               "Invalid Content-Length");
135
136                 bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
137                 e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,
138                                            f->r->pool, f->c->bucket_alloc);
139                 APR_BRIGADE_INSERT_TAIL(bb, e);
140                 e = apr_bucket_eos_create(f->c->bucket_alloc);
141                 APR_BRIGADE_INSERT_TAIL(bb, e);
142                 ctx->eos_sent = 1;
143                 return ap_pass_brigade(f->r->output_filters, bb);
144             }
145
146             /* If we have a limit in effect and we know the C-L ahead of
147              * time, stop it here if it is invalid.
148              */
149             if (ctx->limit && ctx->limit < ctx->remaining) {
150                 apr_bucket_brigade *bb;
151                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,
152                           "Requested content-length of %" APR_OFF_T_FMT
153                           " is larger than the configured limit"
154                           " of %" APR_OFF_T_FMT, ctx->remaining, ctx->limit);
155                 bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
156                 e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,
157                                            f->r->pool, f->c->bucket_alloc);
158                 APR_BRIGADE_INSERT_TAIL(bb, e);
159                 e = apr_bucket_eos_create(f->c->bucket_alloc);
160                 APR_BRIGADE_INSERT_TAIL(bb, e);
161                 ctx->eos_sent = 1;
162                 return ap_pass_brigade(f->r->output_filters, bb);
163             }
164         }
165
166         /* If we don't have a request entity indicated by the headers, EOS.
167          * (BODY_NONE is a valid intermediate state due to trailers,
168          *  but it isn't a valid starting state.)
169          *
170          * RFC 2616 Section 4.4 note 5 states that connection-close
171          * is invalid for a request entity - request bodies must be
172          * denoted by C-L or T-E: chunked.
173          *
174          * Note that since the proxy uses this filter to handle the
175          * proxied *response*, proxy responses MUST be exempt.
176          */
177         if (ctx->state == BODY_NONE && f->r->proxyreq != PROXYREQ_RESPONSE) {
178             e = apr_bucket_eos_create(f->c->bucket_alloc);
179             APR_BRIGADE_INSERT_TAIL(b, e);
180             ctx->eos_sent = 1;
181             return APR_SUCCESS;
182         }
183
184         /* Since we're about to read data, send 100-Continue if needed.
185          * Only valid on chunked and C-L bodies where the C-L is > 0. */
186         if ((ctx->state == BODY_CHUNK ||
187             (ctx->state == BODY_LENGTH && ctx->remaining > 0)) &&
188             f->r->expecting_100 && f->r->proto_num >= HTTP_VERSION(1,1)) {
189             char *tmp;
190             apr_bucket_brigade *bb;
191
192             tmp = apr_pstrcat(f->r->pool, AP_SERVER_PROTOCOL, " ",
193                               ap_get_status_line(100), CRLF CRLF, NULL);
194             bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
195             e = apr_bucket_pool_create(tmp, strlen(tmp), f->r->pool,
196                                        f->c->bucket_alloc);
197             APR_BRIGADE_INSERT_HEAD(bb, e);
198             e = apr_bucket_flush_create(f->c->bucket_alloc);
199             APR_BRIGADE_INSERT_TAIL(bb, e);
200
201             ap_pass_brigade(f->c->output_filters, bb);
202         }
203
204         /* We can't read the chunk until after sending 100 if required. */
205         if (ctx->state == BODY_CHUNK) {
206             char line[30];
207             apr_bucket_brigade *bb;
208             apr_size_t len = 30;
209             apr_off_t brigade_length;
210
211             bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
212
213             rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
214                                 APR_BLOCK_READ, 0);
215
216             if (rv == APR_SUCCESS) {
217                 /* We have to check the length of the brigade we got back.
218                  * We will not accept partial lines.
219                  */
220                 rv = apr_brigade_length(bb, 1, &brigade_length);
221                 if (rv == APR_SUCCESS
222                     && brigade_length > f->r->server->limit_req_line) {
223                     rv = APR_ENOSPC;
224                 }
225                 if (rv == APR_SUCCESS) {
226                     rv = apr_brigade_flatten(bb, line, &len);
227                     if (rv == APR_SUCCESS) {
228                         ctx->remaining = get_chunk_size(line);
229                     }
230                 }
231             }
232             apr_brigade_cleanup(bb);
233
234             /* Detect chunksize error (such as overflow) */
235             if (rv != APR_SUCCESS || ctx->remaining < 0) {
236                 ctx->remaining = 0; /* Reset it in case we have to
237                                      * come back here later */
238                 e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,
239                                            f->r->pool,
240                                            f->c->bucket_alloc);
241                 APR_BRIGADE_INSERT_TAIL(bb, e);
242                 e = apr_bucket_eos_create(f->c->bucket_alloc);
243                 APR_BRIGADE_INSERT_TAIL(bb, e);
244                 ctx->eos_sent = 1;
245                 return ap_pass_brigade(f->r->output_filters, bb);
246             }
247
248             if (!ctx->remaining) {
249                 /* Handle trailers by calling ap_get_mime_headers again! */
250                 ctx->state = BODY_NONE;
251                 ap_get_mime_headers(f->r);
252                 e = apr_bucket_eos_create(f->c->bucket_alloc);
253                 APR_BRIGADE_INSERT_TAIL(b, e);
254                 ctx->eos_sent = 1;
255                 return APR_SUCCESS;
256             }
257         }
258     }
259
260     if (ctx->eos_sent) {
261         e = apr_bucket_eos_create(f->c->bucket_alloc);
262         APR_BRIGADE_INSERT_TAIL(b, e);
263         return APR_SUCCESS;
264     }
265
266     if (!ctx->remaining) {
267         switch (ctx->state) {
268         case BODY_NONE:
269             break;
270         case BODY_LENGTH:
271             e = apr_bucket_eos_create(f->c->bucket_alloc);
272             APR_BRIGADE_INSERT_TAIL(b, e);
273             ctx->eos_sent = 1;
274             return APR_SUCCESS;
275         case BODY_CHUNK:
276             {
277                 char line[30];
278                 apr_bucket_brigade *bb;
279                 apr_size_t len = 30;
280
281                 bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
282
283                 /* We need to read the CRLF after the chunk.  */
284                 rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
285                                     APR_BLOCK_READ, 0);
286                 apr_brigade_cleanup(bb);
287
288                 if (rv == APR_SUCCESS) {
289                     /* Read the real chunk line. */
290                     rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
291                                         APR_BLOCK_READ, 0);
292                     if (rv == APR_SUCCESS) {
293                         rv = apr_brigade_flatten(bb, line, &len);
294                         if (rv == APR_SUCCESS) {
295                             ctx->remaining = get_chunk_size(line);
296                         }
297                     }
298                     apr_brigade_cleanup(bb);
299                 }
300
301                 /* Detect chunksize error (such as overflow) */
302                 if (rv != APR_SUCCESS || ctx->remaining < 0) {
303                     ctx->remaining = 0; /* Reset it in case we have to
304                                          * come back here later */
305                     e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE,
306                                                NULL, f->r->pool,
307                                                f->c->bucket_alloc);
308                     APR_BRIGADE_INSERT_TAIL(bb, e);
309                     e = apr_bucket_eos_create(f->c->bucket_alloc);
310                     APR_BRIGADE_INSERT_TAIL(bb, e);
311                     ctx->eos_sent = 1;
312                     return ap_pass_brigade(f->r->output_filters, bb);
313                 }
314
315                 if (!ctx->remaining) {
316                     /* Handle trailers by calling ap_get_mime_headers again! */
317                     ctx->state = BODY_NONE;
318                     ap_get_mime_headers(f->r);
319                     e = apr_bucket_eos_create(f->c->bucket_alloc);
320                     APR_BRIGADE_INSERT_TAIL(b, e);
321                     ctx->eos_sent = 1;
322                     return APR_SUCCESS;
323                 }
324             }
325             break;
326         }
327     }
328
329     /* Ensure that the caller can not go over our boundary point. */
330     if (ctx->state == BODY_LENGTH || ctx->state == BODY_CHUNK) {
331         if (ctx->remaining < readbytes) {
332             readbytes = ctx->remaining;
333         }
334         AP_DEBUG_ASSERT(readbytes > 0);
335     }
336
337     rv = ap_get_brigade(f->next, b, mode, block, readbytes);
338
339     if (rv != APR_SUCCESS) {
340         return rv;
341     }
342
343     /* How many bytes did we just read? */
344     apr_brigade_length(b, 0, &totalread);
345
346     /* If this happens, we have a bucket of unknown length.  Die because
347      * it means our assumptions have changed. */
348     AP_DEBUG_ASSERT(totalread >= 0);
349
350     if (ctx->state != BODY_NONE) {
351         ctx->remaining -= totalread;
352     }
353
354     /* If we have no more bytes remaining on a C-L request,
355      * save the callter a roundtrip to discover EOS.
356      */
357     if (ctx->state == BODY_LENGTH && ctx->remaining == 0) {
358         e = apr_bucket_eos_create(f->c->bucket_alloc);
359         APR_BRIGADE_INSERT_TAIL(b, e);
360     }
361
362     /* We have a limit in effect. */
363     if (ctx->limit) {
364         /* FIXME: Note that we might get slightly confused on chunked inputs
365          * as we'd need to compensate for the chunk lengths which may not
366          * really count.  This seems to be up for interpretation.  */
367         ctx->limit_used += totalread;
368         if (ctx->limit < ctx->limit_used) {
369             apr_bucket_brigade *bb;
370             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,
371                           "Read content-length of %" APR_OFF_T_FMT
372                           " is larger than the configured limit"
373                           " of %" APR_OFF_T_FMT, ctx->limit_used, ctx->limit);
374             bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
375             e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,
376                                        f->r->pool,
377                                        f->c->bucket_alloc);
378             APR_BRIGADE_INSERT_TAIL(bb, e);
379             e = apr_bucket_eos_create(f->c->bucket_alloc);
380             APR_BRIGADE_INSERT_TAIL(bb, e);
381             ctx->eos_sent = 1;
382             return ap_pass_brigade(f->r->output_filters, bb);
383         }
384     }
385
386     return APR_SUCCESS;
387 }
388
389 /**
390  * Parse a chunk extension, detect overflow.
391  * There are two error cases:
392  *  1) If the conversion would require too many bits, a -1 is returned.
393  *  2) If the conversion used the correct number of bits, but an overflow
394  *     caused only the sign bit to flip, then that negative number is
395  *     returned.
396  * In general, any negative number can be considered an overflow error.
397  */
398 static long get_chunk_size(char *b)
399 {
400     long chunksize = 0;
401     size_t chunkbits = sizeof(long) * 8;
402
403     ap_xlate_proto_from_ascii(b, strlen(b));
404
405     /* Skip leading zeros */
406     while (*b == '0') {
407         ++b;
408     }
409
410     while (apr_isxdigit(*b) && (chunkbits > 0)) {
411         int xvalue = 0;
412
413         if (*b >= '0' && *b <= '9') {
414             xvalue = *b - '0';
415         }
416         else if (*b >= 'A' && *b <= 'F') {
417             xvalue = *b - 'A' + 0xa;
418         }
419         else if (*b >= 'a' && *b <= 'f') {
420             xvalue = *b - 'a' + 0xa;
421         }
422
423         chunksize = (chunksize << 4) | xvalue;
424         chunkbits -= 4;
425         ++b;
426     }
427     if (apr_isxdigit(*b) && (chunkbits <= 0)) {
428         /* overflow */
429         return -1;
430     }
431
432     return chunksize;
433 }
434
435 typedef struct header_struct {
436     apr_pool_t *pool;
437     apr_bucket_brigade *bb;
438 } header_struct;
439
440 /* Send a single HTTP header field to the client.  Note that this function
441  * is used in calls to table_do(), so their interfaces are co-dependent.
442  * In other words, don't change this one without checking table_do in alloc.c.
443  * It returns true unless there was a write error of some kind.
444  */
445 static int form_header_field(header_struct *h,
446                              const char *fieldname, const char *fieldval)
447 {
448 #if APR_CHARSET_EBCDIC
449     char *headfield;
450     apr_size_t len;
451     apr_size_t name_len;
452     apr_size_t val_len;
453     char *next;
454
455     name_len = strlen(fieldname);
456     val_len = strlen(fieldval);
457     len = name_len + val_len + 4; /* 4 for ": " plus CRLF */
458     headfield = (char *)apr_palloc(h->pool, len + 1);
459     memcpy(headfield, fieldname, name_len);
460     next = headfield + name_len;
461     *next++ = ':';
462     *next++ = ' ';
463     memcpy(next, fieldval, val_len);
464     next += val_len;
465     *next++ = CR;
466     *next++ = LF;
467     *next = 0;
468     ap_xlate_proto_to_ascii(headfield, len);
469     apr_brigade_write(h->bb, NULL, NULL, headfield, len);
470 #else
471     struct iovec vec[4];
472     struct iovec *v = vec;
473     v->iov_base = (void *)fieldname;
474     v->iov_len = strlen(fieldname);
475     v++;
476     v->iov_base = ": ";
477     v->iov_len = sizeof(": ") - 1;
478     v++;
479     v->iov_base = (void *)fieldval;
480     v->iov_len = strlen(fieldval);
481     v++;
482     v->iov_base = CRLF;
483     v->iov_len = sizeof(CRLF) - 1;
484     apr_brigade_writev(h->bb, NULL, NULL, vec, 4);
485 #endif /* !APR_CHARSET_EBCDIC */
486     return 1;
487 }
488
489 /* This routine is called by apr_table_do and merges all instances of
490  * the passed field values into a single array that will be further
491  * processed by some later routine.  Originally intended to help split
492  * and recombine multiple Vary fields, though it is generic to any field
493  * consisting of comma/space-separated tokens.
494  */
495 static int uniq_field_values(void *d, const char *key, const char *val)
496 {
497     apr_array_header_t *values;
498     char *start;
499     char *e;
500     char **strpp;
501     int  i;
502
503     values = (apr_array_header_t *)d;
504
505     e = apr_pstrdup(values->pool, val);
506
507     do {
508         /* Find a non-empty fieldname */
509
510         while (*e == ',' || apr_isspace(*e)) {
511             ++e;
512         }
513         if (*e == '\0') {
514             break;
515         }
516         start = e;
517         while (*e != '\0' && *e != ',' && !apr_isspace(*e)) {
518             ++e;
519         }
520         if (*e != '\0') {
521             *e++ = '\0';
522         }
523
524         /* Now add it to values if it isn't already represented.
525          * Could be replaced by a ap_array_strcasecmp() if we had one.
526          */
527         for (i = 0, strpp = (char **) values->elts; i < values->nelts;
528              ++i, ++strpp) {
529             if (*strpp && strcasecmp(*strpp, start) == 0) {
530                 break;
531             }
532         }
533         if (i == values->nelts) {  /* if not found */
534             *(char **)apr_array_push(values) = start;
535         }
536     } while (*e != '\0');
537
538     return 1;
539 }
540
541 /*
542  * Since some clients choke violently on multiple Vary fields, or
543  * Vary fields with duplicate tokens, combine any multiples and remove
544  * any duplicates.
545  */
546 static void fixup_vary(request_rec *r)
547 {
548     apr_array_header_t *varies;
549
550     varies = apr_array_make(r->pool, 5, sizeof(char *));
551
552     /* Extract all Vary fields from the headers_out, separate each into
553      * its comma-separated fieldname values, and then add them to varies
554      * if not already present in the array.
555      */
556     apr_table_do((int (*)(void *, const char *, const char *))uniq_field_values,
557                  (void *) varies, r->headers_out, "Vary", NULL);
558
559     /* If we found any, replace old Vary fields with unique-ified value */
560
561     if (varies->nelts > 0) {
562         apr_table_setn(r->headers_out, "Vary",
563                        apr_array_pstrcat(r->pool, varies, ','));
564     }
565 }
566
567 /* Send a request's HTTP response headers to the client.
568  */
569 static apr_status_t send_all_header_fields(header_struct *h,
570                                            const request_rec *r)
571 {
572     const apr_array_header_t *elts;
573     const apr_table_entry_t *t_elt;
574     const apr_table_entry_t *t_end;
575     struct iovec *vec;
576     struct iovec *vec_next;
577
578     elts = apr_table_elts(r->headers_out);
579     if (elts->nelts == 0) {
580         return APR_SUCCESS;
581     }
582     t_elt = (const apr_table_entry_t *)(elts->elts);
583     t_end = t_elt + elts->nelts;
584     vec = (struct iovec *)apr_palloc(h->pool, 4 * elts->nelts *
585                                      sizeof(struct iovec));
586     vec_next = vec;
587
588     /* For each field, generate
589      *    name ": " value CRLF
590      */
591     do {
592         vec_next->iov_base = (void*)(t_elt->key);
593         vec_next->iov_len = strlen(t_elt->key);
594         vec_next++;
595         vec_next->iov_base = ": ";
596         vec_next->iov_len = sizeof(": ") - 1;
597         vec_next++;
598         vec_next->iov_base = (void*)(t_elt->val);
599         vec_next->iov_len = strlen(t_elt->val);
600         vec_next++;
601         vec_next->iov_base = CRLF;
602         vec_next->iov_len = sizeof(CRLF) - 1;
603         vec_next++;
604         t_elt++;
605     } while (t_elt < t_end);
606
607 #if APR_CHARSET_EBCDIC
608     {
609         apr_size_t len;
610         char *tmp = apr_pstrcatv(r->pool, vec, vec_next - vec, &len);
611         ap_xlate_proto_to_ascii(tmp, len);
612         return apr_brigade_write(h->bb, NULL, NULL, tmp, len);
613     }
614 #else
615     return apr_brigade_writev(h->bb, NULL, NULL, vec, vec_next - vec);
616 #endif
617 }
618
619 /*
620  * Determine the protocol to use for the response. Potentially downgrade
621  * to HTTP/1.0 in some situations and/or turn off keepalives.
622  *
623  * also prepare r->status_line.
624  */
625 static void basic_http_header_check(request_rec *r,
626                                     const char **protocol)
627 {
628     if (r->assbackwards) {
629         /* no such thing as a response protocol */
630         return;
631     }
632
633     if (!r->status_line) {
634         r->status_line = ap_get_status_line(r->status);
635     }
636
637     /* Note that we must downgrade before checking for force responses. */
638     if (r->proto_num > HTTP_VERSION(1,0)
639         && apr_table_get(r->subprocess_env, "downgrade-1.0")) {
640         r->proto_num = HTTP_VERSION(1,0);
641     }
642
643     /* kludge around broken browsers when indicated by force-response-1.0
644      */
645     if (r->proto_num == HTTP_VERSION(1,0)
646         && apr_table_get(r->subprocess_env, "force-response-1.0")) {
647         *protocol = "HTTP/1.0";
648         r->connection->keepalive = AP_CONN_CLOSE;
649     }
650     else {
651         *protocol = AP_SERVER_PROTOCOL;
652     }
653
654 }
655
656 /* fill "bb" with a barebones/initial HTTP response header */
657 static void basic_http_header(request_rec *r, apr_bucket_brigade *bb,
658                               const char *protocol)
659 {
660     char *date;
661     const char *server;
662     header_struct h;
663     struct iovec vec[4];
664
665     if (r->assbackwards) {
666         /* there are no headers to send */
667         return;
668     }
669
670     /* Output the HTTP/1.x Status-Line and the Date and Server fields */
671
672     vec[0].iov_base = (void *)protocol;
673     vec[0].iov_len  = strlen(protocol);
674     vec[1].iov_base = (void *)" ";
675     vec[1].iov_len  = sizeof(" ") - 1;
676     vec[2].iov_base = (void *)(r->status_line);
677     vec[2].iov_len  = strlen(r->status_line);
678     vec[3].iov_base = (void *)CRLF;
679     vec[3].iov_len  = sizeof(CRLF) - 1;
680 #if APR_CHARSET_EBCDIC
681     {
682         char *tmp;
683         apr_size_t len;
684         tmp = apr_pstrcatv(r->pool, vec, 4, &len);
685         ap_xlate_proto_to_ascii(tmp, len);
686         apr_brigade_write(bb, NULL, NULL, tmp, len);
687     }
688 #else
689     apr_brigade_writev(bb, NULL, NULL, vec, 4);
690 #endif
691
692     date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
693     ap_recent_rfc822_date(date, r->request_time);
694
695     h.pool = r->pool;
696     h.bb = bb;
697     form_header_field(&h, "Date", date);
698
699     /* keep the set-by-proxy server header, otherwise
700      * generate a new server header */
701     if (r->proxyreq != PROXYREQ_NONE) {
702         server = apr_table_get(r->headers_out, "Server");
703         if (server) {
704             form_header_field(&h, "Server", server);
705         }
706     }
707     else {
708         form_header_field(&h, "Server", ap_get_server_version());
709     }
710
711     /* unset so we don't send them again */
712     apr_table_unset(r->headers_out, "Date");        /* Avoid bogosity */
713     apr_table_unset(r->headers_out, "Server");
714 }
715
716 AP_DECLARE(void) ap_basic_http_header(request_rec *r, apr_bucket_brigade *bb)
717 {
718     const char *protocol;
719
720     basic_http_header_check(r, &protocol);
721     basic_http_header(r, bb, protocol);
722 }
723
724 /* Navigator versions 2.x, 3.x and 4.0 betas up to and including 4.0b2
725  * have a header parsing bug.  If the terminating \r\n occur starting
726  * at offset 256, 257 or 258 of output then it will not properly parse
727  * the headers.  Curiously it doesn't exhibit this problem at 512, 513.
728  * We are guessing that this is because their initial read of a new request
729  * uses a 256 byte buffer, and subsequent reads use a larger buffer.
730  * So the problem might exist at different offsets as well.
731  *
732  * This should also work on keepalive connections assuming they use the
733  * same small buffer for the first read of each new request.
734  *
735  * At any rate, we check the bytes written so far and, if we are about to
736  * tickle the bug, we instead insert a bogus padding header.  Since the bug
737  * manifests as a broken image in Navigator, users blame the server.  :(
738  * It is more expensive to check the User-Agent than it is to just add the
739  * bytes, so we haven't used the BrowserMatch feature here.
740  */
741 static void terminate_header(apr_bucket_brigade *bb)
742 {
743     char tmp[] = "X-Pad: avoid browser bug" CRLF;
744     char crlf[] = CRLF;
745     apr_off_t len;
746     apr_size_t buflen;
747
748     (void) apr_brigade_length(bb, 1, &len);
749
750     if (len >= 255 && len <= 257) {
751         buflen = strlen(tmp);
752         ap_xlate_proto_to_ascii(tmp, buflen);
753         apr_brigade_write(bb, NULL, NULL, tmp, buflen);
754     }
755     buflen = strlen(crlf);
756     ap_xlate_proto_to_ascii(crlf, buflen);
757     apr_brigade_write(bb, NULL, NULL, crlf, buflen);
758 }
759
760 AP_DECLARE_NONSTD(int) ap_send_http_trace(request_rec *r)
761 {
762     core_server_config *conf;
763     int rv;
764     apr_bucket_brigade *bb;
765     header_struct h;
766     apr_bucket *b;
767     int body;
768     char *bodyread = NULL, *bodyoff;
769     apr_size_t bodylen = 0;
770     apr_size_t bodybuf;
771     long res = -1; /* init to avoid gcc -Wall warning */
772
773     if (r->method_number != M_TRACE) {
774         return DECLINED;
775     }
776
777     /* Get the original request */
778     while (r->prev) {
779         r = r->prev;
780     }
781     conf = (core_server_config *)ap_get_module_config(r->server->module_config,
782                                                       &core_module);
783
784     if (conf->trace_enable == AP_TRACE_DISABLE) {
785         apr_table_setn(r->notes, "error-notes",
786                       "TRACE denied by server configuration");
787         return HTTP_FORBIDDEN;
788     }
789
790     if (conf->trace_enable == AP_TRACE_EXTENDED)
791         /* XX should be = REQUEST_CHUNKED_PASS */
792         body = REQUEST_CHUNKED_DECHUNK;
793     else
794         body = REQUEST_NO_BODY;
795
796     if ((rv = ap_setup_client_block(r, body))) {
797         if (rv == HTTP_REQUEST_ENTITY_TOO_LARGE)
798             apr_table_setn(r->notes, "error-notes",
799                           "TRACE with a request body is not allowed");
800         return rv;
801     }
802
803     if (ap_should_client_block(r)) {
804
805         if (r->remaining > 0) {
806             if (r->remaining > 65536) {
807                 apr_table_setn(r->notes, "error-notes",
808                        "Extended TRACE request bodies cannot exceed 64k\n");
809                 return HTTP_REQUEST_ENTITY_TOO_LARGE;
810             }
811             /* always 32 extra bytes to catch chunk header exceptions */
812             bodybuf = (apr_size_t)r->remaining + 32;
813         }
814         else {
815             /* Add an extra 8192 for chunk headers */
816             bodybuf = 73730;
817         }
818
819         bodyoff = bodyread = apr_palloc(r->pool, bodybuf);
820
821         /* only while we have enough for a chunked header */
822         while ((!bodylen || bodybuf >= 32) &&
823                (res = ap_get_client_block(r, bodyoff, bodybuf)) > 0) {
824             bodylen += res;
825             bodybuf -= res;
826             bodyoff += res;
827         }
828         if (res > 0 && bodybuf < 32) {
829             /* discard_rest_of_request_body into our buffer */
830             while (ap_get_client_block(r, bodyread, bodylen) > 0)
831                 ;
832             apr_table_setn(r->notes, "error-notes",
833                    "Extended TRACE request bodies cannot exceed 64k\n");
834             return HTTP_REQUEST_ENTITY_TOO_LARGE;
835         }
836
837         if (res < 0) {
838             return HTTP_BAD_REQUEST;
839         }
840     }
841
842     ap_set_content_type(r, "message/http");
843
844     /* Now we recreate the request, and echo it back */
845
846     bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
847     apr_brigade_putstrs(bb, NULL, NULL, r->the_request, CRLF, NULL);
848     h.pool = r->pool;
849     h.bb = bb;
850     apr_table_do((int (*) (void *, const char *, const char *))
851                  form_header_field, (void *) &h, r->headers_in, NULL);
852     apr_brigade_puts(bb, NULL, NULL, CRLF);
853
854     /* If configured to accept a body, echo the body */
855     if (bodylen) {
856         b = apr_bucket_pool_create(bodyread, bodylen,
857                                    r->pool, bb->bucket_alloc);
858         APR_BRIGADE_INSERT_TAIL(bb, b);
859     }
860
861     ap_pass_brigade(r->output_filters,  bb);
862
863     return DONE;
864 }
865
866 typedef struct header_filter_ctx {
867     int headers_sent;
868 } header_filter_ctx;
869
870 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
871                                                            apr_bucket_brigade *b)
872 {
873     request_rec *r = f->r;
874     conn_rec *c = r->connection;
875     const char *clheader;
876     const char *protocol;
877     apr_bucket *e;
878     apr_bucket_brigade *b2;
879     header_struct h;
880     header_filter_ctx *ctx = f->ctx;
881
882     AP_DEBUG_ASSERT(!r->main);
883
884     if (r->header_only) {
885         if (!ctx) {
886             ctx = f->ctx = apr_pcalloc(r->pool, sizeof(header_filter_ctx));
887         }
888         else if (ctx->headers_sent) {
889             apr_brigade_destroy(b);
890             return OK;
891         }
892     }
893
894     for (e = APR_BRIGADE_FIRST(b);
895          e != APR_BRIGADE_SENTINEL(b);
896          e = APR_BUCKET_NEXT(e))
897     {
898         if (e->type == &ap_bucket_type_error) {
899             ap_bucket_error *eb = e->data;
900
901             ap_die(eb->status, r);
902             return AP_FILTER_ERROR;
903         }
904     }
905
906     if (r->assbackwards) {
907         r->sent_bodyct = 1;
908         ap_remove_output_filter(f);
909         return ap_pass_brigade(f->next, b);
910     }
911
912     /*
913      * Now that we are ready to send a response, we need to combine the two
914      * header field tables into a single table.  If we don't do this, our
915      * later attempts to set or unset a given fieldname might be bypassed.
916      */
917     if (!apr_is_empty_table(r->err_headers_out)) {
918         r->headers_out = apr_table_overlay(r->pool, r->err_headers_out,
919                                            r->headers_out);
920     }
921
922     /*
923      * Remove the 'Vary' header field if the client can't handle it.
924      * Since this will have nasty effects on HTTP/1.1 caches, force
925      * the response into HTTP/1.0 mode.
926      *
927      * Note: the force-response-1.0 should come before the call to
928      *       basic_http_header_check()
929      */
930     if (apr_table_get(r->subprocess_env, "force-no-vary") != NULL) {
931         apr_table_unset(r->headers_out, "Vary");
932         r->proto_num = HTTP_VERSION(1,0);
933         apr_table_set(r->subprocess_env, "force-response-1.0", "1");
934     }
935     else {
936         fixup_vary(r);
937     }
938
939     /*
940      * Now remove any ETag response header field if earlier processing
941      * says so (such as a 'FileETag None' directive).
942      */
943     if (apr_table_get(r->notes, "no-etag") != NULL) {
944         apr_table_unset(r->headers_out, "ETag");
945     }
946
947     /* determine the protocol and whether we should use keepalives. */
948     basic_http_header_check(r, &protocol);
949     ap_set_keepalive(r);
950
951     if (r->chunked) {
952         apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
953         apr_table_unset(r->headers_out, "Content-Length");
954     }
955
956     apr_table_setn(r->headers_out, "Content-Type",
957                    ap_make_content_type(r, r->content_type));
958
959     if (r->content_encoding) {
960         apr_table_setn(r->headers_out, "Content-Encoding",
961                        r->content_encoding);
962     }
963
964     if (!apr_is_empty_array(r->content_languages)) {
965         int i;
966         char **languages = (char **)(r->content_languages->elts);
967         for (i = 0; i < r->content_languages->nelts; ++i) {
968             apr_table_mergen(r->headers_out, "Content-Language", languages[i]);
969         }
970     }
971
972     /*
973      * Control cachability for non-cachable responses if not already set by
974      * some other part of the server configuration.
975      */
976     if (r->no_cache && !apr_table_get(r->headers_out, "Expires")) {
977         char *date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
978         ap_recent_rfc822_date(date, r->request_time);
979         apr_table_addn(r->headers_out, "Expires", date);
980     }
981
982     /* This is a hack, but I can't find anyway around it.  The idea is that
983      * we don't want to send out 0 Content-Lengths if it is a head request.
984      * This happens when modules try to outsmart the server, and return
985      * if they see a HEAD request.  Apache 1.3 handlers were supposed to
986      * just return in that situation, and the core handled the HEAD.  In
987      * 2.0, if a handler returns, then the core sends an EOS bucket down
988      * the filter stack, and the content-length filter computes a C-L of
989      * zero and that gets put in the headers, and we end up sending a
990      * zero C-L to the client.  We can't just remove the C-L filter,
991      * because well behaved 2.0 handlers will send their data down the stack,
992      * and we will compute a real C-L for the head request. RBB
993      */
994     if (r->header_only
995         && (clheader = apr_table_get(r->headers_out, "Content-Length"))
996         && !strcmp(clheader, "0")) {
997         apr_table_unset(r->headers_out, "Content-Length");
998     }
999
1000     b2 = apr_brigade_create(r->pool, c->bucket_alloc);
1001     basic_http_header(r, b2, protocol);
1002
1003     h.pool = r->pool;
1004     h.bb = b2;
1005
1006     if (r->status == HTTP_NOT_MODIFIED) {
1007         apr_table_do((int (*)(void *, const char *, const char *)) form_header_field,
1008                      (void *) &h, r->headers_out,
1009                      "Connection",
1010                      "Keep-Alive",
1011                      "ETag",
1012                      "Content-Location",
1013                      "Expires",
1014                      "Cache-Control",
1015                      "Vary",
1016                      "Warning",
1017                      "WWW-Authenticate",
1018                      "Proxy-Authenticate",
1019                      "Set-Cookie",
1020                      "Set-Cookie2",
1021                      NULL);
1022     }
1023     else {
1024         send_all_header_fields(&h, r);
1025     }
1026
1027     terminate_header(b2);
1028
1029     ap_pass_brigade(f->next, b2);
1030
1031     if (r->header_only) {
1032         apr_brigade_destroy(b);
1033         ctx->headers_sent = 1;
1034         return OK;
1035     }
1036
1037     r->sent_bodyct = 1;         /* Whatever follows is real body stuff... */
1038
1039     if (r->chunked) {
1040         /* We can't add this filter until we have already sent the headers.
1041          * If we add it before this point, then the headers will be chunked
1042          * as well, and that is just wrong.
1043          */
1044         ap_add_output_filter("CHUNK", NULL, r, r->connection);
1045     }
1046
1047     /* Don't remove this filter until after we have added the CHUNK filter.
1048      * Otherwise, f->next won't be the CHUNK filter and thus the first
1049      * brigade won't be chunked properly.
1050      */
1051     ap_remove_output_filter(f);
1052     return ap_pass_brigade(f->next, b);
1053 }
1054
1055 /* In HTTP/1.1, any method can have a body.  However, most GET handlers
1056  * wouldn't know what to do with a request body if they received one.
1057  * This helper routine tests for and reads any message body in the request,
1058  * simply discarding whatever it receives.  We need to do this because
1059  * failing to read the request body would cause it to be interpreted
1060  * as the next request on a persistent connection.
1061  *
1062  * Since we return an error status if the request is malformed, this
1063  * routine should be called at the beginning of a no-body handler, e.g.,
1064  *
1065  *    if ((retval = ap_discard_request_body(r)) != OK) {
1066  *        return retval;
1067  *    }
1068  */
1069 AP_DECLARE(int) ap_discard_request_body(request_rec *r)
1070 {
1071     apr_bucket_brigade *bb;
1072     int rv, seen_eos;
1073
1074     /* Sometimes we'll get in a state where the input handling has
1075      * detected an error where we want to drop the connection, so if
1076      * that's the case, don't read the data as that is what we're trying
1077      * to avoid.
1078      *
1079      * This function is also a no-op on a subrequest.
1080      */
1081     if (r->main || r->connection->keepalive == AP_CONN_CLOSE ||
1082         ap_status_drops_connection(r->status)) {
1083         return OK;
1084     }
1085
1086     bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
1087     seen_eos = 0;
1088     do {
1089         apr_bucket *bucket;
1090
1091         rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
1092                             APR_BLOCK_READ, HUGE_STRING_LEN);
1093
1094         if (rv != APR_SUCCESS) {
1095             /* FIXME: If we ever have a mapping from filters (apr_status_t)
1096              * to HTTP error codes, this would be a good place for them.
1097              *
1098              * If we received the special case AP_FILTER_ERROR, it means
1099              * that the filters have already handled this error.
1100              * Otherwise, we should assume we have a bad request.
1101              */
1102             if (rv == AP_FILTER_ERROR) {
1103                 apr_brigade_destroy(bb);
1104                 return rv;
1105             }
1106             else {
1107                 apr_brigade_destroy(bb);
1108                 return HTTP_BAD_REQUEST;
1109             }
1110         }
1111
1112         for (bucket = APR_BRIGADE_FIRST(bb);
1113              bucket != APR_BRIGADE_SENTINEL(bb);
1114              bucket = APR_BUCKET_NEXT(bucket))
1115         {
1116             const char *data;
1117             apr_size_t len;
1118
1119             if (APR_BUCKET_IS_EOS(bucket)) {
1120                 seen_eos = 1;
1121                 break;
1122             }
1123
1124             /* These are metadata buckets. */
1125             if (bucket->length == 0) {
1126                 continue;
1127             }
1128
1129             /* We MUST read because in case we have an unknown-length
1130              * bucket or one that morphs, we want to exhaust it.
1131              */
1132             rv = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
1133             if (rv != APR_SUCCESS) {
1134                 apr_brigade_destroy(bb);
1135                 return HTTP_BAD_REQUEST;
1136             }
1137         }
1138         apr_brigade_cleanup(bb);
1139     } while (!seen_eos);
1140
1141     return OK;
1142 }
1143
1144 /* Here we deal with getting the request message body from the client.
1145  * Whether or not the request contains a body is signaled by the presence
1146  * of a non-zero Content-Length or by a Transfer-Encoding: chunked.
1147  *
1148  * Note that this is more complicated than it was in Apache 1.1 and prior
1149  * versions, because chunked support means that the module does less.
1150  *
1151  * The proper procedure is this:
1152  *
1153  * 1. Call ap_setup_client_block() near the beginning of the request
1154  *    handler. This will set up all the necessary properties, and will
1155  *    return either OK, or an error code. If the latter, the module should
1156  *    return that error code. The second parameter selects the policy to
1157  *    apply if the request message indicates a body, and how a chunked
1158  *    transfer-coding should be interpreted. Choose one of
1159  *
1160  *    REQUEST_NO_BODY          Send 413 error if message has any body
1161  *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
1162  *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
1163  *    REQUEST_CHUNKED_PASS     If chunked, pass the chunk headers with body.
1164  *
1165  *    In order to use the last two options, the caller MUST provide a buffer
1166  *    large enough to hold a chunk-size line, including any extensions.
1167  *
1168  * 2. When you are ready to read a body (if any), call ap_should_client_block().
1169  *    This will tell the module whether or not to read input. If it is 0,
1170  *    the module should assume that there is no message body to read.
1171  *
1172  * 3. Finally, call ap_get_client_block in a loop. Pass it a buffer and its size.
1173  *    It will put data into the buffer (not necessarily a full buffer), and
1174  *    return the length of the input block. When it is done reading, it will
1175  *    return 0 if EOF, or -1 if there was an error.
1176  *    If an error occurs on input, we force an end to keepalive.
1177  *
1178  *    This step also sends a 100 Continue response to HTTP/1.1 clients if appropriate.
1179  */
1180
1181 AP_DECLARE(int) ap_setup_client_block(request_rec *r, int read_policy)
1182 {
1183     const char *tenc = apr_table_get(r->headers_in, "Transfer-Encoding");
1184     const char *lenp = apr_table_get(r->headers_in, "Content-Length");
1185
1186     r->read_body = read_policy;
1187     r->read_chunked = 0;
1188     r->remaining = 0;
1189
1190     if (tenc) {
1191         if (strcasecmp(tenc, "chunked")) {
1192             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1193                           "Unknown Transfer-Encoding %s", tenc);
1194             return HTTP_NOT_IMPLEMENTED;
1195         }
1196         if (r->read_body == REQUEST_CHUNKED_ERROR) {
1197             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1198                           "chunked Transfer-Encoding forbidden: %s", r->uri);
1199             return (lenp) ? HTTP_BAD_REQUEST : HTTP_LENGTH_REQUIRED;
1200         }
1201
1202         r->read_chunked = 1;
1203     }
1204     else if (lenp) {
1205         char *endstr;
1206
1207         if (apr_strtoff(&r->remaining, lenp, &endstr, 10)
1208             || *endstr || r->remaining < 0) {
1209             r->remaining = 0;
1210             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1211                           "Invalid Content-Length");
1212             return HTTP_BAD_REQUEST;
1213         }
1214     }
1215
1216     if ((r->read_body == REQUEST_NO_BODY)
1217         && (r->read_chunked || (r->remaining > 0))) {
1218         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1219                       "%s with body is not allowed for %s", r->method, r->uri);
1220         return HTTP_REQUEST_ENTITY_TOO_LARGE;
1221     }
1222
1223 #ifdef AP_DEBUG
1224     {
1225         /* Make sure ap_getline() didn't leave any droppings. */
1226         core_request_config *req_cfg =
1227             (core_request_config *)ap_get_module_config(r->request_config,
1228                                                         &core_module);
1229         AP_DEBUG_ASSERT(APR_BRIGADE_EMPTY(req_cfg->bb));
1230     }
1231 #endif
1232
1233     return OK;
1234 }
1235
1236 AP_DECLARE(int) ap_should_client_block(request_rec *r)
1237 {
1238     /* First check if we have already read the request body */
1239
1240     if (r->read_length || (!r->read_chunked && (r->remaining <= 0))) {
1241         return 0;
1242     }
1243
1244     return 1;
1245 }
1246
1247 /* get_client_block is called in a loop to get the request message body.
1248  * This is quite simple if the client includes a content-length
1249  * (the normal case), but gets messy if the body is chunked. Note that
1250  * r->remaining is used to maintain state across calls and that
1251  * r->read_length is the total number of bytes given to the caller
1252  * across all invocations.  It is messy because we have to be careful not
1253  * to read past the data provided by the client, since these reads block.
1254  * Returns 0 on End-of-body, -1 on error or premature chunk end.
1255  *
1256  */
1257 AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer,
1258                                      apr_size_t bufsiz)
1259 {
1260     apr_status_t rv;
1261     apr_bucket_brigade *bb;
1262
1263     if (r->remaining < 0 || (!r->read_chunked && r->remaining == 0)) {
1264         return 0;
1265     }
1266
1267     bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
1268     if (bb == NULL) {
1269         r->connection->keepalive = AP_CONN_CLOSE;
1270         return -1;
1271     }
1272
1273     rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
1274                         APR_BLOCK_READ, bufsiz);
1275
1276     /* We lose the failure code here.  This is why ap_get_client_block should
1277      * not be used.
1278      */
1279     if (rv != APR_SUCCESS) {
1280         /* if we actually fail here, we want to just return and
1281          * stop trying to read data from the client.
1282          */
1283         r->connection->keepalive = AP_CONN_CLOSE;
1284         apr_brigade_destroy(bb);
1285         return -1;
1286     }
1287
1288     /* If this fails, it means that a filter is written incorrectly and that
1289      * it needs to learn how to properly handle APR_BLOCK_READ requests by
1290      * returning data when requested.
1291      */
1292     AP_DEBUG_ASSERT(!APR_BRIGADE_EMPTY(bb));
1293
1294     /* Check to see if EOS in the brigade.
1295      *
1296      * If so, we have to leave a nugget for the *next* ap_get_client_block
1297      * call to return 0.
1298      */
1299     if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
1300         if (r->read_chunked) {
1301             r->remaining = -1;
1302         }
1303         else {
1304             r->remaining = 0;
1305         }
1306     }
1307
1308     rv = apr_brigade_flatten(bb, buffer, &bufsiz);
1309     if (rv != APR_SUCCESS) {
1310         apr_brigade_destroy(bb);
1311         return -1;
1312     }
1313
1314     /* XXX yank me? */
1315     r->read_length += bufsiz;
1316
1317     apr_brigade_destroy(bb);
1318     return bufsiz;
1319 }
1320