const char *range, *if_range, *match; char *bbuf, *b; u_int32_t rbuf[12];  long length, start, end, one_start = 0, one_end = 0; size_t u; int ranges, empty;
AP_SHA1_CTX hashCtx; core_dir_config *cfg; etag_components_t etag_bits; int weak; unsigned char md[SHA_DIGESTSIZE]; unsigned int i;
API_EXPORT(int) ap_set_byterange(request_rec *r){    const char *range, *if_range, *match;    char *bbuf, *b;    u_int32_t rbuf[12]; /* 48 bytes yields 64 base64 chars */    long length, start, end, one_start = 0, one_end = 0;    size_t u;    int ranges, empty;        if (!r->clength || 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 = ap_table_get(r->headers_in, "Range")))        range = ap_table_get(r->headers_in, "Request-Range");    if (!range || strncasecmp(range, "bytes=", 6)) {        return 0;    }    range += 6;    /* 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 = ap_table_get(r->headers_in, "If-Range"))) {        if (if_range[0] == '"') {            if (!(match = ap_table_get(r->headers_out, "Etag")) ||                (strcmp(if_range, match) != 0))                return 0;        }        else if (!(match = ap_table_get(r->headers_out, "Last-Modified")) ||                 (strcmp(if_range, match) != 0))            return 0;    }    /*     * Parse the byteranges, counting how many of them there are and     * the total number of bytes we will send to the client. This is a     * dummy run for the while(ap_each_byterange()) loop that the     * caller will perform if we return 1.     */    r->range = range;    for (u = 0; u < sizeof(rbuf)/sizeof(rbuf[0]); u++)        rbuf[u] = htonl(arc4random());    bbuf = ap_palloc(r->pool, ap_base64encode_len(sizeof(rbuf)));    ap_base64encode(bbuf, (const unsigned char *)rbuf, sizeof(rbuf));    for (b = bbuf; *b != '\0'; b++) {        if (((b - bbuf) + 1) % 7 == 0)            *b = '-';        else if (!isalnum(*b))            *b = 'a';    }    r->boundary = bbuf;    length = 0;    ranges = 0;    empty = 1;    do {	switch (parse_byterange(r, &start, &end)) {	case BYTERANGE_UNSATISFIABLE:	    empty = 0;	    break;	default:	    /* be more defensive here? */	case BYTERANGE_BADSYNTAX:	    r->boundary = NULL;	    r->range = NULL;	    return 0;	case BYTERANGE_EMPTY:	    break;	case BYTERANGE_OK:	    ++ranges;	    length += byterange_boundary(r, start, end, 0)		+ end - start + 1;	    /* save in case of unsatisfiable ranges */	    one_start = start;	    one_end = end;	    break;	}    } while (*r->range != '\0');    if (ranges == 0) {	/* no ranges or only unsatisfiable ranges */	if (empty || if_range) {	    r->boundary = NULL;	    r->range = NULL;	    return 0;	}	else {	    ap_table_setn(r->headers_out, "Content-Range",		ap_psprintf(r->pool, "bytes */%ld", r->clength));	    ap_set_content_length(r, 0);			  	    r->boundary = NULL;	    r->range = range;	    r->header_only = 1;	    r->status = HTTP_RANGE_NOT_SATISFIABLE;	    return 1;	}    }    else if (ranges == 1) {	/* simple handling of a single range -- no boundaries */        ap_table_setn(r->headers_out, "Content-Range",	    ap_psprintf(r->pool, "bytes %ld-%ld/%ld",		one_start, one_end, r->clength));	ap_table_setn(r->headers_out, "Content-Length",	    ap_psprintf(r->pool, "%ld", one_end - one_start + 1));	r->boundary = NULL;	r->byterange = 1;	r->range = range;	r->status = PARTIAL_CONTENT;	return 1;    }    else {	/* multiple ranges */	length += byterange_boundary(r, -1, -1, 0);	ap_table_setn(r->headers_out, "Content-Length",	    ap_psprintf(r->pool, "%ld", length));	r->byterange = 2;	r->range = range;	r->status = PARTIAL_CONTENT;	return 1;    }}