internal static void ProcessRequestInternal(HttpContext context, string pathOverride)
        {
            HttpRequest  request  = context.Request;
            HttpResponse response = context.Response;
            string       virtualPathWithPathInfo;
            string       physicalPath;
            FileInfo     fileInfo;
            long         fileLength;
            DateTime     lastModifiedInUtc;
            string       etag;
            string       rangeHeader;

            // custom virtual path providers that don't yeild a MapPathBasedVirtualFile
            // are a special case, and do not support TransmitFile, WriteFile, Range requests,
            // or the cache policy that we apply below

            /*
             * if (ProcessRequestForNonMapPathBasedVirtualFile(request, response, overrideVirtualPath)) {
             *  return;
             * }
             *
             * if (overrideVirtualPath == null)
             * {
             *  virtualPathWithPathInfo = request.Path;
             *  physicalPath = request.PhysicalPath;
             * }
             * else {
             *  virtualPathWithPathInfo = overrideVirtualPath;
             *  physicalPath = request.MapPath(overrideVirtualPath);
             * }
             */

            if (pathOverride != null)
            {
                physicalPath = pathOverride;
            }
            else
            {
                physicalPath = context.Request.PhysicalPath;
            }

            // Debug.Trace("StaticFileHandler", "Path= " + virtualPathWithPathInfo + ", PhysicalPath= " + physicalPath);

            try
            {
                fileInfo = GetFileInfo(physicalPath);
            }
            catch (HttpException hex)
            {
                int    httpCode  = hex.GetHttpCode();
                string httpError = String.Format("{0} ({1})", hex.Message, physicalPath);
                throw new HttpException(httpCode, httpError, hex);
            }

            // Determine Last Modified Time.  We might need it soon
            // if we encounter a Range: and If-Range header
            // Using UTC time to avoid daylight savings time bug 83230
            lastModifiedInUtc = new DateTime(fileInfo.LastWriteTimeUtc.Year,
                                             fileInfo.LastWriteTimeUtc.Month,
                                             fileInfo.LastWriteTimeUtc.Day,
                                             fileInfo.LastWriteTimeUtc.Hour,
                                             fileInfo.LastWriteTimeUtc.Minute,
                                             fileInfo.LastWriteTimeUtc.Second,
                                             0,
                                             DateTimeKind.Utc);

            // Because we can't set a "Last-Modified" header to any time
            // in the future, check the last modified time and set it to
            // DateTime.Now if it's in the future.
            // This is to fix VSWhidbey #402323
            DateTime utcNow = DateTime.UtcNow;

            if (lastModifiedInUtc > utcNow)
            {
                // use 1 second resolution
                lastModifiedInUtc = new DateTime(utcNow.Ticks - (utcNow.Ticks % TimeSpan.TicksPerSecond), DateTimeKind.Utc);
            }

            etag       = GenerateETag(lastModifiedInUtc, utcNow);
            fileLength = fileInfo.Length;

            // is this a Range request?
            rangeHeader = request.Headers["Range"];
            if (rangeHeader != null && rangeHeader.StartsWith("bytes", StringComparison.OrdinalIgnoreCase) &&
                ProcessRangeRequest(context, physicalPath, fileLength, rangeHeader, etag, lastModifiedInUtc))
            {
                return;
            }

            // if we get this far, we're sending the entire file
            SendFile(physicalPath, 0, fileLength, fileLength, context);

            // Specify content type. Use extension to do the mapping
            response.ContentType = MimeMapping.GetMapping(physicalPath);
            // Static file handler supports byte ranges
            response.AppendHeader("Accept-Ranges", "bytes");
            // We want to flush cache entry when static file has changed
            response.AddFileDependency(physicalPath);

            /*
             * NOTE: This was the code originally in the handler:
             * // Set an expires in the future.
             * response.Cache.SetExpires(utcNow.AddMinutes(5));
             * // always set Last-Modified
             * response.Cache.SetLastModified(lastModifiedInUtc);
             * // always set ETag
             * response.Cache.SetETag(etag);
             * // always set Cache-Control to public
             * response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate);
             */

            // set cache headers
            HttpCachePolicy cachePolicy = response.Cache;

            SetCachingPolicy(cachePolicy);

            // set cache file info
            cachePolicy.SetETag(etag);
            cachePolicy.SetLastModified(lastModifiedInUtc);
        }
        internal static bool ProcessRangeRequest(HttpContext context,
                                                 string physicalPath,
                                                 long fileLength,
                                                 string rangeHeader,
                                                 string etag,
                                                 DateTime lastModified)
        {
            HttpRequest  request  = context.Request;
            HttpResponse response = context.Response;
            bool         handled  = false;

            // return "416 Requested range not satisfiable" if the file length is zero.
            if (fileLength <= 0)
            {
                SendRangeNotSatisfiable(response, fileLength);
                handled = true;
                return(handled);
            }

            string ifRangeHeader = request.Headers["If-Range"];

            if (ifRangeHeader != null && ifRangeHeader.Length > 1)
            {
                // Is this an ETag or a Date? We only need to check two
                // characters; an ETag either begins with W/ or it is quoted.
                if (ifRangeHeader[0] == '"')
                {
                    // it's a strong ETag
                    if (ifRangeHeader != etag)
                    {
                        // the etags do not match, and we will therefore return the entire response
                        return(handled);
                    }
                }
                else if (ifRangeHeader[0] == 'W' && ifRangeHeader[1] == '/')
                {
                    // it's a weak ETag, and is therefore not usable for sub-range retrieval and
                    // we will return the entire response
                    return(handled);
                }
                else
                {
                    // It's a date. If it is greater than or equal to the last-write time of the file, we can send the range.
                    if (IsOutDated(ifRangeHeader, lastModified))
                    {
                        return(handled);
                    }
                }
            }

            // the expected format is "bytes = <range1>[, <range2>, ...]"
            // where <range> is "<first_byte_pos>-[<last_byte_pos>]" or "-<last_n_bytes>".
            int indexOfEquals = rangeHeader.IndexOf('=');

            if (indexOfEquals == -1 || indexOfEquals == rangeHeader.Length - 1)
            {
                //invalid syntax
                return(handled);
            }

            // iterate through the byte ranges and write each satisfiable range to the response
            int  startIndex = indexOfEquals + 1;
            bool isRangeHeaderSyntacticallyValid = true;
            long offset;
            long length;
            bool isSatisfiable;
            bool exceededMax = false;

            ByteRange[] byteRanges      = null;
            int         byteRangesCount = 0;
            long        totalBytes      = 0;

            while (startIndex < rangeHeader.Length && isRangeHeaderSyntacticallyValid)
            {
                isRangeHeaderSyntacticallyValid = GetNextRange(rangeHeader, ref startIndex, fileLength, out offset, out length, out isSatisfiable);
                if (!isRangeHeaderSyntacticallyValid)
                {
                    break;
                }
                if (!isSatisfiable)
                {
                    continue;
                }
                if (byteRanges == null)
                {
                    byteRanges = new ByteRange[16];
                }
                if (byteRangesCount >= byteRanges.Length)
                {
                    // grow byteRanges array
                    ByteRange[] buffer    = new ByteRange[byteRanges.Length * 2];
                    int         byteCount = byteRanges.Length * Marshal.SizeOf(byteRanges[0]);

                    Buffer.BlockCopy(byteRanges, 0, buffer, 0, byteCount);

                    /*unsafe {
                     *  fixed (ByteRange * src = byteRanges, dst = buffer) {
                     *      StringUtil.memcpyimpl((byte*)src, (byte*)dst, byteCount);
                     *  }
                     * }
                     */

                    byteRanges = buffer;
                }
                byteRanges[byteRangesCount].Offset = offset;
                byteRanges[byteRangesCount].Length = length;
                byteRangesCount++;
                // IIS imposes this limitation too, and sends "400 Bad Request" if exceeded
                totalBytes += length;
                if (totalBytes > fileLength * MAX_RANGE_ALLOWED)
                {
                    exceededMax = true;
                    break;
                }
            }

            if (!isRangeHeaderSyntacticallyValid)
            {
                return(handled);
            }

            if (exceededMax)
            {
                SendBadRequest(response);
                handled = true;
                return(handled);
            }

            if (byteRangesCount == 0)
            {
                // we parsed the Range header and found no satisfiable byte ranges, so return "416 Requested Range Not Satisfiable"
                SendRangeNotSatisfiable(response, fileLength);
                handled = true;
                return(handled);
            }

            string contentType = MimeMapping.GetMapping(physicalPath);

            if (byteRangesCount == 1)
            {
                offset = byteRanges[0].Offset;
                length = byteRanges[0].Length;
                response.ContentType = contentType;
                string contentRange = String.Format(CultureInfo.InvariantCulture, CONTENT_RANGE_FORMAT, offset, offset + length - 1, fileLength);
                response.AppendHeader("Content-Range", contentRange);

                SendFile(physicalPath, offset, length, fileLength, context);
            }
            else
            {
                response.ContentType = MULTIPART_CONTENT_TYPE;
                string contentRange;
                string partialContentType = "Content-Type: " + contentType + "\r\n";
                for (int i = 0; i < byteRangesCount; i++)
                {
                    offset = byteRanges[i].Offset;
                    length = byteRanges[i].Length;
                    response.Write(MULTIPART_RANGE_DELIMITER);
                    response.Write(partialContentType);
                    response.Write("Content-Range: ");
                    contentRange = String.Format(CultureInfo.InvariantCulture, CONTENT_RANGE_FORMAT, offset, offset + length - 1, fileLength);
                    response.Write(contentRange);
                    response.Write("\r\n\r\n");
                    SendFile(physicalPath, offset, length, fileLength, context);
                    response.Write("\r\n");
                }
                response.Write(MULTIPART_RANGE_END);
            }

            // if we make it here, we're sending a "206 Partial Content" status
            response.StatusCode = 206;
            response.AppendHeader("Last-Modified", FormatHttpDateTime(lastModified));
            response.AppendHeader("Accept-Ranges", "bytes");
            response.AppendHeader("ETag", etag);
            response.AppendHeader("Cache-Control", "private");

            handled = true;
            return(handled);
        }