--- modules/http/byterange_filter.c 2011-09-05 12:04:06.000000000 -0400 +++ ../httpd-plain/modules/http//byterange_filter.c 2011-09-05 11:58:48.000000000 -0400 @@ -19,6 +19,11 @@ */ #include "apr.h" + +#if APR_HAVE_PROCESS_H +#include /* for getpid() on Win32 */ +#endif + #include "apr_strings.h" #include "apr_buckets.h" #include "apr_lib.h" @@ -29,7 +34,6 @@ #define APR_WANT_MEMFUNC #include "apr_want.h" -#define CORE_PRIVATE #include "util_filter.h" #include "ap_config.h" #include "httpd.h" @@ -59,6 +63,8 @@ #define DEFAULT_MAX_RANGES 200 #endif +APLOG_USE_MODULE(http); + static int ap_set_byterange(request_rec *r, apr_off_t clength, apr_array_header_t **indexes); @@ -78,6 +84,7 @@ } #define BYTERANGE_FMT "%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT "/%" APR_OFF_T_FMT +#define MAX_PREALLOC_RANGES 100 static apr_status_t copy_brigade_range(apr_bucket_brigade *bb, apr_bucket_brigade *bbout, @@ -184,8 +191,7 @@ } indexes_t; static int get_max_ranges(request_rec *r) { - core_dir_config *core_conf = ap_get_module_config(r->per_dir_config, - &core_module); + core_dir_config *core_conf = ap_get_core_module_config(r->per_dir_config); return core_conf->max_ranges == -1 ? DEFAULT_MAX_RANGES : core_conf->max_ranges; } @@ -274,7 +280,7 @@ "byteranges; boundary=", boundary, NULL)); - if (strcasecmp(orig_ct, NO_CONTENT_TYPE)) { + if (orig_ct) { bound_head = apr_pstrcat(r->pool, CRLF "--", boundary, CRLF "Content-type: ", @@ -381,10 +387,13 @@ const char *if_range; const char *match; const char *ct; - char *cur; + char *cur, **new; + apr_array_header_t *merged; int num_ranges = 0, unsatisfiable = 0; - apr_off_t sum_lengths = 0; + apr_off_t ostart = 0, oend = 0, sum_lengths = 0; + int in_merge = 0; indexes_t *idx; + int overlaps = 0, reversals = 0; int ranges = 1; const char *it; @@ -449,7 +458,11 @@ } } it = range; + if (ranges > MAX_PREALLOC_RANGES) { + ranges = MAX_PREALLOC_RANGES; + } *indexes = apr_array_make(r->pool, ranges, sizeof(indexes_t)); + merged = apr_array_make(r->pool, ranges, sizeof(char *)); while ((cur = ap_getword(r->pool, &range, ','))) { char *dash; char *errp; @@ -509,26 +522,73 @@ end = clength - 1; } + if (!in_merge) { + /* new set */ + ostart = start; + oend = end; + in_merge = 1; + continue; + } + in_merge = 0; + + if (start >= ostart && end <= oend) { + in_merge = 1; + } + + if (start < ostart && end >= ostart-1) { + ostart = start; + reversals++; + in_merge = 1; + } + if (end >= oend && start <= oend+1 ) { + oend = end; + in_merge = 1; + } + + if (in_merge) { + overlaps++; + continue; + } else { + new = (char **)apr_array_push(merged); + *new = apr_psprintf(r->pool, "%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT, + ostart, oend); + idx = (indexes_t *)apr_array_push(*indexes); + idx->start = ostart; + idx->end = oend; + sum_lengths += oend - ostart + 1; + /* new set again */ + in_merge = 1; + ostart = start; + oend = end; + num_ranges++; + } + } + + if (in_merge) { + new = (char **)apr_array_push(merged); + *new = apr_psprintf(r->pool, "%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT, + ostart, oend); idx = (indexes_t *)apr_array_push(*indexes); - idx->start = start; - idx->end = end; - sum_lengths += end - start + 1; - /* new set again */ + idx->start = ostart; + idx->end = oend; + sum_lengths += oend - ostart + 1; num_ranges++; } - - if (num_ranges == 0 && unsatisfiable) { + else 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, + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Sum of ranges not smaller than file, ignoring."); return 0; } r->status = HTTP_PARTIAL_CONTENT; - r->range = it; + r->range = apr_array_pstrcat(r->pool, merged, ','); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "Range: %s | %s (%d : %d : %"APR_OFF_T_FMT")", + it, r->range, overlaps, reversals, clength); return num_ranges; }