httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r..@apache.org
Subject cvs commit: httpd-2.0/server core.c protocol.c
Date Wed, 11 Apr 2001 23:37:17 GMT
rbb         01/04/11 16:37:17

  Modified:    .        CHANGES
               modules/http http_core.c http_protocol.c
               server   core.c protocol.c
  Log:
  When I initially pulled the BYTERANGE filter into the core, Greg Stein
  told me I was wrong.  I was wrong, and Greg was right.  This commit
  just moves the byterange filter and its related functions out of the core,
  and puts them back in the HTTP specific module.
  Submitted by:	Greg Stein
  
  Revision  Changes    Path
  1.170     +4 -0      httpd-2.0/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.169
  retrieving revision 1.170
  diff -u -d -b -w -u -r1.169 -r1.170
  --- CHANGES	2001/04/11 06:44:03	1.169
  +++ CHANGES	2001/04/11 23:37:15	1.170
  @@ -1,5 +1,9 @@
   Changes with Apache 2.0.17-dev
   
  +  *) Move the byterange filter and all of the supporting functions back
  +     to the HTTP module.  The byterange filter turned out to be very
  +     HTTP specific, and it belongs in the HTTP module.  [Greg Stein]
  +
     *) Make clean, distclean, and extraclean consistently according to the
        Gnu makefile guidelines.  [Justin Erenkrantz <jerenkrantz@ebuilt.com>]
   
  
  
  
  1.270     +2 -0      httpd-2.0/modules/http/http_core.c
  
  Index: http_core.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/http/http_core.c,v
  retrieving revision 1.269
  retrieving revision 1.270
  diff -u -d -b -w -u -r1.269 -r1.270
  --- http_core.c	2001/03/27 11:47:23	1.269
  +++ http_core.c	2001/04/11 23:37:16	1.270
  @@ -309,6 +309,8 @@
       ap_register_output_filter("HTTP_HEADER", ap_http_header_filter, 
                                 AP_FTYPE_HTTP_HEADER);
       ap_register_output_filter("CHUNK", chunk_filter, AP_FTYPE_TRANSCODE);
  +    ap_register_output_filter("BYTERANGE", ap_byterange_filter,
  +                              AP_FTYPE_HTTP_HEADER);
   }
   
   AP_DECLARE_DATA module http_module = {
  
  
  
  1.312     +388 -0    httpd-2.0/modules/http/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/http/http_protocol.c,v
  retrieving revision 1.311
  retrieving revision 1.312
  diff -u -d -b -w -u -r1.311 -r1.312
  --- http_protocol.c	2001/03/28 10:40:44	1.311
  +++ http_protocol.c	2001/04/11 23:37:16	1.312
  @@ -2032,3 +2032,391 @@
       l->method_list->nelts = 0;
   } 
   
  +/*
  + * Construct an entity tag (ETag) from resource information.  If it's a real
  + * file, build in some of the file characteristics.  If the modification time
  + * is newer than (request-time minus 1 second), mark the ETag as weak - it
  + * could be modified again in as short an interval.  We rationalize the
  + * modification time we're given to keep it from being in the future.
  + */
  +AP_DECLARE(char *) ap_make_etag(request_rec *r, int force_weak)
  +{
  +    char *etag;
  +    char *weak;
  +
  +    /*
  +     * Make an ETag header out of various pieces of information. We use
  +     * the last-modified date and, if we have a real file, the
  +     * length and inode number - note that this doesn't have to match
  +     * the content-length (i.e. includes), it just has to be unique
  +     * for the file.
  +     *
  +     * If the request was made within a second of the last-modified date,
  +     * we send a weak tag instead of a strong one, since it could
  +     * be modified again later in the second, and the validation
  +     * would be incorrect.
  +     */
  +    
  +    weak = ((r->request_time - r->mtime > APR_USEC_PER_SEC)
  +	    && !force_weak) ? "" : "W/";
  +
  +    if (r->finfo.filetype != 0) {
  +        etag = apr_psprintf(r->pool,
  +			    "%s\"%lx-%lx-%lx\"", weak,
  +			    (unsigned long) r->finfo.inode,
  +			    (unsigned long) r->finfo.size,
  +			    (unsigned long) r->mtime);
  +    }
  +    else {
  +        etag = apr_psprintf(r->pool, "%s\"%lx\"", weak,
  +			    (unsigned long) r->mtime);
  +    }
  +
  +    return etag;
  +}
  +
  +AP_DECLARE(void) ap_set_etag(request_rec *r)
  +{
  +    char *etag;
  +    char *variant_etag, *vlv;
  +    int vlv_weak;
  +
  +    if (!r->vlist_validator) {
  +        etag = ap_make_etag(r, 0);
  +    }
  +    else {
  +        /* If we have a variant list validator (vlv) due to the
  +         * response being negotiated, then we create a structured
  +         * entity tag which merges the variant etag with the variant
  +         * list validator (vlv).  This merging makes revalidation
  +         * somewhat safer, ensures that caches which can deal with
  +         * Vary will (eventually) be updated if the set of variants is
  +         * changed, and is also a protocol requirement for transparent
  +         * content negotiation.
  +         */
  +
  +        /* if the variant list validator is weak, we make the whole
  +         * structured etag weak.  If we would not, then clients could
  +         * have problems merging range responses if we have different
  +         * variants with the same non-globally-unique strong etag.
  +         */
  +
  +        vlv = r->vlist_validator;
  +        vlv_weak = (vlv[0] == 'W');
  +               
  +        variant_etag = ap_make_etag(r, vlv_weak);
  +
  +        /* merge variant_etag and vlv into a structured etag */
  +
  +        variant_etag[strlen(variant_etag) - 1] = '\0';
  +        if (vlv_weak)
  +            vlv += 3;
  +        else
  +            vlv++;
  +        etag = apr_pstrcat(r->pool, variant_etag, ";", vlv, NULL);
  +    }
  +
  +    apr_table_setn(r->headers_out, "ETag", etag);
  +}
  +
  +static int parse_byterange(char *range, apr_off_t clength,
  +                           apr_off_t *start, apr_off_t *end)
  +{
  +    char *dash = strchr(range, '-');
  +
  +    if (!dash)
  +        return 0;
  +
  +    if ((dash == range)) {
  +        /* In the form "-5" */
  +        *start = clength - atol(dash + 1);
  +        *end = clength - 1;
  +    }
  +    else {
  +        *dash = '\0';
  +        dash++;
  +        *start = atol(range);
  +        if (*dash)
  +            *end = atol(dash);
  +        else                    /* "5-" */
  +            *end = clength - 1;
  +    }
  +
  +    if (*start < 0)
  +	*start = 0;
  +
  +    if (*end >= clength)
  +        *end = clength - 1;
  +
  +    if (*start > *end)
  +	return -1;
  +
  +    return (*start > 0 || *end < clength);
  +}
  +
  +static int ap_set_byterange(request_rec *r);
  +
  +typedef struct byterange_ctx {
  +    apr_bucket_brigade *bb;
  +    int num_ranges;
  +    const char *orig_ct;
  +} byterange_ctx;
  +
  +/*
  + * Here we try to be compatible with clients that want multipart/x-byteranges
  + * instead of multipart/byteranges (also see above), as per HTTP/1.1. We
  + * look for the Request-Range header (e.g. Netscape 2 and 3) as an indication
  + * that the browser supports an older protocol. We also check User-Agent
  + * for Microsoft Internet Explorer 3, which needs this as well.
  + */
  +static int use_range_x(request_rec *r)
  +{
  +    const char *ua;
  +    return (apr_table_get(r->headers_in, "Request-Range") ||
  +            ((ua = apr_table_get(r->headers_in, "User-Agent"))
  +             && ap_strstr_c(ua, "MSIE 3")));
  +}
  +
  +#define BYTERANGE_FMT "%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT "/%" APR_OFF_T_FMT
  +
  +AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(
  +    ap_filter_t *f,
  +    apr_bucket_brigade *bb)
  +{
  +#define MIN_LENGTH(len1, len2) ((len1 > len2) ? len2 : len1)
  +    request_rec *r = f->r;
  +    byterange_ctx *ctx = f->ctx;
  +    apr_bucket *e;
  +    apr_bucket_brigade *bsend;
  +    apr_off_t range_start;
  +    apr_off_t range_end;
  +    char *current;
  +    char *bound_head;
  +    apr_ssize_t bb_length;
  +    apr_off_t clength = 0;
  +    apr_status_t rv;
  +    int found = 0;
  +
  +    if (!ctx) {
  +        int num_ranges = ap_set_byterange(r);
  + 
  +        if (num_ranges == -1) {
  +            ap_remove_output_filter(f);
  +            bsend = apr_brigade_create(r->pool);
  +            e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL, r->pool);
  +            APR_BRIGADE_INSERT_TAIL(bsend, e);
  +            e = apr_bucket_eos_create();
  +            APR_BRIGADE_INSERT_TAIL(bsend, e);
  +            return ap_pass_brigade(f->next, bsend);
  +        }
  +        if (num_ranges == 0) {
  +            ap_remove_output_filter(f);
  +            return ap_pass_brigade(f->next, bb);
  +        }
  +
  +        ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx));
  +        ctx->num_ranges = num_ranges;
  +
  +        if (num_ranges > 1) {
  +            ctx->orig_ct = r->content_type;
  +            r->content_type = 
  +                 apr_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/",
  +                          "byteranges; boundary=", r->boundary, NULL);
  +        }
  +
  +        /* create a brigade in case we never call ap_save_brigade() */
  +        ctx->bb = apr_brigade_create(r->pool);
  +    }
  +
  +    /* We can't actually deal with byte-ranges until we have the whole brigade
  +     * because the byte-ranges can be in any order, and according to the RFC,
  +     * we SHOULD return the data in the same order it was requested. 
  +     */
  +    if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
  +        ap_save_brigade(f, &ctx->bb, &bb);
  +        return APR_SUCCESS;
  +    }
  +
  +    /* compute this once (it is an invariant) */
  +    bound_head = apr_pstrcat(r->pool,
  +                             CRLF "--", r->boundary,
  +                             CRLF "Content-type: ",
  +                             ap_make_content_type(r, ctx->orig_ct),
  +                             CRLF "Content-range: bytes ", 
  +                             NULL);
  +    ap_xlate_proto_to_ascii(bound_head, strlen(bound_head));
  +
  +    /* If we have a saved brigade from a previous run, concat the passed
  +     * brigade with our saved brigade.  Otherwise just continue.  
  +     */
  +    if (ctx->bb) {
  +        APR_BRIGADE_CONCAT(ctx->bb, bb);
  +        bb = ctx->bb;
  +        ctx->bb = NULL;     /* ### strictly necessary? call brigade_destroy? */
  +    }
  +
  +    /* It is possible that we won't have a content length yet, so we have to
  +     * compute the length before we can actually do the byterange work.
  +     */
  +    (void) apr_brigade_length(bb, 1, &bb_length);
  +    clength = (apr_off_t)bb_length;
  +
  +    /* this brigade holds what we will be sending */
  +    bsend = apr_brigade_create(r->pool);
  +
  +    while ((current = ap_getword(r->pool, &r->range, ',')) &&
  +           (rv = parse_byterange(current, clength, &range_start, &range_end)))
{
  +        apr_bucket *e2;
  +        apr_bucket *ec;
  +
  +        if (rv == -1) {
  +            continue;
  +        }        
  +        else {
  +            found = 1;
  +        }
  +
  +        if (ctx->num_ranges > 1) {
  +            char *ts;
  +
  +            e = apr_bucket_pool_create(bound_head,
  +                                      strlen(bound_head), r->pool);
  +            APR_BRIGADE_INSERT_TAIL(bsend, e);
  +
  +            ts = apr_psprintf(r->pool, BYTERANGE_FMT CRLF CRLF,
  +                              range_start, range_end, clength);
  +            ap_xlate_proto_to_ascii(ts, strlen(ts));
  +            e = apr_bucket_pool_create(ts, strlen(ts), r->pool);
  +            APR_BRIGADE_INSERT_TAIL(bsend, e);
  +        }
  +        
  +        e = apr_brigade_partition(bb, range_start);
  +        e2 = apr_brigade_partition(bb, range_end + 1);
  +        
  +        ec = e;
  +        do {
  +            apr_bucket *foo;
  +            const char *str;
  +            apr_size_t len;
  +
  +            if (apr_bucket_copy(ec, &foo) != APR_SUCCESS) {
  +                apr_bucket_read(ec, &str, &len, APR_BLOCK_READ);
  +                foo = apr_bucket_heap_create(str, len, 0, NULL);
  +            }
  +            APR_BRIGADE_INSERT_TAIL(bsend, foo);
  +            ec = APR_BUCKET_NEXT(ec);
  +        } while (ec != e2);
  +    }
  +
  +    if (found == 0) {
  +        ap_remove_output_filter(f);
  +        r->status = HTTP_OK;
  +        return HTTP_RANGE_NOT_SATISFIABLE;
  +    }
  +
  +    if (ctx->num_ranges > 1) {
  +        char *end;
  +
  +        /* add the final boundary */
  +        end = apr_pstrcat(r->pool, CRLF "--", r->boundary, "--" CRLF, NULL);
  +        ap_xlate_proto_to_ascii(end, strlen(end));
  +        e = apr_bucket_pool_create(end, strlen(end), r->pool);
  +        APR_BRIGADE_INSERT_TAIL(bsend, e);
  +    }
  +
  +    e = apr_bucket_eos_create();
  +    APR_BRIGADE_INSERT_TAIL(bsend, e);
  +
  +    /* we're done with the original content */
  +    apr_brigade_destroy(bb);
  +
  +    /* send our multipart output */
  +    return ap_pass_brigade(f->next, bsend); 
  +}    
  +
  +static int ap_set_byterange(request_rec *r)
  +{
  +    const char *range;
  +    const char *if_range;
  +    const char *match;
  +    const char *ct;
  +    apr_off_t range_start;
  +    apr_off_t range_end;
  +    int num_ranges;
  +
  +    if (r->assbackwards)
  +        return 0;
  +
  +    /* Check for Range request-header (HTTP/1.1) or Request-Range for
  +     * backwards-compatibility with second-draft Luotonen/Franks
  +     * byte-ranges (e.g. Netscape Navigator 2-3).
  +     *
  +     * We support this form, with Request-Range, and (farther down) we
  +     * send multipart/x-byteranges instead of multipart/byteranges for
  +     * Request-Range based requests to work around a bug in Netscape
  +     * Navigator 2-3 and MSIE 3.
  +     */
  +
  +    if (!(range = apr_table_get(r->headers_in, "Range")))
  +        range = apr_table_get(r->headers_in, "Request-Range");
  +
  +    if (!range || strncasecmp(range, "bytes=", 6)) {
  +        return 0;
  +    }
  +
  +    /* Check the If-Range header for Etag or Date.
  +     * Note that this check will return false (as required) if either
  +     * of the two etags are weak.
  +     */
  +    if ((if_range = apr_table_get(r->headers_in, "If-Range"))) {
  +        if (if_range[0] == '"') {
  +            if (!(match = apr_table_get(r->headers_out, "Etag")) ||
  +                (strcmp(if_range, match) != 0))
  +                return 0;
  +        }
  +        else if (!(match = apr_table_get(r->headers_out, "Last-Modified")) ||
  +                 (strcmp(if_range, match) != 0))
  +            return 0;
  +    }
  +
  +    /* would be nice to pick this up from f->ctx */
  +    ct = ap_make_content_type(r, r->content_type);
  +
  +    if (!ap_strchr_c(range, ',')) {
  +        int rv;
  +        /* A single range */
  +
  +        /* rvarse_byterange() modifies the contents, so make a copy */
  +        if ((rv = parse_byterange(apr_pstrdup(r->pool, range + 6), r->clength,
  +                             &range_start, &range_end)) <= 0) {
  +            return rv;
  +        }
  +        apr_table_setn(r->headers_out, "Content-Range",
  +                       apr_psprintf(r->pool, "bytes " BYTERANGE_FMT,
  +                                    range_start, range_end, r->clength));
  +	apr_table_setn(r->headers_out, "Content-Type", ct);
  +
  +        num_ranges = 1;
  +    }
  +    else {
  +        /* a multiple range */
  +
  +        num_ranges = 2;
  +
  +        /* ### it would be nice if r->boundary was in f->ctx */
  +        r->boundary = apr_psprintf(r->pool, "%qx%lx",
  +                                   r->request_time, (long) getpid());
  +
  +        apr_table_setn(r->headers_out, "Content-Type",
  +		       apr_pstrcat(r->pool,
  +                                   "multipart", use_range_x(r) ? "/x-" : "/",
  +				   "byteranges; boundary=", r->boundary,
  +                                   NULL));
  +    }
  +
  +    r->status = HTTP_PARTIAL_CONTENT;
  +    r->range = range + 6;
  +
  +    return num_ranges;
  +}
  +
  
  
  
  1.8       +0 -2      httpd-2.0/server/core.c
  
  Index: core.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/core.c,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -d -b -w -u -r1.7 -r1.8
  --- core.c	2001/04/04 21:41:52	1.7
  +++ core.c	2001/04/11 23:37:16	1.8
  @@ -3284,8 +3284,6 @@
       ap_register_input_filter("CORE_IN", core_input_filter, AP_FTYPE_NETWORK);
       ap_register_output_filter("CONTENT_LENGTH", ap_content_length_filter, 
                                 AP_FTYPE_HTTP_HEADER);
  -    ap_register_output_filter("BYTERANGE", ap_byterange_filter, 
  -                              AP_FTYPE_HTTP_HEADER);
       ap_register_output_filter("CORE", core_output_filter, AP_FTYPE_NETWORK);
       ap_register_output_filter("SUBREQ_CORE", ap_sub_req_output_filter, 
                                 AP_FTYPE_CONTENT);
  
  
  
  1.12      +0 -388    httpd-2.0/server/protocol.c
  
  Index: protocol.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/protocol.c,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -d -b -w -u -r1.11 -r1.12
  --- protocol.c	2001/03/25 20:42:47	1.11
  +++ protocol.c	2001/04/11 23:37:16	1.12
  @@ -151,221 +151,6 @@
       return type;
   }
   
  -static int parse_byterange(char *range, apr_off_t clength,
  -                           apr_off_t *start, apr_off_t *end)
  -{
  -    char *dash = strchr(range, '-');
  -
  -    if (!dash)
  -        return 0;
  -
  -    if ((dash == range)) {
  -        /* In the form "-5" */
  -        *start = clength - atol(dash + 1);
  -        *end = clength - 1;
  -    }
  -    else {
  -        *dash = '\0';
  -        dash++;
  -        *start = atol(range);
  -        if (*dash)
  -            *end = atol(dash);
  -        else                    /* "5-" */
  -            *end = clength - 1;
  -    }
  -
  -    if (*start < 0)
  -	*start = 0;
  -
  -    if (*end >= clength)
  -        *end = clength - 1;
  -
  -    if (*start > *end)
  -	return -1;
  -
  -    return (*start > 0 || *end < clength);
  -}
  -
  -static int ap_set_byterange(request_rec *r);
  -
  -typedef struct byterange_ctx {
  -    apr_bucket_brigade *bb;
  -    int num_ranges;
  -    const char *orig_ct;
  -} byterange_ctx;
  -
  -/*
  - * Here we try to be compatible with clients that want multipart/x-byteranges
  - * instead of multipart/byteranges (also see above), as per HTTP/1.1. We
  - * look for the Request-Range header (e.g. Netscape 2 and 3) as an indication
  - * that the browser supports an older protocol. We also check User-Agent
  - * for Microsoft Internet Explorer 3, which needs this as well.
  - */
  -static int use_range_x(request_rec *r)
  -{
  -    const char *ua;
  -    return (apr_table_get(r->headers_in, "Request-Range") ||
  -            ((ua = apr_table_get(r->headers_in, "User-Agent"))
  -             && ap_strstr_c(ua, "MSIE 3")));
  -}
  -
  -#define BYTERANGE_FMT "%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT "/%" APR_OFF_T_FMT
  -
  -AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(
  -    ap_filter_t *f,
  -    apr_bucket_brigade *bb)
  -{
  -#define MIN_LENGTH(len1, len2) ((len1 > len2) ? len2 : len1)
  -    request_rec *r = f->r;
  -    byterange_ctx *ctx = f->ctx;
  -    apr_bucket *e;
  -    apr_bucket_brigade *bsend;
  -    apr_off_t range_start;
  -    apr_off_t range_end;
  -    char *current;
  -    char *bound_head;
  -    apr_ssize_t bb_length;
  -    apr_off_t clength = 0;
  -    apr_status_t rv;
  -    int found = 0;
  -
  -    if (!ctx) {
  -        int num_ranges = ap_set_byterange(r);
  - 
  -        if (num_ranges == -1) {
  -            ap_remove_output_filter(f);
  -            bsend = apr_brigade_create(r->pool);
  -            e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL, r->pool);
  -            APR_BRIGADE_INSERT_TAIL(bsend, e);
  -            e = apr_bucket_eos_create();
  -            APR_BRIGADE_INSERT_TAIL(bsend, e);
  -            return ap_pass_brigade(f->next, bsend);
  -        }
  -        if (num_ranges == 0) {
  -            ap_remove_output_filter(f);
  -            return ap_pass_brigade(f->next, bb);
  -        }
  -
  -        ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx));
  -        ctx->num_ranges = num_ranges;
  -
  -        if (num_ranges > 1) {
  -            ctx->orig_ct = r->content_type;
  -            r->content_type = 
  -                 apr_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/",
  -                          "byteranges; boundary=", r->boundary, NULL);
  -        }
  -
  -        /* create a brigade in case we never call ap_save_brigade() */
  -        ctx->bb = apr_brigade_create(r->pool);
  -    }
  -
  -    /* We can't actually deal with byte-ranges until we have the whole brigade
  -     * because the byte-ranges can be in any order, and according to the RFC,
  -     * we SHOULD return the data in the same order it was requested. 
  -     */
  -    if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
  -        ap_save_brigade(f, &ctx->bb, &bb);
  -        return APR_SUCCESS;
  -    }
  -
  -    /* compute this once (it is an invariant) */
  -    bound_head = apr_pstrcat(r->pool,
  -                             CRLF "--", r->boundary,
  -                             CRLF "Content-type: ",
  -                             ap_make_content_type(r, ctx->orig_ct),
  -                             CRLF "Content-range: bytes ", 
  -                             NULL);
  -    ap_xlate_proto_to_ascii(bound_head, strlen(bound_head));
  -
  -    /* If we have a saved brigade from a previous run, concat the passed
  -     * brigade with our saved brigade.  Otherwise just continue.  
  -     */
  -    if (ctx->bb) {
  -        APR_BRIGADE_CONCAT(ctx->bb, bb);
  -        bb = ctx->bb;
  -        ctx->bb = NULL;     /* ### strictly necessary? call brigade_destroy? */
  -    }
  -
  -    /* It is possible that we won't have a content length yet, so we have to
  -     * compute the length before we can actually do the byterange work.
  -     */
  -    (void) apr_brigade_length(bb, 1, &bb_length);
  -    clength = (apr_off_t)bb_length;
  -
  -    /* this brigade holds what we will be sending */
  -    bsend = apr_brigade_create(r->pool);
  -
  -    while ((current = ap_getword(r->pool, &r->range, ',')) &&
  -           (rv = parse_byterange(current, clength, &range_start, &range_end)))
{
  -        apr_bucket *e2;
  -        apr_bucket *ec;
  -
  -        if (rv == -1) {
  -            continue;
  -        }        
  -        else {
  -            found = 1;
  -        }
  -
  -        if (ctx->num_ranges > 1) {
  -            char *ts;
  -
  -            e = apr_bucket_pool_create(bound_head,
  -                                      strlen(bound_head), r->pool);
  -            APR_BRIGADE_INSERT_TAIL(bsend, e);
  -
  -            ts = apr_psprintf(r->pool, BYTERANGE_FMT CRLF CRLF,
  -                              range_start, range_end, clength);
  -            ap_xlate_proto_to_ascii(ts, strlen(ts));
  -            e = apr_bucket_pool_create(ts, strlen(ts), r->pool);
  -            APR_BRIGADE_INSERT_TAIL(bsend, e);
  -        }
  -        
  -        e = apr_brigade_partition(bb, range_start);
  -        e2 = apr_brigade_partition(bb, range_end + 1);
  -        
  -        ec = e;
  -        do {
  -            apr_bucket *foo;
  -            const char *str;
  -            apr_size_t len;
  -
  -            if (apr_bucket_copy(ec, &foo) != APR_SUCCESS) {
  -                apr_bucket_read(ec, &str, &len, APR_BLOCK_READ);
  -                foo = apr_bucket_heap_create(str, len, 0, NULL);
  -            }
  -            APR_BRIGADE_INSERT_TAIL(bsend, foo);
  -            ec = APR_BUCKET_NEXT(ec);
  -        } while (ec != e2);
  -    }
  -
  -    if (found == 0) {
  -        ap_remove_output_filter(f);
  -        r->status = HTTP_OK;
  -        return HTTP_RANGE_NOT_SATISFIABLE;
  -    }
  -
  -    if (ctx->num_ranges > 1) {
  -        char *end;
  -
  -        /* add the final boundary */
  -        end = apr_pstrcat(r->pool, CRLF "--", r->boundary, "--" CRLF, NULL);
  -        ap_xlate_proto_to_ascii(end, strlen(end));
  -        e = apr_bucket_pool_create(end, strlen(end), r->pool);
  -        APR_BRIGADE_INSERT_TAIL(bsend, e);
  -    }
  -
  -    e = apr_bucket_eos_create();
  -    APR_BRIGADE_INSERT_TAIL(bsend, e);
  -
  -    /* we're done with the original content */
  -    apr_brigade_destroy(bb);
  -
  -    /* send our multipart output */
  -    return ap_pass_brigade(f->next, bsend); 
  -}    
  -
   AP_DECLARE(void) ap_set_content_length(request_rec *r, apr_off_t clength)
   {
       r->clength = clength;
  @@ -397,93 +182,6 @@
       return (mtime > now) ? now : mtime;
   }
   
  -/*
  - * Construct an entity tag (ETag) from resource information.  If it's a real
  - * file, build in some of the file characteristics.  If the modification time
  - * is newer than (request-time minus 1 second), mark the ETag as weak - it
  - * could be modified again in as short an interval.  We rationalize the
  - * modification time we're given to keep it from being in the future.
  - */
  -AP_DECLARE(char *) ap_make_etag(request_rec *r, int force_weak)
  -{
  -    char *etag;
  -    char *weak;
  -
  -    /*
  -     * Make an ETag header out of various pieces of information. We use
  -     * the last-modified date and, if we have a real file, the
  -     * length and inode number - note that this doesn't have to match
  -     * the content-length (i.e. includes), it just has to be unique
  -     * for the file.
  -     *
  -     * If the request was made within a second of the last-modified date,
  -     * we send a weak tag instead of a strong one, since it could
  -     * be modified again later in the second, and the validation
  -     * would be incorrect.
  -     */
  -    
  -    weak = ((r->request_time - r->mtime > APR_USEC_PER_SEC)
  -	    && !force_weak) ? "" : "W/";
  -
  -    if (r->finfo.filetype != 0) {
  -        etag = apr_psprintf(r->pool,
  -			    "%s\"%lx-%lx-%lx\"", weak,
  -			    (unsigned long) r->finfo.inode,
  -			    (unsigned long) r->finfo.size,
  -			    (unsigned long) r->mtime);
  -    }
  -    else {
  -        etag = apr_psprintf(r->pool, "%s\"%lx\"", weak,
  -			    (unsigned long) r->mtime);
  -    }
  -
  -    return etag;
  -}
  -
  -AP_DECLARE(void) ap_set_etag(request_rec *r)
  -{
  -    char *etag;
  -    char *variant_etag, *vlv;
  -    int vlv_weak;
  -
  -    if (!r->vlist_validator) {
  -        etag = ap_make_etag(r, 0);
  -    }
  -    else {
  -        /* If we have a variant list validator (vlv) due to the
  -         * response being negotiated, then we create a structured
  -         * entity tag which merges the variant etag with the variant
  -         * list validator (vlv).  This merging makes revalidation
  -         * somewhat safer, ensures that caches which can deal with
  -         * Vary will (eventually) be updated if the set of variants is
  -         * changed, and is also a protocol requirement for transparent
  -         * content negotiation.
  -         */
  -
  -        /* if the variant list validator is weak, we make the whole
  -         * structured etag weak.  If we would not, then clients could
  -         * have problems merging range responses if we have different
  -         * variants with the same non-globally-unique strong etag.
  -         */
  -
  -        vlv = r->vlist_validator;
  -        vlv_weak = (vlv[0] == 'W');
  -               
  -        variant_etag = ap_make_etag(r, vlv_weak);
  -
  -        /* merge variant_etag and vlv into a structured etag */
  -
  -        variant_etag[strlen(variant_etag) - 1] = '\0';
  -        if (vlv_weak)
  -            vlv += 3;
  -        else
  -            vlv++;
  -        etag = apr_pstrcat(r->pool, variant_etag, ";", vlv, NULL);
  -    }
  -
  -    apr_table_setn(r->headers_out, "ETag", etag);
  -}
  -
   /* Get a line of protocol input, including any continuation lines
    * caused by MIME folding (or broken clients) if fold != 0, and place it
    * in the buffer s, of size n bytes, without the ending newline.
  @@ -1233,92 +931,6 @@
   
       ctx->curr_len = 0;
       return ap_pass_brigade(f->next, b);
  -}
  -
  -static int ap_set_byterange(request_rec *r)
  -{
  -    const char *range;
  -    const char *if_range;
  -    const char *match;
  -    const char *ct;
  -    apr_off_t range_start;
  -    apr_off_t range_end;
  -    int num_ranges;
  -
  -    if (r->assbackwards)
  -        return 0;
  -
  -    /* Check for Range request-header (HTTP/1.1) or Request-Range for
  -     * backwards-compatibility with second-draft Luotonen/Franks
  -     * byte-ranges (e.g. Netscape Navigator 2-3).
  -     *
  -     * We support this form, with Request-Range, and (farther down) we
  -     * send multipart/x-byteranges instead of multipart/byteranges for
  -     * Request-Range based requests to work around a bug in Netscape
  -     * Navigator 2-3 and MSIE 3.
  -     */
  -
  -    if (!(range = apr_table_get(r->headers_in, "Range")))
  -        range = apr_table_get(r->headers_in, "Request-Range");
  -
  -    if (!range || strncasecmp(range, "bytes=", 6)) {
  -        return 0;
  -    }
  -
  -    /* Check the If-Range header for Etag or Date.
  -     * Note that this check will return false (as required) if either
  -     * of the two etags are weak.
  -     */
  -    if ((if_range = apr_table_get(r->headers_in, "If-Range"))) {
  -        if (if_range[0] == '"') {
  -            if (!(match = apr_table_get(r->headers_out, "Etag")) ||
  -                (strcmp(if_range, match) != 0))
  -                return 0;
  -        }
  -        else if (!(match = apr_table_get(r->headers_out, "Last-Modified")) ||
  -                 (strcmp(if_range, match) != 0))
  -            return 0;
  -    }
  -
  -    /* would be nice to pick this up from f->ctx */
  -    ct = ap_make_content_type(r, r->content_type);
  -
  -    if (!ap_strchr_c(range, ',')) {
  -        int rv;
  -        /* A single range */
  -
  -        /* rvarse_byterange() modifies the contents, so make a copy */
  -        if ((rv = parse_byterange(apr_pstrdup(r->pool, range + 6), r->clength,
  -                             &range_start, &range_end)) <= 0) {
  -            return rv;
  -        }
  -        apr_table_setn(r->headers_out, "Content-Range",
  -                       apr_psprintf(r->pool, "bytes " BYTERANGE_FMT,
  -                                    range_start, range_end, r->clength));
  -	apr_table_setn(r->headers_out, "Content-Type", ct);
  -
  -        num_ranges = 1;
  -    }
  -    else {
  -        /* a multiple range */
  -
  -        num_ranges = 2;
  -
  -        /* ### it would be nice if r->boundary was in f->ctx */
  -        r->boundary = apr_psprintf(r->pool, "%qx%lx",
  -                                   r->request_time, (long) getpid());
  -
  -        apr_table_setn(r->headers_out, "Content-Type",
  -		       apr_pstrcat(r->pool,
  -                                   "multipart", use_range_x(r) ? "/x-" : "/",
  -				   "byteranges; boundary=", r->boundary,
  -                                   NULL));
  -    }
  -
  -    r->status = HTTP_PARTIAL_CONTENT;
  -    r->range = range + 6;
  -
  -    return num_ranges;
   }
   
   /*
  
  
  

Mime
View raw message