components/apache2/patches/r1165607.patch
branchs11-sru
changeset 2249 9c4f7d7572dd
parent 2248 c2beb07524a9
child 2250 e145454a43d2
equal deleted inserted replaced
2248:c2beb07524a9 2249:9c4f7d7572dd
     1 Jeff Trawick <[email protected]>
       
     2 Subject 	[PATCH] byterange patch for 2.2.20
       
     3 Date 	Thu, 08 Sep 2011 15:16:11 GMT
       
     4 
       
     5 Here's what I have at present:
       
     6 http://people.apache.org/~trawick/2.2.20-byterange-fixes.txt
       
     7 
       
     8 (compiled-in max ranges, uses same AP_ symbol as 2.2.21 even though
       
     9 the compiled-in version isn't the same type of "DEFAULT")
       
    10 
       
    11 --- modules/http/byterange_filter.c.orig	2011-09-08 11:03:54.000000000 -0400
       
    12 +++ modules/http/byterange_filter.c	2011-09-08 11:02:36.000000000 -0400
       
    13 @@ -55,6 +55,10 @@
       
    14  #include <unistd.h>
       
    15  #endif
       
    16  
       
    17 +#ifndef AP_DEFAULT_MAX_RANGES
       
    18 +#define AP_DEFAULT_MAX_RANGES 200
       
    19 +#endif
       
    20 +
       
    21  static int ap_set_byterange(request_rec *r, apr_off_t clength,
       
    22                              apr_array_header_t **indexes);
       
    23  
       
    24 @@ -83,8 +87,6 @@
       
    25      apr_bucket *first = NULL, *last = NULL, *out_first = NULL, *e;
       
    26      apr_uint64_t pos = 0, off_first = 0, off_last = 0;
       
    27      apr_status_t rv;
       
    28 -    const char *s;
       
    29 -    apr_size_t len;
       
    30      apr_uint64_t start64, end64;
       
    31      apr_off_t pofft = 0;
       
    32  
       
    33 @@ -136,44 +138,10 @@
       
    34          if (e == first) {
       
    35              if (off_first != start64) {
       
    36                  rv = apr_bucket_split(copy, (apr_size_t)(start64 - off_first));
       
    37 -                if (rv == APR_ENOTIMPL) {
       
    38 -                    rv = apr_bucket_read(copy, &s, &len, APR_BLOCK_READ);
       
    39 -                    if (rv != APR_SUCCESS) {
       
    40 -                        apr_brigade_cleanup(bbout);
       
    41 -                        return rv;
       
    42 -                    }
       
    43 -                    /*
       
    44 -                     * The read above might have morphed copy in a bucket
       
    45 -                     * of shorter length. So read and delete until we reached
       
    46 -                     * the correct bucket for splitting.
       
    47 -                     */
       
    48 -                    while (start64 - off_first > (apr_uint64_t)copy->length) {
       
    49 -                        apr_bucket *tmp = APR_BUCKET_NEXT(copy);
       
    50 -                        off_first += (apr_uint64_t)copy->length;
       
    51 -                        APR_BUCKET_REMOVE(copy);
       
    52 -                        apr_bucket_destroy(copy);
       
    53 -                        copy = tmp;
       
    54 -                        rv = apr_bucket_read(copy, &s, &len, APR_BLOCK_READ);
       
    55 -                        if (rv != APR_SUCCESS) {
       
    56 -                            apr_brigade_cleanup(bbout);
       
    57 -                            return rv;
       
    58 -                        }
       
    59 -                    }
       
    60 -                    if (start64 > off_first) {
       
    61 -                        rv = apr_bucket_split(copy, (apr_size_t)(start64 - off_first));
       
    62                          if (rv != APR_SUCCESS) {
       
    63                              apr_brigade_cleanup(bbout);
       
    64                              return rv;
       
    65                          }
       
    66 -                    }
       
    67 -                    else {
       
    68 -                        copy = APR_BUCKET_PREV(copy);
       
    69 -                    }
       
    70 -                }
       
    71 -                else if (rv != APR_SUCCESS) {
       
    72 -                        apr_brigade_cleanup(bbout);
       
    73 -                        return rv;
       
    74 -                }
       
    75                  out_first = APR_BUCKET_NEXT(copy);
       
    76                  APR_BUCKET_REMOVE(copy);
       
    77                  apr_bucket_destroy(copy);
       
    78 @@ -189,38 +157,10 @@
       
    79              }
       
    80              if (end64 - off_last != (apr_uint64_t)e->length) {
       
    81                  rv = apr_bucket_split(copy, (apr_size_t)(end64 + 1 - off_last));
       
    82 -                if (rv == APR_ENOTIMPL) {
       
    83 -                    rv = apr_bucket_read(copy, &s, &len, APR_BLOCK_READ);
       
    84                      if (rv != APR_SUCCESS) {
       
    85                          apr_brigade_cleanup(bbout);
       
    86                          return rv;
       
    87                      }
       
    88 -                    /*
       
    89 -                     * The read above might have morphed copy in a bucket
       
    90 -                     * of shorter length. So read until we reached
       
    91 -                     * the correct bucket for splitting.
       
    92 -                     */
       
    93 -                    while (end64 + 1 - off_last > (apr_uint64_t)copy->length) {
       
    94 -                        off_last += (apr_uint64_t)copy->length;
       
    95 -                        copy = APR_BUCKET_NEXT(copy);
       
    96 -                        rv = apr_bucket_read(copy, &s, &len, APR_BLOCK_READ);
       
    97 -                        if (rv != APR_SUCCESS) {
       
    98 -                            apr_brigade_cleanup(bbout);
       
    99 -                            return rv;
       
   100 -                        }
       
   101 -                    }
       
   102 -                    if (end64 < off_last + (apr_uint64_t)copy->length - 1) {
       
   103 -                        rv = apr_bucket_split(copy, end64 + 1 - off_last);
       
   104 -                        if (rv != APR_SUCCESS) {
       
   105 -                            apr_brigade_cleanup(bbout);
       
   106 -                            return rv;
       
   107 -                        }
       
   108 -                    }
       
   109 -                }
       
   110 -                else if (rv != APR_SUCCESS) {
       
   111 -                        apr_brigade_cleanup(bbout);
       
   112 -                        return rv;
       
   113 -                }
       
   114                  copy = APR_BUCKET_NEXT(copy);
       
   115                  if (copy != APR_BRIGADE_SENTINEL(bbout)) {
       
   116                      APR_BUCKET_REMOVE(copy);
       
   117 @@ -243,6 +183,20 @@
       
   118      apr_off_t end;
       
   119  } indexes_t;
       
   120  
       
   121 +static apr_status_t send_416(ap_filter_t *f, apr_bucket_brigade *tmpbb)
       
   122 +{
       
   123 +    apr_bucket *e;
       
   124 +    conn_rec *c = f->r->connection;
       
   125 +    ap_remove_output_filter(f);
       
   126 +    f->r->status = HTTP_OK;
       
   127 +    e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL,
       
   128 +                               f->r->pool, c->bucket_alloc);
       
   129 +    APR_BRIGADE_INSERT_TAIL(tmpbb, e);
       
   130 +    e = apr_bucket_eos_create(c->bucket_alloc);
       
   131 +    APR_BRIGADE_INSERT_TAIL(tmpbb, e);
       
   132 +    return ap_pass_brigade(f->next, tmpbb);
       
   133 +}
       
   134 +
       
   135  AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(ap_filter_t *f,
       
   136                                                           apr_bucket_brigade *bb)
       
   137  {
       
   138 @@ -290,17 +244,23 @@
       
   139      num_ranges = ap_set_byterange(r, clength, &indexes);
       
   140  
       
   141      /* We have nothing to do, get out of the way. */
       
   142 -    if (num_ranges == 0) {
       
   143 +    if (num_ranges == 0 || (AP_DEFAULT_MAX_RANGES >= 0 && num_ranges > AP_DEFAULT_MAX_RANGES)) {
       
   144          r->status = original_status;
       
   145          ap_remove_output_filter(f);
       
   146          return ap_pass_brigade(f->next, bb);
       
   147      }
       
   148  
       
   149 +    /* this brigade holds what we will be sending */
       
   150 +    bsend = apr_brigade_create(r->pool, c->bucket_alloc);
       
   151 +
       
   152 +    if (num_ranges < 0)
       
   153 +        return send_416(f, bsend);
       
   154 +
       
   155      if (num_ranges > 1) {
       
   156          /* Is ap_make_content_type required here? */
       
   157          const char *orig_ct = ap_make_content_type(r, r->content_type);
       
   158          boundary = apr_psprintf(r->pool, "%" APR_UINT64_T_HEX_FMT "%lx",
       
   159 -                                (apr_uint64_t)r->request_time, (long) getpid());
       
   160 +                                (apr_uint64_t)r->request_time, c->id);
       
   161  
       
   162          ap_set_content_type(r, apr_pstrcat(r->pool, "multipart",
       
   163                                             use_range_x(r) ? "/x-" : "/",
       
   164 @@ -325,8 +285,6 @@
       
   165          ap_xlate_proto_to_ascii(bound_head, strlen(bound_head));
       
   166      }
       
   167  
       
   168 -    /* this brigade holds what we will be sending */
       
   169 -    bsend = apr_brigade_create(r->pool, c->bucket_alloc);
       
   170      tmpbb = apr_brigade_create(r->pool, c->bucket_alloc);
       
   171  
       
   172      idx = (indexes_t *)indexes->elts;
       
   173 @@ -384,15 +342,8 @@
       
   174      }
       
   175  
       
   176      if (found == 0) {
       
   177 -        ap_remove_output_filter(f);
       
   178 -        r->status = HTTP_OK;
       
   179          /* bsend is assumed to be empty if we get here. */
       
   180 -        e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL,
       
   181 -                                   r->pool, c->bucket_alloc);
       
   182 -        APR_BRIGADE_INSERT_TAIL(bsend, e);
       
   183 -        e = apr_bucket_eos_create(c->bucket_alloc);
       
   184 -        APR_BRIGADE_INSERT_TAIL(bsend, e);
       
   185 -        return ap_pass_brigade(f->next, bsend);
       
   186 +        return send_416(f, bsend);
       
   187      }
       
   188  
       
   189      if (num_ranges > 1) {
       
   190 @@ -424,7 +375,7 @@
       
   191      const char *match;
       
   192      const char *ct;
       
   193      char *cur;
       
   194 -    int num_ranges = 0;
       
   195 +    int num_ranges = 0, unsatisfiable = 0;
       
   196      apr_off_t sum_lengths = 0;
       
   197      indexes_t *idx;
       
   198      int ranges = 1;
       
   199 @@ -497,14 +448,25 @@
       
   200          char *errp;
       
   201          apr_off_t number, start, end;
       
   202  
       
   203 -        if (!(dash = strchr(cur, '-'))) {
       
   204 +        if (!*cur)
       
   205              break;
       
   206 +
       
   207 +        /*
       
   208 +         * Per RFC 2616 14.35.1: If there is at least one syntactically invalid
       
   209 +         * byte-range-spec, we must ignore the whole header.
       
   210 +         */
       
   211 +
       
   212 +        if (!(dash = strchr(cur, '-'))) {
       
   213 +            return 0;
       
   214          }
       
   215  
       
   216 -        if (dash == range) {
       
   217 +        if (dash == cur) {
       
   218              /* In the form "-5" */
       
   219              if (apr_strtoff(&number, dash+1, &errp, 10) || *errp) {
       
   220 -                break;
       
   221 +                return 0;
       
   222 +            }
       
   223 +            if (number < 1) {
       
   224 +                return 0;
       
   225              }
       
   226              start = clength - number;
       
   227              end = clength - 1;
       
   228 @@ -512,14 +474,17 @@
       
   229          else {
       
   230              *dash++ = '\0';
       
   231              if (apr_strtoff(&number, cur, &errp, 10) || *errp) {
       
   232 -                break;
       
   233 +                return 0;
       
   234              }
       
   235              start = number;
       
   236              if (*dash) {
       
   237                  if (apr_strtoff(&number, dash, &errp, 10) || *errp) {
       
   238 -                    break;
       
   239 +                    return 0;
       
   240                  }
       
   241                  end = number;
       
   242 +                if (start > end) {
       
   243 +                    return 0;
       
   244 +                }
       
   245              }
       
   246              else {                  /* "5-" */
       
   247                  end = clength - 1;
       
   248 @@ -529,15 +494,14 @@
       
   249          if (start < 0) {
       
   250              start = 0;
       
   251          }
       
   252 +        if (start >= clength) {
       
   253 +            unsatisfiable = 1;
       
   254 +            continue;
       
   255 +        }
       
   256          if (end >= clength) {
       
   257              end = clength - 1;
       
   258          }
       
   259  
       
   260 -        if (start > end) {
       
   261 -            /* ignore? count? */
       
   262 -            break;
       
   263 -        }
       
   264 -
       
   265          idx = (indexes_t *)apr_array_push(*indexes);
       
   266          idx->start = start;
       
   267          idx->end = end;
       
   268 @@ -546,6 +510,10 @@
       
   269          num_ranges++;
       
   270      }
       
   271  
       
   272 +    if (num_ranges == 0 && unsatisfiable) {
       
   273 +        /* If all ranges are unsatisfiable, we should return 416 */
       
   274 +        return -1;
       
   275 +    }
       
   276      if (sum_lengths >= clength) {
       
   277          ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
       
   278                        "Sum of ranges not smaller than file, ignoring.");