Web服务器(CassiniDev的裁减版)
做此程序的原因是将软件部署简化,省去IIS的麻烦部署,减少项目实施人员的工作量和工作复杂度
Server sv = new Server(, "/", @"D:\web", IPAddress.Any, null, "Login.aspx");
// **********************************************************************************
// CassiniDev - http://cassinidev.codeplex.com
//
// Copyright (c) 2010 Sky Sanders. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is subject to terms and conditions of the Microsoft Public
// License (Ms-PL). A copy of the license can be found in the license.txt file
// included in this distribution.
//
// You must not remove this notice, or any other, from this software.
//
// ********************************************************************************** #region using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.Remoting;
using System.Security.Permissions;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Hosting; #endregion namespace SimpleWebServer
{
///<summary>
///</summary>
[PermissionSet(SecurityAction.LinkDemand, Name = "Everything"),
PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")]
public class Server : MarshalByRefObject, IDisposable
{
///<summary>
///</summary>
public List<string> Plugins = new List<string>();
///<summary>
///</summary>
public readonly ApplicationManager ApplicationManager; private readonly bool _disableDirectoryListing; private readonly string _hostName; private readonly IPAddress _ipAddress; private readonly object _lockObject; private readonly string _physicalPath; private readonly int _port;
private readonly bool _requireAuthentication;
//private readonly int _timeoutInterval;
private readonly string _virtualPath;
private bool _disposed; private Host _host; private IntPtr _processToken; private string _processUser; //private int _requestCount; private bool _shutdownInProgress; private Socket _socket; //private Timer _timer; private string _appId; private string _dfPage;
///<summary>
///</summary>
public string AppId
{
get { return _appId; }
}
///<summary>
///</summary>
public AppDomain HostAppDomain
{
get
{
if (_host == null)
{
GetHost();
}
if (_host != null)
{
return _host.AppDomain;
}
return null;
}
} ///<summary>
///</summary>
///<param name="port"></param>
///<param name="virtualPath"></param>
///<param name="physicalPath"></param>
public Server(int port, string virtualPath, string physicalPath)
: this(port, virtualPath, physicalPath, false, false)
{
} ///<summary>
///</summary>
///<param name="port"></param>
///<param name="physicalPath"></param>
public Server(int port, string physicalPath)
: this(port, "/", physicalPath, IPAddress.Loopback)
{
} ///<summary>
///</summary>
///<param name="port"></param>
///<param name="virtualPath"></param>
///<param name="physicalPath"></param>
///<param name="ipAddress"></param>
///<param name="hostName"></param>
///<param name="requireAuthentication"></param>
public Server(int port, string virtualPath, string physicalPath, IPAddress ipAddress, string hostName)
: this(port, virtualPath, physicalPath, ipAddress, hostName,false, false, null)
{
} ///<summary>
///</summary>
///<param name="port"></param>
///<param name="virtualPath"></param>
///<param name="physicalPath"></param>
///<param name="requireAuthentication"></param>
public Server(int port, string virtualPath, string physicalPath, bool requireAuthentication)
: this(port, virtualPath, physicalPath, requireAuthentication, false)
{
} ///<summary>
///</summary>
///<param name="port"></param>
///<param name="virtualPath"></param>
///<param name="physicalPath"></param>
///<param name="ipAddress"></param>
///<param name="hostName"></param>
public Server(int port, string virtualPath, string physicalPath, IPAddress ipAddress, string hostName,string dfPage)
: this(port, virtualPath, physicalPath, ipAddress, hostName, false, false, dfPage)
{
} ///<summary>
///</summary>
///<param name="port"></param>
///<param name="virtualPath"></param>
///<param name="physicalPath"></param>
///<param name="ipAddress"></param>
///<param name="hostName"></param>
///<param name="requireAuthentication"></param>
///<param name="disableDirectoryListing"></param>
public Server(int port, string virtualPath, string physicalPath, IPAddress ipAddress, string hostName,
bool requireAuthentication, bool disableDirectoryListing, string dfPage)
: this(port, virtualPath, physicalPath, requireAuthentication, disableDirectoryListing)
{
_ipAddress = ipAddress;
_hostName = hostName;
if (!String.IsNullOrEmpty(dfPage))
dfPage.TrimStart('/');
_dfPage = "/" + dfPage;
//_timeoutInterval = timeout;
} ///<summary>
///</summary>
///<param name="port"></param>
///<param name="virtualPath"></param>
///<param name="physicalPath"></param>
///<param name="ipAddress"></param>
public Server(int port, string virtualPath, string physicalPath, IPAddress ipAddress)
: this(port, virtualPath, physicalPath, ipAddress, null, false, false , null)
{
} ///<summary>
///</summary>
///<param name="port"></param>
///<param name="virtualPath"></param>
///<param name="physicalPath"></param>
///<param name="requireAuthentication"></param>
///<param name="disableDirectoryListing"></param>
public Server(int port, string virtualPath, string physicalPath, bool requireAuthentication,
bool disableDirectoryListing)
{
try
{
Assembly.ReflectionOnlyLoad("Common.Logging");
}
// ReSharper disable EmptyGeneralCatchClause
catch
// ReSharper restore EmptyGeneralCatchClause
{
}
_ipAddress = IPAddress.Loopback;
_requireAuthentication = requireAuthentication;
_disableDirectoryListing = disableDirectoryListing;
_lockObject = new object();
_port = port;
_virtualPath = virtualPath;
_physicalPath = Path.GetFullPath(physicalPath);
_physicalPath = _physicalPath.EndsWith("\\", StringComparison.Ordinal)
? _physicalPath
: _physicalPath + "\\"; ApplicationManager = ApplicationManager.GetApplicationManager();
string uniqueAppString = string.Concat(virtualPath, physicalPath,":",_port.ToString()).ToLowerInvariant();
_appId = (uniqueAppString.GetHashCode()).ToString("x", CultureInfo.InvariantCulture);
ObtainProcessToken();
} ///<summary>
///</summary>
public bool DisableDirectoryListing
{
get { return _disableDirectoryListing; }
} ///<summary>
///</summary>
public bool RequireAuthentication
{
get { return _requireAuthentication; }
} /////<summary>
/////</summary>
//public int TimeoutInterval
//{
// get { return _timeoutInterval; }
//} ///<summary>
///</summary>
public string HostName
{
get { return _hostName; }
} ///<summary>
///</summary>
// ReSharper disable InconsistentNaming
public IPAddress IPAddress
// ReSharper restore InconsistentNaming
{
get { return _ipAddress; }
} ///<summary>
///</summary>
public string PhysicalPath
{
get { return _physicalPath; }
} ///<summary>
///</summary>
public int Port
{
get { return _port; }
} ///<summary>
///</summary>
public string RootUrl
{
get
{
string hostname = _hostName;
if (string.IsNullOrEmpty(_hostName))
{
if (_ipAddress.Equals(IPAddress.Loopback) || _ipAddress.Equals(IPAddress.IPv6Loopback) ||
_ipAddress.Equals(IPAddress.Any) || _ipAddress.Equals(IPAddress.IPv6Any))
{
hostname = "localhost";
}
else
{
hostname = _ipAddress.ToString();
}
} return _port !=
?
String.Format("http://{0}:{1}{2}", hostname, _port, _virtualPath)
:
//FIX: #12017 - TODO:TEST
string.Format("http://{0}{1}", hostname, _virtualPath);
}
} ///<summary>
///</summary>
public string VirtualPath
{
get { return _virtualPath; }
} #region IDisposable Members /// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <filterpriority></filterpriority>
public void Dispose()
{
if (!_disposed)
{
ShutDown();
}
_disposed = true;
GC.SuppressFinalize(this);
} #endregion ///<summary>
///</summary>
public event EventHandler<RequestEventArgs> RequestComplete; /////<summary>
/////</summary>
//public event EventHandler TimedOut; ///<summary>
///</summary>
///<returns></returns>
public IntPtr GetProcessToken()
{
return _processToken;
} ///<summary>
///</summary>
///<returns></returns>
public string GetProcessUser()
{
return _processUser;
} ///<summary>
///</summary>
public void HostStopped()
{
_host = null;
} /// <summary>
/// Obtains a lifetime service object to control the lifetime policy for this instance.
/// </summary>
/// <returns>
/// An object of type <see cref="T:System.Runtime.Remoting.Lifetime.ILease"/> used to control the lifetime policy for this instance. This is the current lifetime service object for this instance if one exists; otherwise, a new lifetime service object initialized to the value of the <see cref="P:System.Runtime.Remoting.Lifetime.LifetimeServices.LeaseManagerPollTime"/> property.
/// </returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller does not have infrastructure permission.
/// </exception><filterpriority></filterpriority><PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="RemotingConfiguration, Infrastructure"/></PermissionSet>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
public override object InitializeLifetimeService()
{
// never expire the license
return null;
} // called at the end of request processing
// to disconnect the remoting proxy for Connection object
// and allow GC to pick it up
/// <summary>
/// </summary>
/// <param name="conn"></param>
/// <param name="userName"></param>
public void OnRequestEnd(Connection conn)
{
try
{
OnRequestComplete(conn.Id);
}
catch
{
// swallow - we don't want consumer killing the server
}
RemotingServices.Disconnect(conn);
//DecrementRequestCount();
} ///<summary>
///</summary>
public void Start()
{
_socket = CreateSocketBindAndListen(AddressFamily.InterNetwork, _ipAddress, _port); //start the timer
//DecrementRequestCount(); ThreadPool.QueueUserWorkItem(delegate
{
while (!_shutdownInProgress)
{
try
{
Socket acceptedSocket = _socket.Accept(); ThreadPool.QueueUserWorkItem(delegate
{
if (!_shutdownInProgress)
{
Connection conn = new Connection(this, acceptedSocket); if (conn.WaitForRequestBytes() == )
{
conn.WriteErrorAndClose();
return;
} Host host = GetHost(); if (host == null)
{
conn.WriteErrorAndClose();
return;
} //IncrementRequestCount();
host.ProcessRequest(conn,_dfPage);
}
});
}
catch
{
Thread.Sleep();
}
}
});
} /// <summary>
/// Allows an <see cref="T:System.Object"/> to attempt to free resources and perform other cleanup operations before the <see cref="T:System.Object"/> is reclaimed by garbage collection.
/// </summary>
~Server()
{
Dispose();
} private static Socket CreateSocketBindAndListen(AddressFamily family, IPAddress address, int port)
{
Socket socket = new Socket(family, SocketType.Stream, ProtocolType.Tcp);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
socket.Bind(new IPEndPoint(address, port));
socket.Listen((int)SocketOptionName.MaxConnections);
return socket;
} /// <summary>
///
/// </summary>
/// <param name="virtualPath"></param>
/// <param name="physicalPath"></param>
/// <param name="hostType"></param>
/// <param name="port"></param>
/// <returns></returns>
/// <remarks>
/// This is Dmitry's hack to enable running outside of GAC.
/// There are some errors being thrown when running in proc
/// </remarks>
private object CreateWorkerAppDomainWithHost(string virtualPath, string physicalPath, Type hostType,int port)
{ // create BuildManagerHost in the worker app domain
//ApplicationManager appManager = ApplicationManager.GetApplicationManager();
Type buildManagerHostType = typeof(HttpRuntime).Assembly.GetType("System.Web.Compilation.BuildManagerHost");
IRegisteredObject buildManagerHost = ApplicationManager.CreateObject(_appId, buildManagerHostType, virtualPath,
physicalPath, false); // call BuildManagerHost.RegisterAssembly to make Host type loadable in the worker app domain
buildManagerHostType.InvokeMember("RegisterAssembly",
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic,
null,
buildManagerHost,
new object[] { hostType.Assembly.FullName, hostType.Assembly.Location }); // create Host in the worker app domain
// FIXME: getting FileLoadException Could not load file or assembly 'WebDev.WebServer20, Version=4.0.1.6, Culture=neutral, PublicKeyToken=f7f6e0b4240c7c27' or one of its dependencies. Failed to grant permission to execute. (Exception from HRESULT: 0x80131418)
// when running dnoa 3.4 samples - webdev is registering trust somewhere that we are not
return ApplicationManager.CreateObject(_appId, hostType, virtualPath, physicalPath, false);
} //private void DecrementRequestCount()
//{
// lock (_lockObject)
// {
// _requestCount--; // if (_requestCount < 1)
// {
// _requestCount = 0; // if (_timeoutInterval > 0 && _timer == null)
// {
// _timer = new Timer(TimeOut, null, _timeoutInterval, Timeout.Infinite);
// }
// }
// }
//} private Host GetHost()
{
if (_shutdownInProgress)
return null;
Host host = _host;
if (host == null)
{
#if NET40
object obj2 = new object();
bool flag = false;
try
{
Monitor.Enter(obj2 = _lockObject, ref flag);
host = _host;
if (host == null)
{
host = (Host)CreateWorkerAppDomainWithHost(_virtualPath, _physicalPath, typeof(Host),Port);
host.Configure(this, _port, _virtualPath, _physicalPath, _requireAuthentication, _disableDirectoryListing);
_host = host;
}
}
finally
{
if (flag)
{
Monitor.Exit(obj2);
}
}
#else lock (_lockObject)
{
host = _host;
if (host == null)
{
host = (Host)CreateWorkerAppDomainWithHost(_virtualPath, _physicalPath, typeof(Host),Port);
host.Configure(this, _port, _virtualPath, _physicalPath, _requireAuthentication, _disableDirectoryListing);
_host = host;
}
} #endif
} return host;
} //private void IncrementRequestCount()
//{ // lock (_lockObject)
// {
// _requestCount++; // if (_timer != null)
// { // _timer.Dispose();
// _timer = null;
// }
// }
//} private void ObtainProcessToken()
{
if (Interop.ImpersonateSelf())
{
Interop.OpenThreadToken(Interop.GetCurrentThread(), 0xf01ff, true, ref _processToken);
Interop.RevertToSelf();
// ReSharper disable PossibleNullReferenceException
_processUser = WindowsIdentity.GetCurrent().Name;
// ReSharper restore PossibleNullReferenceException
}
} private void OnRequestComplete(Guid id)
{ EventHandler<RequestEventArgs> complete = RequestComplete; if (complete != null)
{
complete(this, new RequestEventArgs(id));
}
} ///<summary>
///</summary>
public void ShutDown()
{
if (_shutdownInProgress)
{
return;
} _shutdownInProgress = true; try
{
if (_socket != null)
{
_socket.Close();
}
}
// ReSharper disable EmptyGeneralCatchClause
catch
// ReSharper restore EmptyGeneralCatchClause
{
// TODO: why the swallow?
}
finally
{
_socket = null;
} try
{
if (_host != null)
{
_host.Shutdown();
} // the host is going to raise an event that this class uses to null the field.
// just wait until the field is nulled and continue. while (_host != null)
{
new AutoResetEvent(false).WaitOne();
}
}
// ReSharper disable EmptyGeneralCatchClause
catch
// ReSharper restore EmptyGeneralCatchClause
{
// TODO: what am i afraid of here?
} } //private void TimeOut(object ignored)
//{
// TimeOut();
//} /////<summary>
/////</summary>
//public void TimeOut()
//{
// ShutDown();
// OnTimeOut();
//} //private void OnTimeOut()
//{
// EventHandler handler = TimedOut;
// if (handler != null) handler(this, EventArgs.Empty);
//}
}
}
Server类
// **********************************************************************************
// CassiniDev - http://cassinidev.codeplex.com
//
// Copyright (c) 2010 Sky Sanders. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is subject to terms and conditions of the Microsoft Public
// License (Ms-PL). A copy of the license can be found in the license.txt file
// included in this distribution.
//
// You must not remove this notice, or any other, from this software.
//
// ********************************************************************************** #region using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Web.UI; #endregion namespace SimpleWebServer
{
internal static class CommonExtensions
{
public static string ConvertToHexView(this byte[] value, int numBytesPerRow)
{
if (value == null) return null; List<string> hexSplit = BitConverter.ToString(value)
.Replace('-', ' ')
.Trim()
.SplitIntoChunks(numBytesPerRow*)
.ToList(); int byteAddress = ;
StringBuilder sb = new StringBuilder(); for (int i = ; i < hexSplit.Count; i++)
{
sb.AppendLine(byteAddress.ToString("X4") + ":\t" + hexSplit[i]);
byteAddress += numBytesPerRow;
} return sb.ToString();
} /// <summary>
/// CassiniDev FIX: #12506
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static string GetContentType(string fileName)
{
if (!File.Exists(fileName))
{
return null;
} string contentType; FileInfo info = new FileInfo(fileName);
string extension = info.Extension.ToLowerInvariant(); #region switch filetype
switch (extension)
{
//NOTE: these are fallbacks - and should be refined as needed
// Only if the request does not already know
// the content-type will this switch be hit - meaning that
// served content-types for extensions listed here may not match
// as this method may not be polled. case ".svgz":
contentType = "image/svg+xml";
break; // from registry - last resort - verified mappings follow case ".3g2":
contentType = "video/3gpp2";
break;
case ".3gp":
contentType = "video/3gpp";
break;
case ".3gp2":
contentType = "video/3gpp2";
break;
case ".3gpp":
contentType = "video/3gpp";
break;
case ".adt":
contentType = "audio/vnd.dlna.adts";
break;
case ".amr":
contentType = "audio/AMR";
break;
case ".addin":
contentType = "text/xml";
break;
case ".evr":
contentType = "audio/evrc-qcp";
break;
case ".evrc":
contentType = "audio/evrc-qcp";
break;
case ".ssisdeploymentmanifest":
contentType = "text/xml";
break;
case ".xoml":
contentType = "text/plain";
break;
case ".aac":
contentType = "audio/aac";
break;
case ".ac3":
contentType = "audio/ac3";
break;
case ".accda":
contentType = "application/msaccess";
break;
case ".accdb":
contentType = "application/msaccess";
break;
case ".accdc":
contentType = "application/msaccess";
break;
case ".accde":
contentType = "application/msaccess";
break;
case ".accdr":
contentType = "application/msaccess";
break;
case ".accdt":
contentType = "application/msaccess";
break;
case ".acrobatsecuritysettings":
contentType = "application/vnd.adobe.acrobat-security-settings";
break;
case ".ad":
contentType = "text/plain";
break;
case ".ade":
contentType = "application/msaccess";
break;
case ".adobebridge":
contentType = "application/x-bridge-url";
break;
case ".adp":
contentType = "application/msaccess";
break;
case ".adts":
contentType = "audio/vnd.dlna.adts";
break;
case ".amc":
contentType = "application/x-mpeg";
break;
case ".application":
contentType = "application/x-ms-application";
break;
case ".asa":
contentType = "application/xml";
break;
case ".asax":
contentType = "application/xml";
break;
case ".ascx":
contentType = "application/xml";
break; case ".ashx":
contentType = "application/xml";
break;
case ".asm":
contentType = "text/plain";
break;
case ".asmx":
contentType = "application/xml";
break;
case ".aspx":
contentType = "application/xml";
break;
case ".awf":
contentType = "application/vnd.adobe.workflow";
break;
case ".biz":
contentType = "text/xml";
break; case ".c2r":
contentType = "text/vnd-ms.click2record+xml";
break;
case ".caf":
contentType = "audio/x-caf";
break; case ".cc":
contentType = "text/plain";
break;
case ".cd":
contentType = "text/plain";
break;
case ".cdda":
contentType = "audio/aiff";
break; case ".config":
contentType = "application/xml";
break;
case ".contact":
contentType = "text/x-ms-contact";
break;
case ".coverage":
contentType = "application/xml";
break;
case ".cpp":
contentType = "text/plain";
break;
case ".cs":
contentType = "text/plain";
break;
case ".csdproj":
contentType = "text/plain";
break;
case ".csproj":
contentType = "text/plain";
break;
case ".jar":
contentType = "application/java-archive";
break;
case ".csv":
contentType = "application/vnd.ms-excel";
break;
case ".cur":
contentType = "text/plain";
break;
case ".cxx":
contentType = "text/plain";
break;
case ".datasource":
contentType = "application/xml";
break;
case ".dbproj":
contentType = "text/plain";
break;
case ".dcd":
contentType = "text/xml";
break;
case ".dd":
contentType = "text/plain";
break;
case ".def":
contentType = "text/plain";
break; case ".design":
contentType = "image/design";
break;
case ".dgml":
contentType = "application/xml";
break;
case ".dib":
contentType = "image/bmp";
break;
case ".dif":
contentType = "video/x-dv";
break;
case ".docm":
contentType = "application/vnd.ms-word.document.macroEnabled.12";
break;
case ".docx":
contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
break;
case ".dotm":
contentType = "application/vnd.ms-word.template.macroEnabled.12";
break;
case ".dotx":
contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.template";
break;
case ".dsp":
contentType = "text/plain";
break;
case ".dsprototype":
contentType = "text/plain";
break;
case ".dsw":
contentType = "text/plain";
break;
case ".dtd":
contentType = "application/xml-dtd";
break;
case ".dtsconfig":
contentType = "text/xml";
break;
case ".dv":
contentType = "video/x-dv";
break;
case ".dwfx":
contentType = "model/vnd.dwfx+xps";
break;
case ".easmx":
contentType = "model/vnd.easmx+xps";
break;
case ".edrwx":
contentType = "model/vnd.edrwx+xps";
break;
case ".eprtx":
contentType = "model/vnd.eprtx+xps";
break;
case ".fdf":
contentType = "application/vnd.fdf";
break;
case ".filters":
contentType = "Application/xml";
break;
case ".flc":
contentType = "video/flc";
break;
case ".fo":
contentType = "text/xml";
break;
case ".fsscript":
contentType = "application/fsharp-script";
break;
case ".fsx":
contentType = "application/fsharp-script";
break;
case ".generictest":
contentType = "application/xml";
break;
case ".group":
contentType = "text/x-ms-group";
break;
case ".gsm":
contentType = "audio/x-gsm";
break;
case ".hpp":
contentType = "text/plain";
break;
case ".hxa":
contentType = "application/xml";
break;
case ".hxc":
contentType = "application/xml";
break;
case ".hxd":
contentType = "application/octet-stream";
break;
case ".hxe":
contentType = "application/xml";
break;
case ".hxf":
contentType = "application/xml";
break;
case ".hxh":
contentType = "application/octet-stream";
break;
case ".hxi":
contentType = "application/octet-stream";
break;
case ".hxk":
contentType = "application/xml";
break;
case ".hxq":
contentType = "application/octet-stream";
break;
case ".hxr":
contentType = "application/octet-stream";
break;
case ".hxs":
contentType = "application/octet-stream";
break;
case ".hxt":
contentType = "application/xml";
break;
case ".hxv":
contentType = "application/xml";
break;
case ".hxw":
contentType = "application/octet-stream";
break;
case ".hxx":
contentType = "text/plain";
break;
case ".i":
contentType = "text/plain";
break;
case ".idl":
contentType = "text/plain";
break;
case ".inc":
contentType = "text/plain";
break;
case ".inl":
contentType = "text/plain";
break;
case ".ipproj":
contentType = "text/plain";
break;
case ".iqy":
contentType = "text/x-ms-iqy";
break;
case ".ismv":
contentType = "video/ismv";
break;
case ".jsx":
contentType = "text/plain";
break;
case ".jsxbin":
contentType = "text/plain";
break;
case ".jtx":
contentType = "application/x-jtx+xps";
break;
case ".ldd":
contentType = "text/plain";
break;
case ".library-ms":
contentType = "application/windows-library+xml";
break;
case ".loadtest":
contentType = "application/xml";
break;
case ".lsaprototype":
contentType = "text/plain";
break;
case ".lst":
contentType = "text/plain";
break;
case ".m1v":
contentType = "video/mpeg";
break;
case ".m2t":
contentType = "video/vnd.dlna.mpeg-tts";
break;
case ".m2ts":
contentType = "video/vnd.dlna.mpeg-tts";
break;
case ".m2v":
contentType = "video/mpeg";
break;
case ".m4a":
contentType = "audio/mp4";
break;
case ".m4b":
contentType = "audio/x-m4b";
break;
case ".m4p":
contentType = "audio/x-m4p";
break;
case ".m4v":
contentType = "video/x-m4v";
break;
case ".mac":
contentType = "image/x-macpaint";
break;
case ".mak":
contentType = "text/plain";
break;
case ".map":
contentType = "text/plain";
break;
case ".master":
contentType = "application/xml";
break;
case ".mda":
contentType = "application/msaccess";
break;
case ".mde":
contentType = "application/msaccess";
break;
case ".mdp":
contentType = "text/plain";
break;
case ".mfp":
contentType = "application/x-shockwave-flash";
break;
case ".mk":
contentType = "text/plain";
break;
case ".mod":
contentType = "video/mpeg";
break;
case ".mp2v":
contentType = "video/mpeg";
break;
case ".mp4":
contentType = "video/mp4";
break;
case ".mp4v":
contentType = "video/mp4";
break;
case ".mpf":
contentType = "application/vnd.ms-mediapackage";
break;
case ".mqv":
contentType = "video/quicktime";
break;
case ".mts":
contentType = "video/vnd.dlna.mpeg-tts";
break;
case ".mtx":
contentType = "application/xml";
break;
case ".mxp":
contentType = "application/x-mmxp";
break;
case ".nix":
contentType = "application/x-mix-transfer";
break;
case ".odc":
contentType = "text/x-ms-odc";
break;
case ".odh":
contentType = "text/plain";
break;
case ".odl":
contentType = "text/plain";
break;
case ".odp":
contentType = "application/vnd.oasis.opendocument.presentation";
break;
case ".ods":
contentType = "application/vnd.oasis.opendocument.spreadsheet";
break;
case ".odt":
contentType = "application/vnd.oasis.opendocument.text";
break;
case ".orderedtest":
contentType = "application/xml";
break;
case ".osdx":
contentType = "application/opensearchdescription+xml";
break;
case ".pct":
contentType = "image/pict";
break;
case ".pcx":
contentType = "image/x-pcx";
break; case ".pdfxml":
contentType = "application/vnd.adobe.pdfxml";
break;
case ".pdx":
contentType = "application/vnd.adobe.pdx";
break;
case ".pic":
contentType = "image/pict";
break;
case ".pict":
contentType = "image/pict";
break;
case ".pkgdef":
contentType = "text/plain";
break;
case ".pkgundef":
contentType = "text/plain";
break;
case ".png":
contentType = "image/png";
break;
case ".pnt":
contentType = "image/x-macpaint";
break;
case ".pntg":
contentType = "image/x-macpaint";
break;
case ".potm":
contentType = "application/vnd.ms-powerpoint.template.macroEnabled.12";
break;
case ".potx":
contentType = "application/vnd.openxmlformats-officedocument.presentationml.template";
break;
case ".ppa":
contentType = "application/vnd.ms-powerpoint";
break;
case ".ppam":
contentType = "application/vnd.ms-powerpoint.addin.macroEnabled.12";
break;
case ".ppsm":
contentType = "application/vnd.ms-powerpoint.slideshow.macroEnabled.12";
break;
case ".ppsx":
contentType = "application/vnd.openxmlformats-officedocument.presentationml.slideshow";
break;
case ".pptm":
contentType = "application/vnd.ms-powerpoint.presentation.macroEnabled.12";
break;
case ".pptx":
contentType = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
break;
case ".psc1":
contentType = "application/PowerShell";
break;
case ".psess":
contentType = "application/xml";
break;
case ".pwz":
contentType = "application/vnd.ms-powerpoint";
break;
case ".pxr":
contentType = "image/pxr";
break;
case ".qcp":
contentType = "audio/vnd.qcelp";
break;
case ".qht":
contentType = "text/x-html-insertion";
break;
case ".qhtm":
contentType = "text/x-html-insertion";
break;
case ".qti":
contentType = "image/x-quicktime";
break;
case ".qtif":
contentType = "image/x-quicktime";
break;
case ".qtl":
contentType = "application/x-quicktimeplayer";
break;
case ".rat":
contentType = "application/rat-file";
break;
case ".raw":
contentType = "application/octet-stream";
break; case ".rc":
contentType = "text/plain";
break;
case ".rc2":
contentType = "text/plain";
break;
case ".rct":
contentType = "text/plain";
break;
case ".rdf":
contentType = "text/xml";
break;
case ".rdlc":
contentType = "application/xml";
break;
case ".rels":
contentType = "application/vnd.ms-package.relationships+xml";
break;
case ".resx":
contentType = "application/xml";
break;
case ".rgs":
contentType = "text/plain";
break;
case ".rjt":
contentType = "application/vnd.rn-realsystem-rjt";
break;
case ".rm":
contentType = "application/vnd.rn-realmedia";
break;
case ".rmf":
contentType = "application/vnd.adobe.rmf";
break;
case ".rmj":
contentType = "application/vnd.rn-realsystem-rmj";
break;
case ".rmm":
contentType = "audio/x-pn-realaudio";
break;
case ".rmp":
contentType = "application/vnd.rn-rn_music_package";
break;
case ".rms":
contentType = "application/vnd.rn-realaudio-secure";
break;
case ".rmvb":
contentType = "application/vnd.rn-realmedia-vbr";
break;
case ".rmx":
contentType = "application/vnd.rn-realsystem-rmx";
break;
case ".rnx":
contentType = "application/vnd.rn-realplayer";
break;
case ".rp":
contentType = "image/vnd.rn-realpix";
break;
case ".rpm":
contentType = "audio/x-pn-realaudio-plugin";
break;
case ".rqy":
contentType = "text/x-ms-rqy";
break;
case ".rsml":
contentType = "application/vnd.rn-rsml";
break;
case ".rt":
contentType = "text/vnd.rn-realtext";
break;
case ".rtsp":
contentType = "application/x-rtsp";
break;
case ".ruleset":
contentType = "application/xml";
break;
case ".rv":
contentType = "video/vnd.rn-realvideo";
break;
case ".s":
contentType = "text/plain";
break;
case ".sd":
contentType = "text/plain";
break;
case ".sd2":
contentType = "audio/x-sd2";
break;
case ".sdm":
contentType = "text/plain";
break;
case ".sdmdocument":
contentType = "text/plain";
break;
case ".sdp":
contentType = "application/sdp";
break;
case ".sdv":
contentType = "video/sd-video";
break;
case ".searchConnector-ms":
contentType = "application/windows-search-connector+xml";
break;
case ".settings":
contentType = "application/xml";
break;
case ".sgi":
contentType = "image/x-sgi";
break;
case ".shtml":
contentType = "text/html";
break;
case ".sitemap":
contentType = "application/xml";
break;
case ".skin":
contentType = "application/xml";
break;
case ".sldm":
contentType = "application/vnd.ms-powerpoint.slide.macroEnabled.12";
break;
case ".sldx":
contentType = "application/vnd.openxmlformats-officedocument.presentationml.slide";
break;
case ".slk":
contentType = "application/vnd.ms-excel";
break;
case ".sln":
contentType = "text/plain";
break;
case ".slupkg-ms":
contentType = "application/x-ms-license";
break;
case ".smi":
contentType = "application/smil";
break;
case ".smil":
contentType = "application/smil";
break;
case ".snippet":
contentType = "application/xml";
break;
case ".sol":
contentType = "text/plain";
break;
case ".sor":
contentType = "text/plain";
break;
case ".srf":
contentType = "text/plain";
break;
case ".svc":
contentType = "application/xml";
break;
case ".tga":
contentType = "image/x-targa";
break;
case ".targa":
contentType = "image/x-targa";
break;
case ".testrunconfig":
contentType = "application/xml";
break;
case ".testsettings":
contentType = "application/xml";
break;
case ".thmx":
contentType = "application/vnd.ms-officetheme";
break;
case ".tlh":
contentType = "text/plain";
break;
case ".tli":
contentType = "text/plain";
break;
case ".trx":
contentType = "application/xml";
break;
case ".ts":
contentType = "video/vnd.dlna.mpeg-tts";
break;
case ".tts":
contentType = "video/vnd.dlna.mpeg-tts";
break;
case ".user":
contentType = "text/plain";
break;
case ".vb":
contentType = "text/plain";
break;
case ".vbdproj":
contentType = "text/plain";
break;
case ".vbproj":
contentType = "text/plain";
break;
case ".vcproj":
contentType = "Application/xml";
break;
case ".vcxproj":
contentType = "Application/xml";
break;
case ".vddproj":
contentType = "text/plain";
break;
case ".vdp":
contentType = "text/plain";
break;
case ".vdproj":
contentType = "text/plain";
break;
case ".vdx":
contentType = "application/vnd.visio";
break;
case ".vscontent":
contentType = "application/xml";
break;
case ".vsct":
contentType = "text/xml";
break;
case ".vsd":
contentType = "application/vnd.visio";
break;
case ".vsi":
contentType = "application/ms-vsi";
break;
case ".vsix":
contentType = "application/vsix";
break;
case ".vsixlangpack":
contentType = "text/xml";
break;
case ".vsixmanifest":
contentType = "text/xml";
break;
case ".vsl":
contentType = "application/vnd.visio";
break;
case ".vsmdi":
contentType = "application/xml";
break;
case ".vspscc":
contentType = "text/plain";
break;
case ".vss":
contentType = "application/vnd.visio";
break;
case ".vsscc":
contentType = "text/plain";
break;
case ".vssettings":
contentType = "text/xml";
break;
case ".vssscc":
contentType = "text/plain";
break;
case ".vst":
contentType = "application/vnd.visio";
break;
case ".vstemplate":
contentType = "text/xml";
break;
case ".vsto":
contentType = "application/x-ms-vsto";
break;
case ".vsu":
contentType = "application/vnd.visio";
break;
case ".vsw":
contentType = "application/vnd.visio";
break;
case ".vsx":
contentType = "application/vnd.visio";
break;
case ".vtx":
contentType = "application/vnd.visio";
break;
case ".wax":
contentType = "audio/x-ms-wax";
break;
case ".wbk":
contentType = "application/msword";
break;
case ".wdp":
contentType = "image/vnd.ms-photo";
break;
case ".webtest":
contentType = "application/xml";
break;
case ".wiq":
contentType = "application/xml";
break;
case ".wiz":
contentType = "application/msword";
break;
case ".wm":
contentType = "video/x-ms-wm";
break;
case ".wma":
contentType = "audio/x-ms-wma";
break;
case ".wmd":
contentType = "application/x-ms-wmd";
break;
case ".wmv":
contentType = "video/x-ms-wmv";
break;
case ".wmx":
contentType = "video/x-ms-wmx";
break;
case ".wmz":
contentType = "application/x-ms-wmz";
break;
case ".wpl":
contentType = "application/vnd.ms-wpl";
break;
case ".wsc":
contentType = "text/scriptlet";
break;
case ".wsdl":
contentType = "application/xml";
break;
case ".wvx":
contentType = "video/x-ms-wvx";
break;
case ".xaml":
contentType = "application/xaml+xml";
break;
case ".xbap":
contentType = "application/x-ms-xbap";
break;
case ".xbrl":
contentType = "text/xml";
break;
case ".xdp":
contentType = "application/vnd.adobe.xdp+xml";
break;
case ".xdr":
contentType = "application/xml";
break;
case ".xej":
contentType = "application/xej+xml";
break;
case ".xel":
contentType = "application/xel+xml";
break;
case ".xesc":
contentType = "application/x-ms-wmv";
break;
case ".xfd":
contentType = "application/vnd.adobe.xfd+xml";
break;
case ".xfdf":
contentType = "application/vnd.adobe.xfdf";
break;
case ".xht":
contentType = "application/xhtml+xml";
break;
case ".xhtml":
contentType = "application/xhtml+xml";
break;
case ".xlam":
contentType = "application/vnd.ms-excel.addin.macroEnabled.12";
break;
case ".xlk":
contentType = "application/vnd.ms-excel";
break;
case ".xll":
contentType = "application/vnd.ms-excel";
break;
case ".xlsb":
contentType = "application/vnd.ms-excel.sheet.binary.macroEnabled.12";
break;
case ".xlsm":
contentType = "application/vnd.ms-excel.sheet.macroEnabled.12";
break;
case ".xlsx":
contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
break;
case ".xltm":
contentType = "application/vnd.ms-excel.template.macroEnabled.12";
break;
case ".xltx":
contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.template";
break;
case ".xml":
contentType = "application/xml";
break;
case ".xmta":
contentType = "application/xml";
break;
case ".xpr":
contentType = "image/xpr";
break;
case ".xps":
contentType = "application/vnd.ms-xpsdocument";
break;
case ".xrm-ms":
contentType = "text/xml";
break;
case ".xsc":
contentType = "application/xml";
break;
case ".xsd":
contentType = "application/xml";
break;
case ".xsl":
contentType = "text/xml";
break;
case ".xslt":
contentType = "application/xml";
break;
case ".xss":
contentType = "application/xml";
break;
case ".323":
contentType = "text/h323";
break;
case ".acx":
contentType = "application/internet-property-stream";
break;
case ".ai":
contentType = "application/postscript";
break;
case ".aif":
contentType = "audio/x-aiff";
break;
case ".aifc":
contentType = "audio/x-aiff";
break;
case ".aiff":
contentType = "audio/x-aiff";
break;
case ".asf":
contentType = "video/x-ms-asf";
break;
case ".asr":
contentType = "video/x-ms-asf";
break;
case ".asx":
contentType = "video/x-ms-asf";
break;
case ".au":
contentType = "audio/basic";
break;
case ".avi":
contentType = "video/x-msvideo";
break;
case ".axs":
contentType = "application/olescript";
break;
case ".bas":
contentType = "text/plain";
break;
case ".bcpio":
contentType = "application/x-bcpio";
break;
case ".bin":
contentType = "application/octet-stream";
break;
case ".bmp":
contentType = "image/bmp";
break;
case ".c":
contentType = "text/plain";
break;
case ".cat":
contentType = "application/vnd.ms-pkiseccat";
break;
case ".cdf":
contentType = "application/x-cdf";
break;
case ".cer":
contentType = "application/x-x509-ca-cert";
break;
case ".class":
contentType = "application/octet-stream";
break;
case ".clp":
contentType = "application/x-msclip";
break;
case ".cmx":
contentType = "image/x-cmx";
break;
case ".cod":
contentType = "image/cis-cod";
break;
case ".cpio":
contentType = "application/x-cpio";
break;
case ".crd":
contentType = "application/x-mscardfile";
break;
case ".crl":
contentType = "application/pkix-crl";
break;
case ".crt":
contentType = "application/x-x509-ca-cert";
break;
case ".csh":
contentType = "application/x-csh";
break;
case ".css":
contentType = "text/css";
break;
case ".dcr":
contentType = "application/x-director";
break;
case ".der":
contentType = "application/x-x509-ca-cert";
break;
case ".dir":
contentType = "application/x-director";
break;
case ".dll":
contentType = "application/x-msdownload";
break;
case ".dms":
contentType = "application/octet-stream";
break;
case ".doc":
contentType = "application/msword";
break;
case ".dot":
contentType = "application/msword";
break;
case ".dvi":
contentType = "application/x-dvi";
break;
case ".dxr":
contentType = "application/x-director";
break;
case ".eps":
contentType = "application/postscript";
break;
case ".etx":
contentType = "text/x-setext";
break;
case ".evy":
contentType = "application/envoy";
break;
case ".exe":
contentType = "application/octet-stream";
break;
case ".fif":
contentType = "application/fractals";
break;
case ".flr":
contentType = "x-world/x-vrml";
break;
case ".gif":
contentType = "image/gif";
break;
case ".gtar":
contentType = "application/x-gtar";
break;
case ".gz":
contentType = "application/x-gzip";
break;
case ".h":
contentType = "text/plain";
break;
case ".hdf":
contentType = "application/x-hdf";
break;
case ".hlp":
contentType = "application/winhlp";
break;
case ".hqx":
contentType = "application/mac-binhex40";
break;
case ".hta":
contentType = "application/hta";
break;
case ".htc":
contentType = "text/x-component";
break;
case ".htm":
contentType = "text/html";
break;
case ".html":
contentType = "text/html";
break;
case ".htt":
contentType = "text/webviewhtml";
break;
case ".ico":
contentType = "image/x-icon";
break;
case ".ief":
contentType = "image/ief";
break;
case ".iii":
contentType = "application/x-iphone";
break;
case ".ins":
contentType = "application/x-internet-signup";
break;
case ".isp":
contentType = "application/x-internet-signup";
break;
case ".jfif":
contentType = "image/pipeg";
break;
case ".jpe":
contentType = "image/jpeg";
break;
case ".jpeg":
contentType = "image/jpeg";
break;
case ".jpg":
contentType = "image/jpeg";
break;
case ".js":
contentType = "application/x-javascript";
break;
case ".latex":
contentType = "application/x-latex";
break;
case ".lha":
contentType = "application/octet-stream";
break;
case ".lsf":
contentType = "video/x-la-asf";
break;
case ".lsx":
contentType = "video/x-la-asf";
break;
case ".lzh":
contentType = "application/octet-stream";
break;
case ".m13":
contentType = "application/x-msmediaview";
break;
case ".m14":
contentType = "application/x-msmediaview";
break;
case ".m3u":
contentType = "audio/x-mpegurl";
break;
case ".man":
contentType = "application/x-troff-man";
break;
case ".mdb":
contentType = "application/x-msaccess";
break;
case ".me":
contentType = "application/x-troff-me";
break;
case ".mht":
contentType = "message/rfc822";
break;
case ".mhtml":
contentType = "message/rfc822";
break;
case ".mid":
contentType = "audio/mid";
break;
case ".mny":
contentType = "application/x-msmoney";
break;
case ".mov":
contentType = "video/quicktime";
break;
case ".movie":
contentType = "video/x-sgi-movie";
break;
case ".mp2":
contentType = "video/mpeg";
break;
case ".mp3":
contentType = "audio/mpeg";
break;
case ".mpa":
contentType = "video/mpeg";
break;
case ".mpe":
contentType = "video/mpeg";
break;
case ".mpeg":
contentType = "video/mpeg";
break;
case ".mpg":
contentType = "video/mpeg";
break;
case ".mpp":
contentType = "application/vnd.ms-project";
break;
case ".mpv2":
contentType = "video/mpeg";
break;
case ".ms":
contentType = "application/x-troff-ms";
break;
case ".msg":
contentType = "application/vnd.ms-outlook";
break;
case ".mvb":
contentType = "application/x-msmediaview";
break;
case ".nc":
contentType = "application/x-netcdf";
break;
case ".nws":
contentType = "message/rfc822";
break;
case ".oda":
contentType = "application/oda";
break;
case ".p10":
contentType = "application/pkcs10";
break;
case ".p12":
contentType = "application/x-pkcs12";
break;
case ".p7b":
contentType = "application/x-pkcs7-certificates";
break;
case ".p7c":
contentType = "application/x-pkcs7-mime";
break;
case ".p7m":
contentType = "application/x-pkcs7-mime";
break;
case ".p7r":
contentType = "application/x-pkcs7-certreqresp";
break;
case ".p7s":
contentType = "application/x-pkcs7-signature";
break;
case ".pbm":
contentType = "image/x-portable-bitmap";
break;
case ".pdf":
contentType = "application/pdf";
break;
case ".pfx":
contentType = "application/x-pkcs12";
break;
case ".pgm":
contentType = "image/x-portable-graymap";
break;
case ".pko":
contentType = "application/ynd.ms-pkipko";
break;
case ".pma":
contentType = "application/x-perfmon";
break;
case ".pmc":
contentType = "application/x-perfmon";
break;
case ".pml":
contentType = "application/x-perfmon";
break;
case ".pmr":
contentType = "application/x-perfmon";
break;
case ".pmw":
contentType = "application/x-perfmon";
break;
case ".pnm":
contentType = "image/x-portable-anymap";
break;
case ".pot":
contentType = "application/vnd.ms-powerpoint";
break;
case ".pot,":
contentType = "application/vnd.ms-powerpoint";
break;
case ".ppm":
contentType = "image/x-portable-pixmap";
break;
case ".pps":
contentType = "application/vnd.ms-powerpoint";
break;
case ".ppt":
contentType = "application/vnd.ms-powerpoint";
break;
case ".prf":
contentType = "application/pics-rules";
break;
case ".ps":
contentType = "application/postscript";
break;
case ".pub":
contentType = "application/x-mspublisher";
break;
case ".qt":
contentType = "video/quicktime";
break;
case ".ra":
contentType = "audio/x-pn-realaudio";
break;
case ".ram":
contentType = "audio/x-pn-realaudio";
break;
case ".ras":
contentType = "image/x-cmu-raster";
break;
case ".rgb":
contentType = "image/x-rgb";
break;
case ".rmi":
contentType = "audio/mid";
break;
case ".roff":
contentType = "application/x-troff";
break;
case ".rtf":
contentType = "application/rtf";
break;
case ".rtx":
contentType = "text/richtext";
break;
case ".scd":
contentType = "application/x-msschedule";
break;
case ".sct":
contentType = "text/scriptlet";
break;
case ".setpay":
contentType = "application/set-payment-initiation";
break;
case ".setreg":
contentType = "application/set-registration-initiation";
break;
case ".sh":
contentType = "application/x-sh";
break;
case ".shar":
contentType = "application/x-shar";
break;
case ".sit":
contentType = "application/x-stuffit";
break;
case ".snd":
contentType = "audio/basic";
break;
case ".spc":
contentType = "application/x-pkcs7-certificates";
break;
case ".spl":
contentType = "application/futuresplash";
break;
case ".src":
contentType = "application/x-wais-source";
break;
case ".sst":
contentType = "application/vnd.ms-pkicertstore";
break;
case ".stl":
contentType = "application/vnd.ms-pkistl";
break;
case ".stm":
contentType = "text/html";
break;
case ".sv4cpio":
contentType = "application/x-sv4cpio";
break;
case ".sv4crc":
contentType = "application/x-sv4crc";
break;
case ".svg":
contentType = "image/svg+xml";
break;
case ".swf":
contentType = "application/x-shockwave-flash";
break;
case ".t":
contentType = "application/x-troff";
break;
case ".tar":
contentType = "application/x-tar";
break;
case ".tcl":
contentType = "application/x-tcl";
break;
case ".tex":
contentType = "application/x-tex";
break;
case ".texi":
contentType = "application/x-texinfo";
break;
case ".texinfo":
contentType = "application/x-texinfo";
break;
case ".tgz":
contentType = "application/x-compressed";
break;
case ".tif":
contentType = "image/tiff";
break;
case ".tiff":
contentType = "image/tiff";
break;
case ".tr":
contentType = "application/x-troff";
break;
case ".trm":
contentType = "application/x-msterminal";
break;
case ".tsv":
contentType = "text/tab-separated-values";
break;
case ".txt":
contentType = "text/plain";
break;
case ".uls":
contentType = "text/iuls";
break;
case ".ustar":
contentType = "application/x-ustar";
break;
case ".vcf":
contentType = "text/x-vcard";
break;
case ".vrml":
contentType = "x-world/x-vrml";
break;
case ".wav":
contentType = "audio/x-wav";
break;
case ".wcm":
contentType = "application/vnd.ms-works";
break;
case ".wdb":
contentType = "application/vnd.ms-works";
break;
case ".wks":
contentType = "application/vnd.ms-works";
break;
case ".wmf":
contentType = "application/x-msmetafile";
break;
case ".wps":
contentType = "application/vnd.ms-works";
break;
case ".wri":
contentType = "application/x-mswrite";
break;
case ".wrl":
contentType = "x-world/x-vrml";
break;
case ".wrz":
contentType = "x-world/x-vrml";
break;
case ".xaf":
contentType = "x-world/x-vrml";
break;
case ".xbm":
contentType = "image/x-xbitmap";
break;
case ".xla":
contentType = "application/vnd.ms-excel";
break;
case ".xlc":
contentType = "application/vnd.ms-excel";
break;
case ".xlm":
contentType = "application/vnd.ms-excel";
break;
case ".xls":
contentType = "application/vnd.ms-excel";
break;
case ".xlt":
contentType = "application/vnd.ms-excel";
break;
case ".xlw":
contentType = "application/vnd.ms-excel";
break;
case ".xof":
contentType = "x-world/x-vrml";
break;
case ".xpm":
contentType = "image/x-xpixmap";
break;
case ".xwd":
contentType = "image/x-xwindowdump";
break;
case ".z":
contentType = "application/x-compress";
break;
case ".zip":
contentType = "application/zip";
break; default:
contentType = "";
break;
}
#endregion return contentType;
} public static T GetValueOrDefault<T>(this IDataRecord row, string fieldName)
{
int ordinal = row.GetOrdinal(fieldName);
return row.GetValueOrDefault<T>(ordinal);
} public static T GetValueOrDefault<T>(this IDataRecord row, int ordinal)
{
return (T) (row.IsDBNull(ordinal) ? default(T) : row.GetValue(ordinal));
} public static byte[] StreamToBytes(this Stream input)
{
int capacity = input.CanSeek ? (int) input.Length : ;
using (MemoryStream output = new MemoryStream(capacity))
{
int readLength;
byte[] buffer = new byte[]; do
{
readLength = input.Read(buffer, , buffer.Length);
output.Write(buffer, , readLength);
} while (readLength != ); return output.ToArray();
}
} private static IList<string> SplitIntoChunks(this string text, int chunkSize)
{
List<string> chunks = new List<string>();
int offset = ;
while (offset < text.Length)
{
int size = Math.Min(chunkSize, text.Length - offset);
chunks.Add(text.Substring(offset, size));
offset += size;
}
return chunks;
}
} /// <summary>
///
/// </summary>
public enum RunState
{
/// <summary>
///
/// </summary>
Idle = ,
/// <summary>
///
/// </summary>
Running
} /// <summary>
///
/// </summary>
public enum PortMode
{
/// <summary>
///
/// </summary>
FirstAvailable = ,
/// <summary>
///
/// </summary>
Specific
} /// <summary>
///
/// </summary>
public enum ErrorField
{
/// <summary>
///
/// </summary>
None,
/// <summary>
///
/// </summary>
ApplicationPath,
/// <summary>
///
/// </summary>
VirtualPath,
/// <summary>
///
/// </summary>
HostName,
/// <summary>
///
/// </summary>
IsAddHost,
/// <summary>
///
/// </summary>
// ReSharper disable InconsistentNaming
IPAddress,
// ReSharper restore InconsistentNaming
/// <summary>
///
/// </summary>
// ReSharper disable InconsistentNaming
IPAddressAny,
// ReSharper restore InconsistentNaming
/// <summary>
///
/// </summary>
// ReSharper disable InconsistentNaming
IPAddressLoopBack,
// ReSharper restore InconsistentNaming
/// <summary>
///
/// </summary>
Port,
/// <summary>
///
/// </summary>
PortRangeStart,
/// <summary>
///
/// </summary>
PortRangeEnd,
/// <summary>
///
/// </summary>
PortRange
} /// <summary>
///
/// </summary>
// ReSharper disable InconsistentNaming
public enum IPMode
// ReSharper restore InconsistentNaming
{
/// <summary>
///
/// </summary>
Loopback = ,
/// <summary>
///
/// </summary>
Any,
/// <summary>
///
/// </summary>
Specific
} /// <summary>
///
/// </summary>
public enum RunMode
{
/// <summary>
///
/// </summary>
Server,
/// <summary>
///
/// </summary>
Hostsfile
} /// <summary>
///
/// </summary>
internal class CassiniException : Exception
{
public CassiniException(string message, ErrorField field, Exception innerException)
: base(message, innerException)
{
Field = field;
} public CassiniException(string message, ErrorField field)
: this(message, field, null)
{
} public ErrorField Field { get; set; }
}
}
Common类
// **********************************************************************************
// CassiniDev - http://cassinidev.codeplex.com
//
// Copyright (c) 2010 Sky Sanders. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is subject to terms and conditions of the Microsoft Public
// License (Ms-PL). A copy of the license can be found in the license.txt file
// included in this distribution.
//
// You must not remove this notice, or any other, from this software.
//
// ********************************************************************************** #region using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Web; #endregion namespace SimpleWebServer
{
/// <summary>
///
/// </summary>
public class Connection : MarshalByRefObject
{
private const int HttpForbidden = ; // ReSharper disable InconsistentNaming
private const int HttpOK = ;
// ReSharper restore InconsistentNaming private readonly MemoryStream _responseContent;
/// <summary>
///
/// </summary>
public List<string> Plugins = new List<string>();
private readonly Server _server; private Socket _socket; internal Connection(Server server, Socket socket)
{
Plugins = server.Plugins;
Id = Guid.NewGuid();
_responseContent = new MemoryStream();
_server = server;
_socket = socket;
} /// <summary>
///
/// </summary>
public bool Connected
{
get { return _socket.Connected; }
} /// <summary>
///
/// </summary>
public Guid Id { get; private set; } /// <summary>
///
/// </summary>
// ReSharper disable InconsistentNaming
public string LocalIP
// ReSharper restore InconsistentNaming
{
get
{
IPEndPoint ep = (IPEndPoint) _socket.LocalEndPoint;
return (ep != null && ep.Address != null) ? ep.Address.ToString() : "127.0.0.1";
}
} // ReSharper disable InconsistentNaming
/// <summary>
///
/// </summary>
public string RemoteIP
// ReSharper restore InconsistentNaming
{
get
{
IPEndPoint ep = (IPEndPoint) _socket.RemoteEndPoint;
return (ep != null && ep.Address != null) ? ep.Address.ToString() : "127.0.0.1";
}
} /// <summary>
///
/// </summary>
public void Close()
{ try
{
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
// ReSharper disable EmptyGeneralCatchClause
catch
// ReSharper restore EmptyGeneralCatchClause
{
}
finally
{
_socket = null;
}
} /// <summary>
/// </summary>
public override object InitializeLifetimeService()
{
return null;
} /// <summary>
///
/// </summary>
/// <param name="maxBytes"></param>
/// <returns></returns>
public byte[] ReadRequestBytes(int maxBytes)
{
try
{
if (WaitForRequestBytes() == )
{
return null;
} int numBytes = _socket.Available; if (numBytes > maxBytes)
{
numBytes = maxBytes;
} int numReceived = ; byte[] buffer = new byte[numBytes]; if (numBytes > )
{
numReceived = _socket.Receive(buffer, , numBytes, SocketFlags.None);
} if (numReceived < numBytes)
{
byte[] tempBuffer = new byte[numReceived]; if (numReceived > )
{
Buffer.BlockCopy(buffer, , tempBuffer, , numReceived);
} buffer = tempBuffer;
} return buffer;
}
catch
{
return null;
}
} /// <summary>
///
/// </summary>
/// <returns></returns>
public int WaitForRequestBytes()
{
int availBytes = ; try
{
if (_socket.Available == )
{
_socket.Poll(, SelectMode.SelectRead); if (_socket.Available == && _socket.Connected)
{
_socket.Poll(, SelectMode.SelectRead);
}
} availBytes = _socket.Available;
}
// ReSharper disable EmptyGeneralCatchClause
catch
// ReSharper restore EmptyGeneralCatchClause
{
} return availBytes;
} /// <summary>
///
/// </summary>
public void Write100Continue()
{
WriteEntireResponseFromString(, null, null, true);
} internal void Write200Continue()
{
WriteEntireResponseFromString(, null, string.Empty, true);
} /// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
public void WriteBody(byte[] data, int offset, int length)
{
try
{
_responseContent.Write(data, , data.Length);
_socket.Send(data, offset, length, SocketFlags.None);
}
catch (SocketException)
{
}
} /// <summary>
///
/// </summary>
/// <param name="fileName"></param>
/// <param name="keepAlive"></param>
public void WriteEntireResponseFromFile(String fileName, bool keepAlive)
{
if (!File.Exists(fileName))
{
WriteErrorAndClose();
return;
} // Deny the request if the contentType cannot be recognized. string contentType = CommonExtensions.GetContentType(fileName); //TODO: i am pretty sure this is unnecessary
if (contentType == null)
{
WriteErrorAndClose(HttpForbidden);
return;
} string contentTypeHeader = "Content-Type: " + contentType + "\r\n"; bool completed = false;
FileStream fs = null; try
{
fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
int len = (int) fs.Length;
byte[] fileBytes = new byte[len];
int bytesRead = fs.Read(fileBytes, , len); String headers = MakeResponseHeaders(HttpOK, contentTypeHeader, bytesRead, keepAlive);
_socket.Send(Encoding.UTF8.GetBytes(headers)); _socket.Send(fileBytes, , bytesRead, SocketFlags.None); completed = true;
}
catch (SocketException)
{
}
finally
{
if (!keepAlive || !completed)
{
Close();
} if (fs != null)
{
fs.Close();
}
}
} /// <summary>
///
/// </summary>
/// <param name="statusCode"></param>
/// <param name="extraHeaders"></param>
/// <param name="body"></param>
/// <param name="keepAlive"></param>
public void WriteEntireResponseFromString(int statusCode, String extraHeaders, String body, bool keepAlive)
{
try
{
int bodyLength = (body != null) ? Encoding.UTF8.GetByteCount(body) : ;
string headers = MakeResponseHeaders(statusCode, extraHeaders, bodyLength, keepAlive); _socket.Send(Encoding.UTF8.GetBytes(headers + body));
}
catch (SocketException)
{
}
finally
{
if (!keepAlive)
{
Close();
}
}
} /// <summary>
///
/// </summary>
/// <param name="statusCode"></param>
/// <param name="message"></param>
public void WriteErrorAndClose(int statusCode, string message)
{
WriteEntireResponseFromString(statusCode, null, GetErrorResponseBody(statusCode, message), false);
} /// <summary>
///
/// </summary>
/// <param name="statusCode"></param>
public void WriteErrorAndClose(int statusCode)
{
WriteErrorAndClose(statusCode, null);
} /// <summary>
///
/// </summary>
/// <param name="statusCode"></param>
/// <param name="extraHeaders"></param>
public void WriteErrorWithExtraHeadersAndKeepAlive(int statusCode, string extraHeaders)
{
WriteEntireResponseFromString(statusCode, extraHeaders, GetErrorResponseBody(statusCode, null), true);
} /// <summary>
///
/// </summary>
/// <param name="statusCode"></param>
/// <param name="extraHeaders"></param>
public void WriteHeaders(int statusCode, String extraHeaders)
{
string headers = MakeResponseHeaders(statusCode, extraHeaders, -, false); try
{
_socket.Send(Encoding.UTF8.GetBytes(headers));
}
catch (SocketException)
{
}
} private string GetErrorResponseBody(int statusCode, string message)
{
string body = Messages.FormatErrorMessageBody(statusCode, _server.VirtualPath); if (!string.IsNullOrEmpty(message))
{
body += "\r\n<!--\r\n" + message + "\r\n-->";
} return body;
} //private void InitializeLogInfo()
//{
// _requestLog = new LogInfo
// {
// Created = DateTime.Now,
// ConversationId = Id,
// RowType = 1,
// Identity = _server.GetProcessUser(),
// PhysicalPath = _server.PhysicalPath
// }; // _responseLog = new LogInfo
// {
// ConversationId = Id,
// RowType = 2
// };
//} private static string MakeResponseHeaders(int statusCode, string moreHeaders, int contentLength, bool keepAlive)
{
StringBuilder sb = new StringBuilder(); sb.Append("HTTP/1.1 " + statusCode + " " + HttpWorkerRequest.GetStatusDescription(statusCode) + "\r\n");
sb.Append("Server: Cassini/" + Messages.VersionString + "\r\n");
sb.Append("Date: " + DateTime.Now.ToUniversalTime().ToString("R", DateTimeFormatInfo.InvariantInfo) + "\r\n"); if (contentLength >= )
{
sb.Append("Content-Length: " + contentLength + "\r\n");
} if (moreHeaders != null)
{
sb.Append(moreHeaders);
} if (!keepAlive)
{
sb.Append("Connection: Close\r\n");
} sb.Append("\r\n"); return sb.ToString();
}
}
}
Connection类
#region using System;
using System.Globalization;
using System.Security.Permissions;
using System.Security.Principal;
using System.Threading;
using System.Web;
using System.Web.Hosting; #endregion namespace SimpleWebServer
{
public class Host : MarshalByRefObject, IRegisteredObject
{
private bool _disableDirectoryListing; private string _installPath; private string _lowerCasedClientScriptPathWithTrailingSlash; private string _lowerCasedVirtualPath; private string _lowerCasedVirtualPathWithTrailingSlash; private volatile int _pendingCallsCount; private string _physicalClientScriptPath; private string _physicalPath; private int _port; private bool _requireAuthentication; private Server _server; private string _virtualPath; public AppDomain AppDomain
{
get { return AppDomain.CurrentDomain; }
} public Host()
{
HostingEnvironment.RegisterObject(this);
} public bool DisableDirectoryListing
{
get { return _disableDirectoryListing; }
} public string InstallPath
{
get { return _installPath; }
} public string NormalizedClientScriptPath
{
get { return _lowerCasedClientScriptPathWithTrailingSlash; }
} public string NormalizedVirtualPath
{
get { return _lowerCasedVirtualPathWithTrailingSlash; }
} public string PhysicalClientScriptPath
{
get { return _physicalClientScriptPath; }
} public string PhysicalPath
{
get { return _physicalPath; }
} public int Port
{
get { return _port; }
} public bool RequireAuthentication
{
get { return _requireAuthentication; }
} public string VirtualPath
{
get { return _virtualPath; }
} #region IRegisteredObject Members void IRegisteredObject.Stop(bool immediate)
{
// Unhook the Host so Server will process the requests in the new appdomain. if (_server != null)
{
_server.HostStopped();
} // Make sure all the pending calls complete before this Object is unregistered.
WaitForPendingCallsToFinish(); HostingEnvironment.UnregisterObject(this); Thread.Sleep();
HttpRuntime.Close();
Thread.Sleep();
} #endregion public void Configure(Server server, int port, string virtualPath, string physicalPath,
bool requireAuthentication)
{
Configure(server, port, virtualPath, physicalPath, requireAuthentication, false);
} public void Configure(Server server, int port, string virtualPath, string physicalPath)
{
Configure(server, port, virtualPath, physicalPath, false, false);
} public void Configure(Server server, int port, string virtualPath, string physicalPath,
bool requireAuthentication, bool disableDirectoryListing)
{
_server = server; _port = port;
_installPath = null;
_virtualPath = virtualPath;
_requireAuthentication = requireAuthentication;
_disableDirectoryListing = disableDirectoryListing;
_lowerCasedVirtualPath = CultureInfo.InvariantCulture.TextInfo.ToLower(_virtualPath);
_lowerCasedVirtualPathWithTrailingSlash = virtualPath.EndsWith("/", StringComparison.Ordinal)
? virtualPath
: virtualPath + "/";
_lowerCasedVirtualPathWithTrailingSlash =
CultureInfo.InvariantCulture.TextInfo.ToLower(_lowerCasedVirtualPathWithTrailingSlash);
_physicalPath = physicalPath;
_physicalClientScriptPath = HttpRuntime.AspClientScriptPhysicalPath + "\\";
_lowerCasedClientScriptPathWithTrailingSlash =
CultureInfo.InvariantCulture.TextInfo.ToLower(HttpRuntime.AspClientScriptVirtualPath + "/");
} public SecurityIdentifier GetProcessSid()
{
using (WindowsIdentity identity = new WindowsIdentity(_server.GetProcessToken()))
{
return identity.User;
}
} public IntPtr GetProcessToken()
{
new SecurityPermission(PermissionState.Unrestricted).Assert();
return _server.GetProcessToken();
} public string GetProcessUser()
{
return _server.GetProcessUser();
} public override object InitializeLifetimeService()
{
// never expire the license
return null;
} public bool IsVirtualPathAppPath(string path)
{
if (path == null)
{
return false;
}
path = CultureInfo.InvariantCulture.TextInfo.ToLower(path);
return (path == _lowerCasedVirtualPath || path == _lowerCasedVirtualPathWithTrailingSlash);
} public bool IsVirtualPathInApp(string path, out bool isClientScriptPath)
{
isClientScriptPath = false; if (path == null)
{
return false;
} if (_virtualPath == "/" && path.StartsWith("/", StringComparison.Ordinal))
{
if (path.StartsWith(_lowerCasedClientScriptPathWithTrailingSlash, StringComparison.Ordinal))
{
isClientScriptPath = true;
}
return true;
} path = CultureInfo.InvariantCulture.TextInfo.ToLower(path); if (path.StartsWith(_lowerCasedVirtualPathWithTrailingSlash, StringComparison.Ordinal))
{
return true;
} if (path == _lowerCasedVirtualPath)
{
return true;
} if (path.StartsWith(_lowerCasedClientScriptPathWithTrailingSlash, StringComparison.Ordinal))
{
isClientScriptPath = true;
return true;
} return false;
} public bool IsVirtualPathInApp(String path)
{
bool isClientScriptPath;
return IsVirtualPathInApp(path, out isClientScriptPath);
} public void ProcessRequest(Connection conn,string dfPage)
{
// Add a pending call to make sure our thread doesn't get killed
AddPendingCall(); try
{
new Request(_server, this, conn, dfPage).Process();
}
finally
{
RemovePendingCall();
}
} [SecurityPermission(SecurityAction.Assert, Unrestricted = true)]
public void Shutdown()
{
HostingEnvironment.InitiateShutdown();
} private void AddPendingCall()
{
//TODO: investigate this issue - ref var not volitile
#pragma warning disable 0420
Interlocked.Increment(ref _pendingCallsCount);
#pragma warning restore 0420
} private void RemovePendingCall()
{
//TODO: investigate this issue - ref var not volitile
#pragma warning disable 0420
Interlocked.Decrement(ref _pendingCallsCount);
#pragma warning restore 0420
} private void WaitForPendingCallsToFinish()
{
for (; ; )
{
if (_pendingCallsCount <= )
{
break;
} Thread.Sleep();
}
}
}
}
Host类
// **********************************************************************************
// CassiniDev - http://cassinidev.codeplex.com
//
// Copyright (c) 2010 Sky Sanders. All rights reserved.
//
// This source code is subject to terms and conditions of the Microsoft Public
// License (Ms-PL). A copy of the license can be found in the license.txt file
// included in this distribution.
//
// You must not remove this notice, or any other, from this software.
//
// ********************************************************************************** #region using System;
using System.Runtime.InteropServices; #endregion namespace SimpleWebServer
{
internal static class Interop
{
#region Structs [DllImport("SECUR32.DLL", CharSet = CharSet.Unicode)]
public static extern int AcceptSecurityContext(ref SecHandle phCredential, IntPtr phContext,
ref SecBufferDesc pInput, uint fContextReq, uint TargetDataRep,
ref SecHandle phNewContext, ref SecBufferDesc pOutput,
ref uint pfContextAttr, ref long ptsTimeStamp); [DllImport("SECUR32.DLL", CharSet = CharSet.Unicode)]
public static extern int AcquireCredentialsHandle(string pszPrincipal, string pszPackage, uint fCredentialUse,
IntPtr pvLogonID, IntPtr pAuthData, IntPtr pGetKeyFn,
IntPtr pvGetKeyArgument, ref SecHandle phCredential,
ref long ptsExpiry); [DllImport("KERNEL32.DLL", CharSet = CharSet.Unicode)]
public static extern int CloseHandle(IntPtr phToken); [DllImport("SECUR32.DLL", CharSet = CharSet.Unicode)]
public static extern int DeleteSecurityContext(ref SecHandle phContext); /// <summary>
/// FIX: #12506
/// </summary>
[DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)]
public static extern int FindMimeFromData(IntPtr pBC, [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1,
SizeParamIndex = )] byte[] pBuffer, int cbSize,
[MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed,
int dwMimeFlags, out IntPtr ppwzMimeOut, int dwReserved); [DllImport("SECUR32.DLL", CharSet = CharSet.Unicode)]
public static extern int FreeCredentialsHandle(ref SecHandle phCredential); [DllImport("kernel32.dll", EntryPoint = "GetConsoleScreenBufferInfo", SetLastError = true,
CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int GetConsoleScreenBufferInfo(int hConsoleOutput,
ref CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo); [DllImport("KERNEL32.DLL", SetLastError = true)]
public static extern IntPtr GetCurrentThread(); [DllImport("kernel32.dll", EntryPoint = "GetStdHandle", SetLastError = true, CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
public static extern int GetStdHandle(int nStdHandle); [DllImport("ADVAPI32.DLL", SetLastError = true)]
public static extern bool ImpersonateSelf(int level); [DllImport("ADVAPI32.DLL", SetLastError = true)]
public static extern int OpenThreadToken(IntPtr thread, int access, bool openAsSelf, ref IntPtr hToken); [DllImport("SECUR32.DLL", CharSet = CharSet.Unicode)]
public static extern int QuerySecurityContextToken(ref SecHandle phContext, ref IntPtr phToken); [DllImport("ADVAPI32.DLL", SetLastError = true)]
public static extern int RevertToSelf(); #region Nested type: CONSOLE_SCREEN_BUFFER_INFO public struct CONSOLE_SCREEN_BUFFER_INFO
{
internal COORD dwCursorPosition;
internal COORD dwMaximumWindowSize;
internal COORD dwSize;
internal SMALL_RECT srWindow;
internal Int16 wAttributes;
} #endregion #region Nested type: COORD public struct COORD
{
internal Int16 x;
internal Int16 y;
} #endregion #region Nested type: SecBuffer [StructLayout(LayoutKind.Sequential)]
public struct SecBuffer
{
// ReSharper disable InconsistentNaming
public uint cbBuffer;
public uint BufferType;
public IntPtr pvBuffer;
// ReSharper restore InconsistentNaming
} #endregion #region Nested type: SecBufferDesc [StructLayout(LayoutKind.Sequential)]
public struct SecBufferDesc
{
// ReSharper disable InconsistentNaming
public uint ulVersion;
public uint cBuffers;
public IntPtr pBuffers;
// ReSharper restore InconsistentNaming
} #endregion #region Nested type: SecHandle [StructLayout(LayoutKind.Sequential)]
public struct SecHandle
{
// ReSharper disable InconsistentNaming
public IntPtr dwLower;
public IntPtr dwUpper;
// ReSharper restore InconsistentNaming
} #endregion #region Nested type: SMALL_RECT public struct SMALL_RECT
{
internal Int16 Bottom;
internal Int16 Left;
internal Int16 Right;
internal Int16 Top;
} #endregion #endregion
}
}
Interop
// **********************************************************************************
// CassiniDev - http://cassinidev.codeplex.com
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is subject to terms and conditions of the Microsoft Public
// License (Ms-PL). A copy of the license can be found in the license.txt file
// included in this distribution.
//
// You must not remove this notice, or any other, from this software.
//
// ********************************************************************************** #region using System.IO;
using System.Text;
using System.Web; #endregion namespace SimpleWebServer
{
/// <summary>
/// TODO: get this into resources
/// </summary>
internal static class Messages
{
private const string _dirListingDirFormat =
@"{0,38:dddd, MMMM dd, yyyy hh:mm tt} <dir> <A href=""{1}/"">{2}</A>
"; private const string _dirListingFileFormat =
@"{0,38:dddd, MMMM dd, yyyy hh:mm tt} {1,12:n0} <A href=""{2}"">{3}</A>
"; private const string _dirListingFormat1 =
@"<html>
<head>
<title>Directory Listing -- {0}</title>
"; private const string _dirListingFormat2 =
@" </head>
<body bgcolor=""white""> <h2> <i>Directory Listing -- {0}</i> </h2></span> <hr width=100% size=1 color=silver> <PRE>
"; private const string _dirListingParentFormat =
@"<A href=""{0}"">[To Parent Directory]</A> "; private const string _httpErrorFormat1 =
@"<html>
<head>
<title>{0}</title>
"; private const string _httpStyle =
@" <style>
body {font-family:""Verdana"";font-weight:normal;font-size: 8pt;color:black;}
p {font-family:""Verdana"";font-weight:normal;color:black;margin-top: -5px}
b {font-family:""Verdana"";font-weight:bold;color:black;margin-top: -5px}
h1 { font-family:""Verdana"";font-weight:normal;font-size:18pt;color:red }
h2 { font-family:""Verdana"";font-weight:normal;font-size:14pt;color:maroon }
pre {font-family:""Lucida Console"";font-size: 8pt}
.marker {font-weight: bold; color: black;text-decoration: none;}
.version {color: gray;}
.error {margin-bottom: 10px;}
.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }
</style>
"; private static readonly string _dirListingTail =
@"</PRE>
<hr width=100% size=1 color=silver> <b>Version Information:</b> CassiniDev Web Server " +
VersionString + @" </font> </body>
</html>
"; private static readonly string _httpErrorFormat2 =
@" </head>
<body bgcolor=""white""> <span><h1>Server Error in '{0}' Application.<hr width=100% size=1 color=silver></h1> <h2> <i>HTTP Error {1} - {2}.</i> </h2></span> <hr width=100% size=1 color=silver> <b>Version Information:</b> CassiniDev Web Server " +
VersionString + @" </font> </body>
</html>
"; public static string VersionString = typeof (Server).Assembly.GetName().Version.ToString(); public static string FormatDirectoryListing(string dirPath, string parentPath, FileSystemInfo[] elements)
{
StringBuilder sb = new StringBuilder(); sb.Append(string.Format(_dirListingFormat1, dirPath));
sb.Append(_httpStyle);
sb.Append(string.Format(_dirListingFormat2, dirPath)); if (parentPath != null)
{
if (!parentPath.EndsWith("/"))
{
parentPath += "/";
} sb.Append(string.Format(_dirListingParentFormat, parentPath));
} if (elements != null)
{
for (int i = ; i < elements.Length; i++)
{
if (elements[i] is FileInfo)
{
FileInfo fi = (FileInfo) elements[i];
sb.Append(string.Format(_dirListingFileFormat,
fi.LastWriteTime, fi.Length, fi.Name, fi.Name));
}
else if (elements[i] is DirectoryInfo)
{
DirectoryInfo di = (DirectoryInfo) elements[i];
sb.Append(string.Format(_dirListingDirFormat,
di.LastWriteTime, di.Name, di.Name));
}
}
} sb.Append(_dirListingTail);
return sb.ToString();
} public static string FormatErrorMessageBody(int statusCode, string appName)
{
string desc = HttpWorkerRequest.GetStatusDescription(statusCode); return string.Format(_httpErrorFormat1, desc)
+ _httpStyle
+ string.Format(_httpErrorFormat2, appName, statusCode, desc);
}
}
}
Messages
// **********************************************************************************
// CassiniDev - http://cassinidev.codeplex.com
//
// Copyright (c) 2010 Sky Sanders. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is subject to terms and conditions of the Microsoft Public
// License (Ms-PL). A copy of the license can be found in the license.txt file
// included in this distribution.
//
// You must not remove this notice, or any other, from this software.
//
// ********************************************************************************** #region using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Web;
using System.Web.Hosting;
using Microsoft.Win32.SafeHandles;
using System.Security.Principal; #endregion namespace SimpleWebServer
{
public class Request : SimpleWorkerRequest
{
private const int MaxChunkLength = * ; private const int MaxHeaderBytes = * ; private static readonly char[] BadPathChars = new[] { '%', '>', '<', ':', '\\' }; private static readonly string[] DefaultFileNames = new[] { "default.aspx", "default.htm", "default.html" }; private static readonly char[] IntToHex = new[]
{
'', '', '', '', '', '', '', '', '', '', 'a', 'b', 'c', 'd', 'e', 'f'
}; private static readonly string[] RestrictedDirs = new[]
{
"/bin",
"/app_browsers",
"/app_code",
"/app_data",
"/app_localresources",
"/app_globalresources",
"/app_webreferences"
}; private readonly IStackWalk _connectionPermission = new PermissionSet(PermissionState.Unrestricted);
private readonly Host _host;
private readonly Server _server; private string _allRawHeaders; private byte[] _body; private int _bodyLength; private Connection _connection; private int _contentLength; // security permission to Assert remoting calls to _connection
private int _endHeadersOffset; private string _filePath; private byte[] _headerBytes; private List<ByteString> _headerByteStrings; private bool _headersSent; // parsed request data private bool _isClientScriptPath; private string[] _knownRequestHeaders; private string _path; private string _pathInfo; private string _pathTranslated; private string _protocol; private string _queryString;
private byte[] _queryStringBytes; private List<byte[]> _responseBodyBytes; private StringBuilder _responseHeadersBuilder; private int _responseStatus; private bool _specialCaseStaticFileHeaders; private int _startHeadersOffset; private string[][] _unknownRequestHeaders; private string _url; private string _verb; private string _dfPage; public Request(Server server, Host host, Connection connection,string dfPage)
: base(String.Empty, String.Empty, null)
{
_connectionPermission = new PermissionSet(PermissionState.Unrestricted);
_server = server;
_host = host;
_connection = connection;
_dfPage = dfPage;
} public override void CloseConnection()
{
_connectionPermission.Assert();
_connection.Close();
} public override void EndOfRequest()
{
Connection conn = _connection;
if (conn != null)
{
_connection = null;
_server.OnRequestEnd(conn);
} } public override void FlushResponse(bool finalFlush)
{
if (_responseStatus == && !_headersSent && finalFlush && _verb == "GET")
{ // attempt directory listing
if (ProcessDirectoryListingRequest())
{
return;
}
} _connectionPermission.Assert(); if (!_headersSent)
{
_connection.WriteHeaders(_responseStatus, _responseHeadersBuilder.ToString()); _headersSent = true;
}
foreach (byte[] bytes in _responseBodyBytes)
{
_connection.WriteBody(bytes, , bytes.Length);
} _responseBodyBytes = new List<byte[]>(); if (finalFlush)
{
_connection.Close();
}
} public override string GetAppPath()
{
return _host.VirtualPath;
} public override string GetAppPathTranslated()
{
return _host.PhysicalPath;
} public override string GetFilePath()
{
return _filePath;
} public override string GetFilePathTranslated()
{
return _pathTranslated;
} public override string GetHttpVerbName()
{
return _verb;
} public override string GetHttpVersion()
{
return _protocol;
} public override string GetKnownRequestHeader(int index)
{
return _knownRequestHeaders[index];
} public override string GetLocalAddress()
{
_connectionPermission.Assert();
return _connection.LocalIP;
} public override int GetLocalPort()
{
return _host.Port;
} public override string GetPathInfo()
{
return _pathInfo;
} public override byte[] GetPreloadedEntityBody()
{
return _body;
} public override string GetQueryString()
{
return _queryString;
} public override byte[] GetQueryStringRawBytes()
{
return _queryStringBytes;
} public override string GetRawUrl()
{
return _url;
} public override string GetRemoteAddress()
{
_connectionPermission.Assert();
return _connection.RemoteIP;
} public override int GetRemotePort()
{
return ;
} public override string GetServerName()
{
string localAddress = GetLocalAddress();
if (localAddress.Equals("127.0.0.1"))
{
return "localhost";
}
return localAddress;
} public override string GetServerVariable(string name)
{
string processUser = string.Empty;
string str2 = name;
if (str2 == null)
{
return processUser;
}
if (str2 != "ALL_RAW")
{
if (str2 != "SERVER_PROTOCOL")
{
if (str2 == "LOGON_USER")
{
if (GetUserToken() != IntPtr.Zero)
{
processUser = _host.GetProcessUser();
}
return processUser;
}
if ((str2 == "AUTH_TYPE") && (GetUserToken() != IntPtr.Zero))
{
processUser = "NTLM";
}
return processUser;
}
}
else
{
return _allRawHeaders;
}
return _protocol;
} public override string GetUnknownRequestHeader(string name)
{
int n = _unknownRequestHeaders.Length; for (int i = ; i < n; i++)
{
if (string.Compare(name, _unknownRequestHeaders[i][], StringComparison.OrdinalIgnoreCase) == )
{
return _unknownRequestHeaders[i][];
}
} return null;
} public override string[][] GetUnknownRequestHeaders()
{
return _unknownRequestHeaders;
} ///////////////////////////////////////////////////////////////////////////////////////////////
// Implementation of HttpWorkerRequest public override string GetUriPath()
{
return _path;
} public Connection GetConnection()
{
return _connection;
} public override bool HeadersSent()
{
return _headersSent;
} public override bool IsClientConnected()
{
_connectionPermission.Assert();
return _connection.Connected;
} public override bool IsEntireEntityBodyIsPreloaded()
{
return (_contentLength == _bodyLength);
} public override string MapPath(string path)
{
string mappedPath;
bool isClientScriptPath; if (string.IsNullOrEmpty(path) || path.Equals("/"))
{
// asking for the site root
mappedPath = _host.VirtualPath == "/" ? _host.PhysicalPath : Environment.SystemDirectory;
}
else if (_host.IsVirtualPathAppPath(path))
{
// application path
mappedPath = _host.PhysicalPath;
}
else if (_host.IsVirtualPathInApp(path, out isClientScriptPath))
{
if (isClientScriptPath)
{
mappedPath = _host.PhysicalClientScriptPath +
path.Substring(_host.NormalizedClientScriptPath.Length);
}
else
{
// inside app but not the app path itself
mappedPath = _host.PhysicalPath + path.Substring(_host.NormalizedVirtualPath.Length);
}
}
else
{
// outside of app -- make relative to app path
if (path.StartsWith("/", StringComparison.Ordinal))
{
mappedPath = _host.PhysicalPath + path.Substring();
}
else
{
mappedPath = _host.PhysicalPath + path;
}
} mappedPath = mappedPath.Replace('/', '\\'); if (mappedPath.EndsWith("\\", StringComparison.Ordinal) &&
!mappedPath.EndsWith(":\\", StringComparison.Ordinal))
{
mappedPath = mappedPath.Substring(, mappedPath.Length - );
} return mappedPath;
} [AspNetHostingPermission(SecurityAction.Assert, Level = AspNetHostingPermissionLevel.Medium)]
public void Process()
{
// read the request
if (!TryParseRequest())
{
return;
} // 100 response to POST
if (_verb == "POST" && _contentLength > && _bodyLength < _contentLength)
{
_connection.Write100Continue();
}
if (!_host.RequireAuthentication)
{
// special case for client script
if (_isClientScriptPath)
{
_connection.WriteEntireResponseFromFile(
_host.PhysicalClientScriptPath + _path.Substring(_host.NormalizedClientScriptPath.Length), false);
return;
} // deny access to code, bin, etc.
if (IsRequestForRestrictedDirectory())
{
_connection.WriteErrorAndClose();
return;
} // special case for a request to a directory (ensure / at the end and process default documents)
if (ProcessDirectoryRequest())
{
return;
} PrepareResponse(); // Hand the processing over to HttpRuntime
HttpRuntime.ProcessRequest(this);
}
} public override int ReadEntityBody(byte[] buffer, int size)
{
int bytesRead = ; _connectionPermission.Assert();
byte[] bytes = _connection.ReadRequestBytes(size); if (bytes != null && bytes.Length > )
{
bytesRead = bytes.Length;
Buffer.BlockCopy(bytes, , buffer, , bytesRead);
} return bytesRead;
} public override void SendCalculatedContentLength(int contentLength)
{
if (!_headersSent)
{
_responseHeadersBuilder.Append("Content-Length: ");
_responseHeadersBuilder.Append(contentLength.ToString(CultureInfo.InvariantCulture));
_responseHeadersBuilder.Append("\r\n");
}
} public override void SendKnownResponseHeader(int index, string value)
{
if (_headersSent)
{
return;
} switch (index)
{
case HeaderServer:
case HeaderDate:
case HeaderConnection:
// ignore these
return;
case HeaderAcceptRanges:
// FIX: #14359
if (value != "bytes")
{
// use this header to detect when we're processing a static file
break;
}
_specialCaseStaticFileHeaders = true;
return; case HeaderExpires:
case HeaderLastModified:
// FIX: #14359
if (!_specialCaseStaticFileHeaders)
{
// NOTE: Ignore these for static files. These are generated
// by the StaticFileHandler, but they shouldn't be.
break;
}
return; // FIX: #12506
case HeaderContentType: string contentType = null; if (value == "application/octet-stream")
{
// application/octet-stream is default for unknown so lets
// take a shot at determining the type.
// don't do this for other content-types as you are going to
// end up sending text/plain for endpoints that are handled by
// asp.net such as .aspx, .asmx, .axd, etc etc
contentType = CommonExtensions.GetContentType(_pathTranslated);
}
value = contentType ?? value;
break;
} _responseHeadersBuilder.Append(GetKnownResponseHeaderName(index));
_responseHeadersBuilder.Append(": ");
_responseHeadersBuilder.Append(value);
_responseHeadersBuilder.Append("\r\n");
} public void SetResponseHeader(string name, string value)
{
_responseHeadersBuilder.Append(name);
_responseHeadersBuilder.Append(": ");
_responseHeadersBuilder.Append(value);
_responseHeadersBuilder.Append("\r\n");
} public override void SendResponseFromFile(string filename, long offset, long length)
{
if (length == )
{
return;
} FileStream f = null;
try
{
f = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
SendResponseFromFileStream(f, offset, length);
}
finally
{
if (f != null)
{
f.Close();
}
}
} public override void SendResponseFromFile(IntPtr handle, long offset, long length)
{
if (length == )
{
return;
} using (var sfh = new SafeFileHandle(handle, false))
{
using (var f = new FileStream(sfh, FileAccess.Read))
{
SendResponseFromFileStream(f, offset, length);
}
}
} public override void SendResponseFromMemory(byte[] data, int length)
{
if (length > )
{
var bytes = new byte[length]; Buffer.BlockCopy(data, , bytes, , length);
_responseBodyBytes.Add(bytes);
}
} public override void SendStatus(int statusCode, string statusDescription)
{
_responseStatus = statusCode;
} public override void SendUnknownResponseHeader(string name, string value)
{
if (_headersSent)
return; _responseHeadersBuilder.Append(name);
_responseHeadersBuilder.Append(": ");
_responseHeadersBuilder.Append(value);
_responseHeadersBuilder.Append("\r\n");
} private bool IsBadPath()
{
if (_path.IndexOfAny(BadPathChars) >= )
{
return true;
} if (CultureInfo.InvariantCulture.CompareInfo.IndexOf(_path, "..", CompareOptions.Ordinal) >= )
{
return true;
} if (CultureInfo.InvariantCulture.CompareInfo.IndexOf(_path, "//", CompareOptions.Ordinal) >= )
{
return true;
} return false;
} private bool IsRequestForRestrictedDirectory()
{
String p = CultureInfo.InvariantCulture.TextInfo.ToLower(_path); if (_host.VirtualPath != "/")
{
p = p.Substring(_host.VirtualPath.Length);
} foreach (String dir in RestrictedDirs)
{
if (p.StartsWith(dir, StringComparison.Ordinal))
{
if (p.Length == dir.Length || p[dir.Length] == '/')
{
return true;
}
}
} return false;
} private void ParseHeaders()
{
_knownRequestHeaders = new string[RequestHeaderMaximum]; // construct unknown headers as array list of name1,value1,...
var headers = new List<string>(); for (int i = ; i < _headerByteStrings.Count; i++)
{
string s = _headerByteStrings[i].GetString(); int c = s.IndexOf(':'); if (c >= )
{
string name = s.Substring(, c).Trim();
string value = s.Substring(c + ).Trim(); // remember
int knownIndex = GetKnownRequestHeaderIndex(name);
if (knownIndex >= )
{
_knownRequestHeaders[knownIndex] = value;
}
else
{
headers.Add(name);
headers.Add(value);
}
}
} // copy to array unknown headers int n = headers.Count / ;
_unknownRequestHeaders = new string[n][];
int j = ; for (int i = ; i < n; i++)
{
_unknownRequestHeaders[i] = new string[];
_unknownRequestHeaders[i][] = headers[j++];
_unknownRequestHeaders[i][] = headers[j++];
} // remember all raw headers as one string if (_headerByteStrings.Count > )
{
_allRawHeaders = Encoding.UTF8.GetString(_headerBytes, _startHeadersOffset,
_endHeadersOffset - _startHeadersOffset);
}
else
{
_allRawHeaders = String.Empty;
}
} private void ParsePostedContent()
{
_contentLength = ;
_bodyLength = ; string contentLengthValue = _knownRequestHeaders[HeaderContentLength];
if (contentLengthValue != null)
{
try
{
_contentLength = Int32.Parse(contentLengthValue, CultureInfo.InvariantCulture);
}
// ReSharper disable EmptyGeneralCatchClause
catch
// ReSharper restore EmptyGeneralCatchClause
{
}
} if (_headerBytes.Length > _endHeadersOffset)
{
_bodyLength = _headerBytes.Length - _endHeadersOffset; if (_bodyLength > _contentLength)
{
_bodyLength = _contentLength; // don't read more than the content-length
} if (_bodyLength > )
{
_body = new byte[_bodyLength];
Buffer.BlockCopy(_headerBytes, _endHeadersOffset, _body, , _bodyLength);
}
}
} private void ParseRequestLine()
{
ByteString requestLine = _headerByteStrings[];
ByteString[] elems = requestLine.Split(' '); if (elems == null || elems.Length < || elems.Length > )
{
_connection.WriteErrorAndClose();
return;
} _verb = elems[].GetString(); ByteString urlBytes = elems[];
_url = urlBytes.GetString(); _protocol = elems.Length == ? elems[].GetString() : "HTTP/1.0"; // query string int iqs = urlBytes.IndexOf('?');
_queryStringBytes = iqs > ? urlBytes.Substring(iqs + ).GetBytes() : new byte[]; iqs = _url.IndexOf('?');
if (_url == "/" && !String.IsNullOrEmpty(_dfPage))
_path = _dfPage;
else if (iqs > )
{
_path = _url.Substring(, iqs);
_queryString = _url.Substring(iqs + );
}
else
{
_path = _url;
_queryStringBytes = new byte[];
} // url-decode path if (_path.IndexOf('%') >= )
{
_path = HttpUtility.UrlDecode(_path, Encoding.UTF8); iqs = _url.IndexOf('?');
if (iqs >= )
{
_url = _path + _url.Substring(iqs);
}
else
{
_url = _path;
}
} // path info int lastDot = _path.LastIndexOf('.');
int lastSlh = _path.LastIndexOf('/'); if (lastDot >= && lastSlh >= && lastDot < lastSlh)
{
int ipi = _path.IndexOf('/', lastDot);
_filePath = _path.Substring(, ipi);
_pathInfo = _path.Substring(ipi);
}
else
{
_filePath = _path;
_pathInfo = String.Empty;
} _pathTranslated = MapPath(_filePath); } private void PrepareResponse()
{
_headersSent = false;
_responseStatus = ;
_responseHeadersBuilder = new StringBuilder();
_responseBodyBytes = new List<byte[]>(); ProcessPlugins();
} private bool ProcessDirectoryListingRequest()
{
if (_verb != "GET")
{
return false;
} String dirPathTranslated = _pathTranslated; if (_pathInfo.Length > )
{
// directory path can never have pathInfo
dirPathTranslated = MapPath(_path);
} if (!Directory.Exists(dirPathTranslated))
{
return false;
} // get all files and subdirs
FileSystemInfo[] infos = null;
try
{
infos = (new DirectoryInfo(dirPathTranslated)).GetFileSystemInfos();
}
// ReSharper disable EmptyGeneralCatchClause
catch
// ReSharper restore EmptyGeneralCatchClause
{
} // determine if parent is appropriate
string parentPath = null; if (_path.Length > )
{
int i = _path.LastIndexOf('/', _path.Length - ); parentPath = (i > ) ? _path.Substring(, i) : "/";
if (!_host.IsVirtualPathInApp(parentPath))
{
parentPath = null;
}
} _connection.WriteEntireResponseFromString(, "Content-type: text/html; charset=utf-8\r\n",
Messages.FormatDirectoryListing(_path, parentPath, infos),
false);
return true;
} private bool ProcessDirectoryRequest()
{
String dirPathTranslated = _pathTranslated; if (_pathInfo.Length > )
{
// directory path can never have pathInfo
dirPathTranslated = MapPath(_path);
} if (!Directory.Exists(dirPathTranslated))
{
return false;
} // have to redirect /foo to /foo/ to allow relative links to work
if (!_path.EndsWith("/", StringComparison.Ordinal))
{
string newPath = _path + "/";
string location = "Location: " + UrlEncodeRedirect(newPath) + "\r\n";
string body = "<html><head><title>Object moved</title></head><body>\r\n" +
"<h2>Object moved to <a href='" + newPath + "'>here</a>.</h2>\r\n" +
"</body></html>\r\n"; _connection.WriteEntireResponseFromString(, location, body, false);
return true;
} // check for the default file
foreach (string filename in DefaultFileNames)
{
string defaultFilePath = dirPathTranslated + "\\" + filename; if (File.Exists(defaultFilePath))
{
// pretend the request is for the default file path
_path += filename;
_filePath = _path;
_url = (_queryString != null) ? (_path + "?" + _queryString) : _path;
_pathTranslated = defaultFilePath;
return false; // go through normal processing
}
} return false; // go through normal processing
} private void ReadAllHeaders()
{
_headerBytes = null; do
{
if (!TryReadAllHeaders())
{
// something bad happened
break;
}
} while (_endHeadersOffset < ); // found \r\n\r\n } private void Reset()
{
_headerBytes = null;
_startHeadersOffset = ;
_endHeadersOffset = ;
_headerByteStrings = null; _isClientScriptPath = false; _verb = null;
_url = null;
_protocol = null; _path = null;
_filePath = null;
_pathInfo = null;
_pathTranslated = null;
_queryString = null;
_queryStringBytes = null; _contentLength = ;
_bodyLength = ;
_body = null; _allRawHeaders = null;
_unknownRequestHeaders = null;
_knownRequestHeaders = null;
_specialCaseStaticFileHeaders = false;
} private void SendResponseFromFileStream(Stream f, long offset, long length)
{
long fileSize = f.Length; if (length == -)
{
length = fileSize - offset;
} if (length == || offset < || length > fileSize - offset)
{
return;
} if (offset > )
{
f.Seek(offset, SeekOrigin.Begin);
} if (length <= MaxChunkLength)
{
var fileBytes = new byte[(int)length];
int bytesRead = f.Read(fileBytes, , (int)length);
SendResponseFromMemory(fileBytes, bytesRead);
}
else
{
var chunk = new byte[MaxChunkLength];
var bytesRemaining = (int)length; while (bytesRemaining > )
{
int bytesToRead = (bytesRemaining < MaxChunkLength) ? bytesRemaining : MaxChunkLength;
int bytesRead = f.Read(chunk, , bytesToRead); SendResponseFromMemory(chunk, bytesRead);
bytesRemaining -= bytesRead; // flush to release keep memory
if ((bytesRemaining > ) && (bytesRead > ))
{
FlushResponse(false);
}
}
}
} private void SkipAllPostedContent()
{
if ((_contentLength > ) && (_bodyLength < _contentLength))
{
byte[] buffer;
for (int i = _contentLength - _bodyLength; i > ; i -= buffer.Length)
{
buffer = _connection.ReadRequestBytes(i);
if ((buffer == null) || (buffer.Length == ))
{
return;
}
}
}
} /// <summary>
/// TODO: defer response until request is written
/// </summary>
/// <returns></returns>
private bool TryParseRequest()
{
Reset(); ReadAllHeaders(); if (_headerBytes == null || _endHeadersOffset < ||
_headerByteStrings == null || _headerByteStrings.Count == )
{
_connection.WriteErrorAndClose();
return false;
} ParseRequestLine(); // Check for bad path
if (IsBadPath())
{
_connection.WriteErrorAndClose();
return false;
} // Check if the path is not well formed or is not for the current app
if (!_host.IsVirtualPathInApp(_path, out _isClientScriptPath))
{
_connection.WriteErrorAndClose();
return false;
} ParseHeaders(); ParsePostedContent(); return true;
} private bool TryReadAllHeaders()
{
// read the first packet (up to 32K)
byte[] headerBytes = _connection.ReadRequestBytes(MaxHeaderBytes); if (headerBytes == null || headerBytes.Length == )
return false; if (_headerBytes != null)
{
// previous partial read
int len = headerBytes.Length + _headerBytes.Length;
if (len > MaxHeaderBytes)
return false; var bytes = new byte[len];
Buffer.BlockCopy(_headerBytes, , bytes, , _headerBytes.Length);
Buffer.BlockCopy(headerBytes, , bytes, _headerBytes.Length, headerBytes.Length);
_headerBytes = bytes;
}
else
{
_headerBytes = headerBytes;
} // start parsing
_startHeadersOffset = -;
_endHeadersOffset = -;
_headerByteStrings = new List<ByteString>(); // find the end of headers
var parser = new ByteParser(_headerBytes); for (; ; )
{
ByteString line = parser.ReadLine(); if (line == null)
{
break;
} if (_startHeadersOffset < )
{
_startHeadersOffset = parser.CurrentOffset;
} if (line.IsEmpty)
{
_endHeadersOffset = parser.CurrentOffset;
break;
} _headerByteStrings.Add(line);
} return true;
} private static string UrlEncodeRedirect(string path)
{
// this method mimics the logic in HttpResponse.Redirect (which relies on internal methods) // count non-ascii characters
byte[] bytes = Encoding.UTF8.GetBytes(path);
int count = bytes.Length;
int countNonAscii = ;
for (int i = ; i < count; i++)
{
if ((bytes[i] & 0x80) != )
{
countNonAscii++;
}
} // encode all non-ascii characters using UTF-8 %XX
if (countNonAscii > )
{
// expand not 'safe' characters into %XX, spaces to +s
var expandedBytes = new byte[count + countNonAscii * ];
int pos = ;
for (int i = ; i < count; i++)
{
byte b = bytes[i]; if ((b & 0x80) == )
{
expandedBytes[pos++] = b;
}
else
{
expandedBytes[pos++] = (byte)'%';
expandedBytes[pos++] = (byte)IntToHex[(b >> ) & 0xf];
expandedBytes[pos++] = (byte)IntToHex[b & 0xf];
}
} path = Encoding.ASCII.GetString(expandedBytes);
} // encode spaces into %20
if (path.IndexOf(' ') >= )
{
path = path.Replace(" ", "%20");
} return path;
} private void ProcessPlugins()
{
if (_connection.Plugins != null)
{
foreach (string pluginTypeName in _connection.Plugins)
{
// #TODO: maybe keep plugins instantiated in the connection with reflected method cached? Type pluginType = Type.GetType(pluginTypeName);
object plugin = Activator.CreateInstance(pluginType);
MethodInfo pluginMethod = plugin.GetType().GetMethod("ProcessRequest");
pluginMethod.Invoke(plugin, new object[] { this }); }
}
}
#region Nested type: ByteParser internal class ByteParser
{
private readonly byte[] _bytes; private int _pos; public ByteParser(byte[] bytes)
{
_bytes = bytes;
_pos = ;
} public int CurrentOffset
{
get { return _pos; }
} public ByteString ReadLine()
{
ByteString line = null; for (int i = _pos; i < _bytes.Length; i++)
{
if (_bytes[i] == (byte)'\n')
{
int len = i - _pos;
if (len > && _bytes[i - ] == (byte)'\r')
{
len--;
} line = new ByteString(_bytes, _pos, len);
_pos = i + ;
return line;
}
} if (_pos < _bytes.Length)
{
line = new ByteString(_bytes, _pos, _bytes.Length - _pos);
} _pos = _bytes.Length;
return line;
}
} #endregion #region Nested type: ByteString internal class ByteString
{
private readonly byte[] _bytes; private readonly int _length; private readonly int _offset; public ByteString(byte[] bytes, int offset, int length)
{
_bytes = bytes;
_offset = offset;
_length = length;
} public byte[] Bytes
{
get { return _bytes; }
} public bool IsEmpty
{
get { return (_bytes == null || _length == ); }
} public byte this[int index]
{
get { return _bytes[_offset + index]; }
} public int Length
{
get { return _length; }
} public int Offset
{
get { return _offset; }
} public byte[] GetBytes()
{
var bytes = new byte[_length];
if (_length > ) Buffer.BlockCopy(_bytes, _offset, bytes, , _length);
return bytes;
} public string GetString(Encoding enc)
{
if (IsEmpty) return string.Empty;
return enc.GetString(_bytes, _offset, _length);
} public string GetString()
{
return GetString(Encoding.UTF8);
} public int IndexOf(char ch)
{
return IndexOf(ch, );
} public int IndexOf(char ch, int offset)
{
for (int i = offset; i < _length; i++)
{
if (this[i] == (byte)ch) return i;
}
return -;
} public ByteString[] Split(char sep)
{
var list = new List<ByteString>(); int pos = ;
while (pos < _length)
{
int i = IndexOf(sep, pos);
if (i < )
{
break;
} list.Add(Substring(pos, i - pos));
pos = i + ; while (this[pos] == (byte)sep && pos < _length)
{
pos++;
}
} if (pos < _length)
list.Add(Substring(pos)); return list.ToArray();
} public ByteString Substring(int offset, int len)
{
return new ByteString(_bytes, _offset + offset, len);
} public ByteString Substring(int offset)
{
return Substring(offset, _length - offset);
}
} #endregion
}
}
Request
// **********************************************************************************
// CassiniDev - http://cassinidev.codeplex.com
//
// Copyright (c) 2010 Sky Sanders. All rights reserved.
//
// This source code is subject to terms and conditions of the Microsoft Public
// License (Ms-PL). A copy of the license can be found in the license.txt file
// included in this distribution.
//
// You must not remove this notice, or any other, from this software.
//
// ********************************************************************************** #region using System; #endregion namespace SimpleWebServer
{
///<summary>
///</summary>
public class RequestEventArgs : EventArgs
{
private readonly Guid _id; ///<summary>
///</summary>
///<param name="id"></param>
///<param name="requestLog"></param>
///<param name="responseLog"></param>
public RequestEventArgs(Guid id)
{
_id = id;
} ///<summary>
///</summary>
public Guid Id
{
get { return _id; }
} }
}
RequestEventArgs
Web服务器(CassiniDev的裁减版)的更多相关文章
- Nginx 0.8.x + PHP 5.2.13(FastCGI)搭建胜过Apache十倍的Web服务器(第6版)
前言:本文是我撰写的关于搭建“Nginx + PHP(FastCGI)”Web服务器的第6篇文章.本系列文章作为国内最早详细介绍 Nginx + PHP 安装.配置.使用的资料之一,为推动 Nginx ...
- Nginx 0.8.x + PHP 5.2.13(FastCGI)搭建胜过Apache十倍的Web服务器(第6版)(转)
转自:http://blog.s135.com/nginx_php_v6/] 前言:本文是我撰写的关于搭建“Nginx + PHP(FastCGI)”Web服务器的第6篇文章.本系列文章作为国内最早详 ...
- Nginx 0.8.x + PHP 5.2.13(FastCGI)搭建胜过Apache十倍的Web服务器(第6版)[原创]
mkdir -p /data0/software cd /data0/software wget http://sysoev.ru/nginx/nginx-0.8.46.tar.gz wget htt ...
- 手写一个Web服务器,极简版Tomcat
网络传输是通过遵守HTTP协议的数据格式来传输的. HTTP协议是由标准化组织W3C(World Wide Web Consortium,万维网联盟)和IETF(Internet Engineerin ...
- [转]三大WEB服务器对比分析(apache ,lighttpd,nginx)
原博文地址:http://www.blogjava.net/daniel-tu/archive/2008/12/29/248883.html 一.软件介绍(apache lighttpd ngin ...
- 三大WEB服务器对比分析(apache ,lighttpd,nginx)
一.软件介绍(apache lighttpd nginx) 1. lighttpd Lighttpd是一个具有非常低的内存开销,cpu占用率低,效能好,以及丰富的模块等特点.lighttpd是众多 ...
- [教程]安装青鸟云Web服务器
青鸟云Web服务器 支持的安装环境: Windows XP (32bit) Windows Server 2003/R2 (32bit) Windows 7 (32/64bit) Windows Se ...
- 转: 三大WEB服务器对比分析(apache ,lighttpd,nginx) (2008年的旧文,仅供参考之用)
from: http://www.blogjava.net/daniel-tu/archive/2008/12/29/248883.html 三大WEB服务器对比分析(apache ,lighttp ...
- (转)三大WEB服务器对比分析(apache ,lighttpd,nginx)
ref : https://www.iteye.com/blog/hai0378-1860220 一.软件介绍(apache lighttpd nginx) 1. lighttpd Light ...
随机推荐
- Oracle Exadata体系笔记
Exadata一开始是以一个存储系统形式诞生的,叫做SAGE(Storage Appliance for Grid Environ ments,网格环境存储设备) Exadata原本设计用来解决超 ...
- 如何调试Android Framework?
Linus有一句名言广为人知:Read the fucking source code. 但其实,要深入理解某个软件.框架或者系统的工作原理,仅仅「看」代码是远远不够的.就拿Android Frame ...
- 【转】使用Xcode中的iOS SDK给iphone开发出第一个App程序
之前已经折腾过用Xcode开发OS X的程序了,现在继续折腾,用iOS SDK开发移动设备(iphone/ipad/ipod touch)的程序. 1.从iOS Developer Library中找 ...
- jsonp实现跨域访问
要实现JSONP跨域访问,首先就要了解什么是跨域?然后JSONP与JSON的关系? 1.什么是跨域? 跨域简单的说就是一个域名下的程序和另一个域名下的程序做数据交互.比如说:现有一个http://ww ...
- EL表达式(胖先生版)
EL表达式没有指定范围,从最小范围开始 <% pageContext.setAttribute("shxt", "java web"); request. ...
- Oracle 安装 检查操作系统版本 必须是 5.0 5.1 的解决办法
打开 oraparam.ini文件 添加红色部分 Windows=5.1,5.2,6.1 最下面添加 [Windows-6.1-required]#Minimum display colours fo ...
- 开发框架XUtils
xUtils 包含了很多实用的android工具. xUtils 最初源于Afinal框架,进行了大量重构,使得xUtils支持大文件上传,更全面的http请求协议支持(10种谓词),拥有更加灵活的O ...
- Golang几个常用记录日志对比
go语言有一个标准库,log,提供了最基本的日志功能,但是没有什么高级的功能,如果需要高级的特性,就需要使用第三方包,下面是一些候选的包: go_tmlog https://code.google.c ...
- spring依赖注入原理剖析
PropertyDefinition.java package junit.test; public class PropertyDefinition { private String name; p ...
- Juniti学习总结
JUnit简介 JUnit是由 Erich Gamma和Kent Beck编写的一个回归测试框架(regression testing framework).JUnit测试是程序员测试,即所谓白盒测试 ...