using System; using System.Collections.Specialized; using System.Globalization; using System.IO; using System.Security; using System.Web; using System.Web.Caching; using System.Xml; using System.Data; namespace Common.Handlers { /// /// Poskytuje statické soubory uložené v configuracním souboru. /// public class StaticFileHandler: IHttpHandler { private static StringDictionary _contentTypes; public static string _resourceFileName = "staticFiles.config"; static StaticFileHandler() { _contentTypes = new StringDictionary(); _contentTypes.Add("css", "text/css"); _contentTypes.Add("js", "text/javascript"); _contentTypes.Add("txt", "text/plain"); _contentTypes.Add("cs", "text/plain"); _contentTypes.Add("htm", "text/html"); _contentTypes.Add("html","text/html"); _contentTypes.Add("xml", "text/xml"); _contentTypes.Add("gif", "image/gif"); _contentTypes.Add("jpeg","image/jpeg"); _contentTypes.Add("jpg", "image/jpeg"); _contentTypes.Add("png", "image/png"); _contentTypes.Add("pdf", "application/pdf"); _contentTypes.Add("rtf", "application/msword"); _contentTypes.Add("doc", "application/msword"); _contentTypes.Add("xls", "application/vnd.ms-excel"); _contentTypes.Add("csv", "application/vnd.ms-excel"); _contentTypes.Add("ppt", "application/vnd.ms-powerpoint"); } public StaticFileHandler() { } #region IHttpHandler Members /// /// Metoda poskytující výstup statického souboru /// /// aktuální context public void ProcessRequest(HttpContext context) { string key = context.Request.QueryString["name"] as string; if ((key == null) || (key.Length == 0)) throw new HttpException(404, "Resource not found"); bool useName; FileInfo fi = getStaticFile(context, key, out useName); if (FileIsNotModifiedSince(fi.LastWriteTime.ToUniversalTime(), context.Request)) { context.Response.StatusCode = 304; context.Response.SuppressContent = true; return; } context.Response.ContentType = getMimeMapping(fi.FullName); context.Response.AppendHeader("Content-Length", fi.Length.ToString()); if (useName) context.Response.AppendHeader("Content-Disposition", "attachment;filename=" + key + fi.Extension); context.Response.Cache.SetLastModified(fi.LastWriteTime); context.Response.Cache.SetCacheability(HttpCacheability.Public); context.Response.WriteFile(fi.FullName); } /// /// Urcuje, že daný handler muže být použi pro obsloužení více requestu. /// public bool IsReusable { get { return true; } } #endregion /// /// Poskytuje tabulku s informacemi o souborech, které mají být poskytnuty návštevníkum /// /// /// public static DataTable StaticFiles(HttpContext context) { DataTable result = context.Cache[StaticFileHandler._resourceFileName] as DataTable; if (result == null) { string filePath = context.Server.MapPath("~/"+StaticFileHandler._resourceFileName); FileInfo fi = new FileInfo(filePath); if (!fi.Exists) throw new HttpException(404, "Resources not found"); DataSet ds = new DataSet(); ds.ReadXml(fi.FullName); if (ds.Tables.Count > 0) result = ds.Tables[0]; else throw new HttpException(404, "Resources not found"); CacheDependency dep = new CacheDependency(fi.FullName); context.Cache.Insert(StaticFileHandler._resourceFileName, result, dep); } return result; } /// /// Vrací informace jaký content type se má pro daný soubor použít /// /// soubor, který bude poskytnu, podle jeho prípony se urcuje content type /// vrácený content type pro predaný soubor, výchozí hodnotou je application/octet-stream private static string getMimeMapping(string fileName) { string result = null; int idx = fileName.LastIndexOf('.'); if (idx > 0 && idx > fileName.LastIndexOf('\\')) result = _contentTypes[fileName.Substring(idx+1).ToLower(CultureInfo.InvariantCulture)]; if (result == null) return "application/octet-stream"; else return result; } /// /// Vrací informace o požadovaném souboru, který je uložen v adresárové strukture webu /// /// aktuální context požadavku /// klíc požadovaného souboru /// informace o požadovaném souboru private FileInfo getStaticFile(HttpContext context, string key, out bool useName) { string fN = string.Empty; useName = false; DataTable table = StaticFileHandler.StaticFiles(context); DataRow [] rows = table.Select(string.Format("key = '{0}'", key)); if ((rows != null) && (rows.Length > 0)) { DataRow row = rows[0]; useName = (bool)row["useName"]; fN = context.Server.MapPath("~/"+row["location"].ToString()); if (!File.Exists(fN)) throw new HttpException(404, "Resource not found"); try { return new FileInfo(fN); } catch (IOException) { throw new HttpException(404, "Resource not found"); } catch (SecurityException) { throw new HttpException(401, "Access denied"); } } else { throw new HttpException(404, "Resource not found"); } } /// /// Zjistí, zda je soubor nebyl modifikován jindy než je požadováno v hlavicce požadavku /// /// poslední zmena požadovaného souboru /// aktuální požadavek /// informace o tom, zda se datumy nerozcházejí private bool FileIsNotModifiedSince(DateTime lastWriteTime, HttpRequest Request) { string ifModified = Request.Headers["If-Modified-Since"]; if (ifModified != null) { string lastModified = lastWriteTime.ToString("r"); return (ifModified == lastModified); } return false; } } }