From: Jim Jagielski Date: Thu, 25 Aug 2011 17:38:19 +0000 (+0000) Subject: Merge in byteranges X-Git-Tag: 2.3.15~356 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4eddc76b623b85ac0d8c03f5548226cc270e0130;p=apache Merge in byteranges git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1161661 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/http/byterange_filter.c b/modules/http/byterange_filter.c index cc665e5efa..63e46798f6 100644 --- a/modules/http/byterange_filter.c +++ b/modules/http/byterange_filter.c @@ -469,11 +469,14 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(ap_filter_t *f, static int ap_set_byterange(request_rec *r) { - const char *range; + const char *range, *or; const char *if_range; const char *match; const char *ct; - int num_ranges; + char *merged, *cur; + int num_ranges = 0; + apr_off_t ostart, oend; + int in_merge = 0; if (r->assbackwards) { return 0; @@ -526,17 +529,81 @@ static int ap_set_byterange(request_rec *r) } } - if (!ap_strchr_c(range, ',')) { - /* a single range */ - num_ranges = 1; - } - else { - /* a multiple range */ - num_ranges = 2; + range += 6; + or = apr_pstrdup(r->pool, range); + merged = apr_pstrdup(r->pool, ""); + while ((cur = ap_getword(r->pool, &range, ','))) { + char *dash; + char *errp; + apr_off_t number, start, end; + + if (!(dash = strchr(cur, '-'))) { + break; + } + + if (dash == cur) { + /* In the form "-5"... leave as is */ + merged = apr_pstrcat(r->pool, merged, (num_ranges++ ? "," : ""), cur, NULL); + continue; + } + *dash++ = '\0'; + if (!*dash) { + /* form "5-" */ + merged = apr_pstrcat(r->pool, merged, (num_ranges++ ? "," : ""), cur, "-", NULL); + continue; + } + /* + * we have #-#, so we need to grab them... we don't bother + * doing this for the #- or -# cases for speed reasons. + * After all, those will be fixed when the filter parses + * the merged range + */ + if (apr_strtoff(&number, cur, &errp, 10) || *errp || number < 0) { + break; + } + start = number; + if (apr_strtoff(&number, dash, &errp, 10) || *errp || number <= 0) { + break; + } + end = number; + if (!in_merge) { + ostart = start; + oend = end; + } + in_merge = 0; + if (start <= ostart) { + ostart = start; + in_merge = 1; + } + if (start > ostart && start < oend) { + in_merge = 1; + } + if ((end-1) >= oend) { + oend = end; + in_merge = 1; + } + if (end > ostart && end < oend) { + in_merge = 1; + } + if (in_merge) { + continue; + } else { + char *nr = apr_psprintf(r->pool, "%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT, + ostart, oend); + merged = apr_pstrcat(r->pool, merged, (num_ranges++ ? "," : ""), nr, NULL); + } } + if (in_merge) { + char *nr = apr_psprintf(r->pool, "%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT, + ostart, oend); + merged = apr_pstrcat(r->pool, merged, (num_ranges++ ? "," : ""), nr, NULL); + } + r->status = HTTP_PARTIAL_CONTENT; - r->range = range + 6; + r->range = merged; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "Range: %s | %s", or, merged); return num_ranges; }