public bool SendFileToBrowser(string localFilePath, bool remapToSkin, bool sendChunked, bool makeDownloadable) { // File location if (remapToSkin) { localFilePath = localFilePath.Replace("skin/", ""); while (localFilePath.StartsWith("/")) { localFilePath = localFilePath.Substring(1); } localFilePath = localFilePath.Replace("/", "\\"); localFilePath = Path.Combine(Themes.ActiveThemeFolder, localFilePath); } // Read file (this MAY remap a relative path to an absolute path, so don't check if file exists ahead of this) byte[] bytes = FileCache.ReadBinaryFile(localFilePath); if (bytes.Length == 0) { if (Settings.Default.DebugAdvanced) { Functions.WriteLineToLogFile("SendFileToBrowser: File doesn't exist: " + localFilePath); } return(Send404Page()); } // Get mime type wipeHeader(); addToHeaderMimeType(Functions.MimeTypeForFileName(localFilePath)); // Trim to any range request if (Request.Headers.HasParameter("Range")) { if ((Settings.Default.DebugServer) && (Settings.Default.DebugAdvanced)) { Functions.WriteLineToLogFile("Sending byte range.."); } bool shouldReturnContentRange = true; bytes = TrimBytesToRange(bytes, ref shouldReturnContentRange); if (!shouldReturnContentRange) // in case it wasn't syntactically correct, return normal file (RFC 2616) { Response.StatusCode = 200; } } else { // Send header Response.StatusCode = 200; } // Downloadable? if (makeDownloadable) { string dlFilename = Path.GetFileName(localFilePath); addToHeader("content-disposition", "attachment; filename=" + HttpUtility.UrlEncode(dlFilename)); } // Send bytes return(SendToBrowser(bytes, true)); }