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;
}
}
}