--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/apache2/patches/r1165607.patch Thu Sep 08 14:48:47 2011 -0700
@@ -0,0 +1,278 @@
+Jeff Trawick <[email protected]>
+Subject [PATCH] byterange patch for 2.2.20
+Date Thu, 08 Sep 2011 15:16:11 GMT
+
+Here's what I have at present:
+http://people.apache.org/~trawick/2.2.20-byterange-fixes.txt
+
+(compiled-in max ranges, uses same AP_ symbol as 2.2.21 even though
+the compiled-in version isn't the same type of "DEFAULT")
+
+--- modules/http/byterange_filter.c.orig 2011-09-08 11:03:54.000000000 -0400
++++ modules/http/byterange_filter.c 2011-09-08 11:02:36.000000000 -0400
+@@ -55,6 +55,10 @@
+ #include <unistd.h>
+ #endif
+
++#ifndef AP_DEFAULT_MAX_RANGES
++#define AP_DEFAULT_MAX_RANGES 200
++#endif
++
+ static int ap_set_byterange(request_rec *r, apr_off_t clength,
+ apr_array_header_t **indexes);
+
+@@ -83,8 +87,6 @@
+ apr_bucket *first = NULL, *last = NULL, *out_first = NULL, *e;
+ apr_uint64_t pos = 0, off_first = 0, off_last = 0;
+ apr_status_t rv;
+- const char *s;
+- apr_size_t len;
+ apr_uint64_t start64, end64;
+ apr_off_t pofft = 0;
+
+@@ -136,44 +138,10 @@
+ if (e == first) {
+ if (off_first != start64) {
+ rv = apr_bucket_split(copy, (apr_size_t)(start64 - off_first));
+- if (rv == APR_ENOTIMPL) {
+- rv = apr_bucket_read(copy, &s, &len, APR_BLOCK_READ);
+- if (rv != APR_SUCCESS) {
+- apr_brigade_cleanup(bbout);
+- return rv;
+- }
+- /*
+- * The read above might have morphed copy in a bucket
+- * of shorter length. So read and delete until we reached
+- * the correct bucket for splitting.
+- */
+- while (start64 - off_first > (apr_uint64_t)copy->length) {
+- apr_bucket *tmp = APR_BUCKET_NEXT(copy);
+- off_first += (apr_uint64_t)copy->length;
+- APR_BUCKET_REMOVE(copy);
+- apr_bucket_destroy(copy);
+- copy = tmp;
+- rv = apr_bucket_read(copy, &s, &len, APR_BLOCK_READ);
+- if (rv != APR_SUCCESS) {
+- apr_brigade_cleanup(bbout);
+- return rv;
+- }
+- }
+- if (start64 > off_first) {
+- rv = apr_bucket_split(copy, (apr_size_t)(start64 - off_first));
+ if (rv != APR_SUCCESS) {
+ apr_brigade_cleanup(bbout);
+ return rv;
+ }
+- }
+- else {
+- copy = APR_BUCKET_PREV(copy);
+- }
+- }
+- else if (rv != APR_SUCCESS) {
+- apr_brigade_cleanup(bbout);
+- return rv;
+- }
+ out_first = APR_BUCKET_NEXT(copy);
+ APR_BUCKET_REMOVE(copy);
+ apr_bucket_destroy(copy);
+@@ -189,38 +157,10 @@
+ }
+ if (end64 - off_last != (apr_uint64_t)e->length) {
+ rv = apr_bucket_split(copy, (apr_size_t)(end64 + 1 - off_last));
+- if (rv == APR_ENOTIMPL) {
+- rv = apr_bucket_read(copy, &s, &len, APR_BLOCK_READ);
+ if (rv != APR_SUCCESS) {
+ apr_brigade_cleanup(bbout);
+ return rv;
+ }
+- /*
+- * The read above might have morphed copy in a bucket
+- * of shorter length. So read until we reached
+- * the correct bucket for splitting.
+- */
+- while (end64 + 1 - off_last > (apr_uint64_t)copy->length) {
+- off_last += (apr_uint64_t)copy->length;
+- copy = APR_BUCKET_NEXT(copy);
+- rv = apr_bucket_read(copy, &s, &len, APR_BLOCK_READ);
+- if (rv != APR_SUCCESS) {
+- apr_brigade_cleanup(bbout);
+- return rv;
+- }
+- }
+- if (end64 < off_last + (apr_uint64_t)copy->length - 1) {
+- rv = apr_bucket_split(copy, end64 + 1 - off_last);
+- if (rv != APR_SUCCESS) {
+- apr_brigade_cleanup(bbout);
+- return rv;
+- }
+- }
+- }
+- else if (rv != APR_SUCCESS) {
+- apr_brigade_cleanup(bbout);
+- return rv;
+- }
+ copy = APR_BUCKET_NEXT(copy);
+ if (copy != APR_BRIGADE_SENTINEL(bbout)) {
+ APR_BUCKET_REMOVE(copy);
+@@ -243,6 +183,20 @@
+ apr_off_t end;
+ } indexes_t;
+
++static apr_status_t send_416(ap_filter_t *f, apr_bucket_brigade *tmpbb)
++{
++ apr_bucket *e;
++ conn_rec *c = f->r->connection;
++ ap_remove_output_filter(f);
++ f->r->status = HTTP_OK;
++ e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL,
++ f->r->pool, c->bucket_alloc);
++ APR_BRIGADE_INSERT_TAIL(tmpbb, e);
++ e = apr_bucket_eos_create(c->bucket_alloc);
++ APR_BRIGADE_INSERT_TAIL(tmpbb, e);
++ return ap_pass_brigade(f->next, tmpbb);
++}
++
+ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(ap_filter_t *f,
+ apr_bucket_brigade *bb)
+ {
+@@ -290,17 +244,23 @@
+ num_ranges = ap_set_byterange(r, clength, &indexes);
+
+ /* We have nothing to do, get out of the way. */
+- if (num_ranges == 0) {
++ if (num_ranges == 0 || (AP_DEFAULT_MAX_RANGES >= 0 && num_ranges > AP_DEFAULT_MAX_RANGES)) {
+ r->status = original_status;
+ ap_remove_output_filter(f);
+ return ap_pass_brigade(f->next, bb);
+ }
+
++ /* this brigade holds what we will be sending */
++ bsend = apr_brigade_create(r->pool, c->bucket_alloc);
++
++ if (num_ranges < 0)
++ return send_416(f, bsend);
++
+ if (num_ranges > 1) {
+ /* Is ap_make_content_type required here? */
+ const char *orig_ct = ap_make_content_type(r, r->content_type);
+ boundary = apr_psprintf(r->pool, "%" APR_UINT64_T_HEX_FMT "%lx",
+- (apr_uint64_t)r->request_time, (long) getpid());
++ (apr_uint64_t)r->request_time, c->id);
+
+ ap_set_content_type(r, apr_pstrcat(r->pool, "multipart",
+ use_range_x(r) ? "/x-" : "/",
+@@ -325,8 +285,6 @@
+ ap_xlate_proto_to_ascii(bound_head, strlen(bound_head));
+ }
+
+- /* this brigade holds what we will be sending */
+- bsend = apr_brigade_create(r->pool, c->bucket_alloc);
+ tmpbb = apr_brigade_create(r->pool, c->bucket_alloc);
+
+ idx = (indexes_t *)indexes->elts;
+@@ -384,15 +342,8 @@
+ }
+
+ if (found == 0) {
+- ap_remove_output_filter(f);
+- r->status = HTTP_OK;
+ /* bsend is assumed to be empty if we get here. */
+- e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL,
+- r->pool, c->bucket_alloc);
+- APR_BRIGADE_INSERT_TAIL(bsend, e);
+- e = apr_bucket_eos_create(c->bucket_alloc);
+- APR_BRIGADE_INSERT_TAIL(bsend, e);
+- return ap_pass_brigade(f->next, bsend);
++ return send_416(f, bsend);
+ }
+
+ if (num_ranges > 1) {
+@@ -424,7 +375,7 @@
+ const char *match;
+ const char *ct;
+ char *cur;
+- int num_ranges = 0;
++ int num_ranges = 0, unsatisfiable = 0;
+ apr_off_t sum_lengths = 0;
+ indexes_t *idx;
+ int ranges = 1;
+@@ -497,14 +448,25 @@
+ char *errp;
+ apr_off_t number, start, end;
+
+- if (!(dash = strchr(cur, '-'))) {
++ if (!*cur)
+ break;
++
++ /*
++ * Per RFC 2616 14.35.1: If there is at least one syntactically invalid
++ * byte-range-spec, we must ignore the whole header.
++ */
++
++ if (!(dash = strchr(cur, '-'))) {
++ return 0;
+ }
+
+- if (dash == range) {
++ if (dash == cur) {
+ /* In the form "-5" */
+ if (apr_strtoff(&number, dash+1, &errp, 10) || *errp) {
+- break;
++ return 0;
++ }
++ if (number < 1) {
++ return 0;
+ }
+ start = clength - number;
+ end = clength - 1;
+@@ -512,14 +474,17 @@
+ else {
+ *dash++ = '\0';
+ if (apr_strtoff(&number, cur, &errp, 10) || *errp) {
+- break;
++ return 0;
+ }
+ start = number;
+ if (*dash) {
+ if (apr_strtoff(&number, dash, &errp, 10) || *errp) {
+- break;
++ return 0;
+ }
+ end = number;
++ if (start > end) {
++ return 0;
++ }
+ }
+ else { /* "5-" */
+ end = clength - 1;
+@@ -529,15 +494,14 @@
+ if (start < 0) {
+ start = 0;
+ }
++ if (start >= clength) {
++ unsatisfiable = 1;
++ continue;
++ }
+ if (end >= clength) {
+ end = clength - 1;
+ }
+
+- if (start > end) {
+- /* ignore? count? */
+- break;
+- }
+-
+ idx = (indexes_t *)apr_array_push(*indexes);
+ idx->start = start;
+ idx->end = end;
+@@ -546,6 +510,10 @@
+ num_ranges++;
+ }
+
++ if (num_ranges == 0 && unsatisfiable) {
++ /* If all ranges are unsatisfiable, we should return 416 */
++ return -1;
++ }
+ if (sum_lengths >= clength) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Sum of ranges not smaller than file, ignoring.");