Web服务器(CassiniDev的裁减版)

 做此程序的原因是将软件部署简化,省去IIS的麻烦部署,减少项目实施人员的工作量和工作复杂度

 

Server sv = new Server(8000, "/", @"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 != 80
                           ?
                               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>2</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>2</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() == 0)
                                        {
                                            conn.WriteErrorAndClose(400);
                                            return;
                                        }

                                        Host host = GetHost();

                                        if (host == null)
                                        {
                                            conn.WriteErrorAndClose(500);
                                            return;
                                        }

                                        //IncrementRequestCount();
                                        host.ProcessRequest(conn,_dfPage);
                                    }
                                });
                        }
                        catch
                        {
                            Thread.Sleep(100);
                        }
                    }
                });
        }


        /// <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(2))
            {
                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(100);
                }
            }
            // 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*3)
                .ToList();

            int byteAddress = 0;
            StringBuilder sb = new StringBuilder();

            for (int i = 0; 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 : 0;
            using (MemoryStream output = new MemoryStream(capacity))
            {
                int readLength;
                byte[] buffer = new byte[4096];

                do
                {
                    readLength = input.Read(buffer, 0, buffer.Length);
                    output.Write(buffer, 0, readLength);
                } while (readLength != 0);

                return output.ToArray();
            }
        }

        private static IList<string> SplitIntoChunks(this string text, int chunkSize)
        {
            List<string> chunks = new List<string>();
            int offset = 0;
            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 = 0,
        /// <summary>
        /// 
        /// </summary>
        Running
    }

    /// <summary>
    /// 
    /// </summary>
    public enum PortMode
    {
        /// <summary>
        /// 
        /// </summary>
        FirstAvailable = 0,
        /// <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 = 0,
        /// <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 = 403;

// ReSharper disable InconsistentNaming
        private const int HttpOK = 200;
// 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() == 0)
                {
                    return null;
                }

                int numBytes = _socket.Available;

                if (numBytes > maxBytes)
                {
                    numBytes = maxBytes;
                }

                int numReceived = 0;

                byte[] buffer = new byte[numBytes];

                if (numBytes > 0)
                {
                    numReceived = _socket.Receive(buffer, 0, numBytes, SocketFlags.None);
                }

                if (numReceived < numBytes)
                {
                    byte[] tempBuffer = new byte[numReceived];

                    if (numReceived > 0)
                    {
                        Buffer.BlockCopy(buffer, 0, tempBuffer, 0, numReceived);
                    }

                    buffer = tempBuffer;
                }

                return buffer;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public int WaitForRequestBytes()
        {
            int availBytes = 0;

            try
            {
                if (_socket.Available == 0)
                {
                    _socket.Poll(100000, SelectMode.SelectRead);

                    if (_socket.Available == 0 && _socket.Connected)
                    {
                        _socket.Poll(30000000, SelectMode.SelectRead);
                    }
                }

                availBytes = _socket.Available;
            }
                // ReSharper disable EmptyGeneralCatchClause
            catch
                // ReSharper restore EmptyGeneralCatchClause
            {
            }

            return availBytes;
        }

        /// <summary>
        /// 
        /// </summary>
        public void Write100Continue()
        {
            WriteEntireResponseFromString(100, null, null, true);
        }

        internal void Write200Continue()
        {
            WriteEntireResponseFromString(200, 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, 0, 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(404);
                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, 0, len);

                String headers = MakeResponseHeaders(HttpOK, contentTypeHeader, bytesRead, keepAlive);
                _socket.Send(Encoding.UTF8.GetBytes(headers));

                _socket.Send(fileBytes, 0, 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) : 0;
                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, -1, 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 >= 0)
            {
                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(100);
            HttpRuntime.Close();
            Thread.Sleep(100);
        }

        #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 <= 0)
                {
                    break;
                }

                Thread.Sleep(250);
            }
        }
    }
}
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 = 3)] 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}        &lt;dir&gt; <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>&nbsp;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>&nbsp;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 = 0; 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 = 64 * 1024;

        private const int MaxHeaderBytes = 32 * 1024;

        private static readonly char[] BadPathChars = new[] { '%', '>', '<', ':', '\\' };

        private static readonly string[] DefaultFileNames = new[] { "default.aspx", "default.htm", "default.html" };

        private static readonly char[] IntToHex = new[]
            {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '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 == 404 && !_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, 0, 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 0;
        }

        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 = 0; i < n; i++)
            {
                if (string.Compare(name, _unknownRequestHeaders[i][0], StringComparison.OrdinalIgnoreCase) == 0)
                {
                    return _unknownRequestHeaders[i][1];
                }
            }

            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(1);
                }
                else
                {
                    mappedPath = _host.PhysicalPath + path;
                }
            }

            mappedPath = mappedPath.Replace('/', '\\');

            if (mappedPath.EndsWith("\\", StringComparison.Ordinal) &&
                !mappedPath.EndsWith(":\\", StringComparison.Ordinal))
            {
                mappedPath = mappedPath.Substring(0, mappedPath.Length - 1);
            }

            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 > 0 && _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(403);
                    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 = 0;

            _connectionPermission.Assert();
            byte[] bytes = _connection.ReadRequestBytes(size);

            if (bytes != null && bytes.Length > 0)
            {
                bytesRead = bytes.Length;
                Buffer.BlockCopy(bytes, 0, buffer, 0, 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 == 0)
            {
                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 == 0)
            {
                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 > 0)
            {
                var bytes = new byte[length];

                Buffer.BlockCopy(data, 0, bytes, 0, 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) >= 0)
            {
                return true;
            }

            if (CultureInfo.InvariantCulture.CompareInfo.IndexOf(_path, "..", CompareOptions.Ordinal) >= 0)
            {
                return true;
            }

            if (CultureInfo.InvariantCulture.CompareInfo.IndexOf(_path, "//", CompareOptions.Ordinal) >= 0)
            {
                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 = 1; i < _headerByteStrings.Count; i++)
            {
                string s = _headerByteStrings[i].GetString();

                int c = s.IndexOf(':');

                if (c >= 0)
                {
                    string name = s.Substring(0, c).Trim();
                    string value = s.Substring(c + 1).Trim();

                    // remember
                    int knownIndex = GetKnownRequestHeaderIndex(name);
                    if (knownIndex >= 0)
                    {
                        _knownRequestHeaders[knownIndex] = value;
                    }
                    else
                    {
                        headers.Add(name);
                        headers.Add(value);
                    }
                }
            }

            // copy to array unknown headers

            int n = headers.Count / 2;
            _unknownRequestHeaders = new string[n][];
            int j = 0;

            for (int i = 0; i < n; i++)
            {
                _unknownRequestHeaders[i] = new string[2];
                _unknownRequestHeaders[i][0] = headers[j++];
                _unknownRequestHeaders[i][1] = headers[j++];
            }

            // remember all raw headers as one string

            if (_headerByteStrings.Count > 1)
            {
                _allRawHeaders = Encoding.UTF8.GetString(_headerBytes, _startHeadersOffset,
                                                         _endHeadersOffset - _startHeadersOffset);
            }
            else
            {
                _allRawHeaders = String.Empty;
            }
        }

        private void ParsePostedContent()
        {
            _contentLength = 0;
            _bodyLength = 0;

            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 > 0)
                {
                    _body = new byte[_bodyLength];
                    Buffer.BlockCopy(_headerBytes, _endHeadersOffset, _body, 0, _bodyLength);
                }
            }
        }

        private void ParseRequestLine()
        {
            ByteString requestLine = _headerByteStrings[0];
            ByteString[] elems = requestLine.Split(' ');

            if (elems == null || elems.Length < 2 || elems.Length > 3)
            {
                _connection.WriteErrorAndClose(400);
                return;
            }

            _verb = elems[0].GetString();

            ByteString urlBytes = elems[1];
            _url = urlBytes.GetString();

            _protocol = elems.Length == 3 ? elems[2].GetString() : "HTTP/1.0";

            // query string

            int iqs = urlBytes.IndexOf('?');
            _queryStringBytes = iqs > 0 ? urlBytes.Substring(iqs + 1).GetBytes() : new byte[0];

            iqs = _url.IndexOf('?');
            if (_url == "/" && !String.IsNullOrEmpty(_dfPage))
                _path = _dfPage;
            else if (iqs > 0)
            {
                _path = _url.Substring(0, iqs);
                _queryString = _url.Substring(iqs + 1);
            }
            else
            {
                _path = _url;
                _queryStringBytes = new byte[0];
            }

            // url-decode path

            if (_path.IndexOf('%') >= 0)
            {
                _path = HttpUtility.UrlDecode(_path, Encoding.UTF8);

                iqs = _url.IndexOf('?');
                if (iqs >= 0)
                {
                    _url = _path + _url.Substring(iqs);
                }
                else
                {
                    _url = _path;
                }
            }

            // path info

            int lastDot = _path.LastIndexOf('.');
            int lastSlh = _path.LastIndexOf('/');

            if (lastDot >= 0 && lastSlh >= 0 && lastDot < lastSlh)
            {
                int ipi = _path.IndexOf('/', lastDot);
                _filePath = _path.Substring(0, ipi);
                _pathInfo = _path.Substring(ipi);
            }
            else
            {
                _filePath = _path;
                _pathInfo = String.Empty;
            }

            _pathTranslated = MapPath(_filePath);

        }

        private void PrepareResponse()
        {
            _headersSent = false;
            _responseStatus = 200;
            _responseHeadersBuilder = new StringBuilder();
            _responseBodyBytes = new List<byte[]>();

            ProcessPlugins();
        }

        private bool ProcessDirectoryListingRequest()
        {
            if (_verb != "GET")
            {
                return false;
            }

            String dirPathTranslated = _pathTranslated;

            if (_pathInfo.Length > 0)
            {
                // 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 > 1)
            {
                int i = _path.LastIndexOf('/', _path.Length - 2);

                parentPath = (i > 0) ? _path.Substring(0, i) : "/";
                if (!_host.IsVirtualPathInApp(parentPath))
                {
                    parentPath = null;
                }
            }

            _connection.WriteEntireResponseFromString(200, "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 > 0)
            {
                // 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(302, 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 < 0); // found \r\n\r\n

        }

        private void Reset()
        {
            _headerBytes = null;
            _startHeadersOffset = 0;
            _endHeadersOffset = 0;
            _headerByteStrings = null;

            _isClientScriptPath = false;

            _verb = null;
            _url = null;
            _protocol = null;

            _path = null;
            _filePath = null;
            _pathInfo = null;
            _pathTranslated = null;
            _queryString = null;
            _queryStringBytes = null;

            _contentLength = 0;
            _bodyLength = 0;
            _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 == -1)
            {
                length = fileSize - offset;
            }

            if (length == 0 || offset < 0 || length > fileSize - offset)
            {
                return;
            }

            if (offset > 0)
            {
                f.Seek(offset, SeekOrigin.Begin);
            }

            if (length <= MaxChunkLength)
            {
                var fileBytes = new byte[(int)length];
                int bytesRead = f.Read(fileBytes, 0, (int)length);
                SendResponseFromMemory(fileBytes, bytesRead);
            }
            else
            {
                var chunk = new byte[MaxChunkLength];
                var bytesRemaining = (int)length;

                while (bytesRemaining > 0)
                {
                    int bytesToRead = (bytesRemaining < MaxChunkLength) ? bytesRemaining : MaxChunkLength;
                    int bytesRead = f.Read(chunk, 0, bytesToRead);

                    SendResponseFromMemory(chunk, bytesRead);
                    bytesRemaining -= bytesRead;

                    // flush to release keep memory
                    if ((bytesRemaining > 0) && (bytesRead > 0))
                    {
                        FlushResponse(false);
                    }
                }
            }
        }

        private void SkipAllPostedContent()
        {
            if ((_contentLength > 0) && (_bodyLength < _contentLength))
            {
                byte[] buffer;
                for (int i = _contentLength - _bodyLength; i > 0; i -= buffer.Length)
                {
                    buffer = _connection.ReadRequestBytes(i);
                    if ((buffer == null) || (buffer.Length == 0))
                    {
                        return;
                    }
                }
            }
        }


        /// <summary>
        /// TODO: defer response until request is written
        /// </summary>
        /// <returns></returns>
        private bool TryParseRequest()
        {
            Reset();

            ReadAllHeaders();

            if (_headerBytes == null || _endHeadersOffset < 0 ||
                _headerByteStrings == null || _headerByteStrings.Count == 0)
            {
                _connection.WriteErrorAndClose(400);
                return false;
            }

            ParseRequestLine();

            // Check for bad path
            if (IsBadPath())
            {
                _connection.WriteErrorAndClose(400);
                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(404);
                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 == 0)
                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, 0, bytes, 0, _headerBytes.Length);
                Buffer.BlockCopy(headerBytes, 0, bytes, _headerBytes.Length, headerBytes.Length);
                _headerBytes = bytes;
            }
            else
            {
                _headerBytes = headerBytes;
            }

            // start parsing
            _startHeadersOffset = -1;
            _endHeadersOffset = -1;
            _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 < 0)
                {
                    _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 = 0;
            for (int i = 0; i < count; i++)
            {
                if ((bytes[i] & 0x80) != 0)
                {
                    countNonAscii++;
                }
            }

            // encode all non-ascii characters using UTF-8 %XX
            if (countNonAscii > 0)
            {
                // expand not 'safe' characters into %XX, spaces to +s
                var expandedBytes = new byte[count + countNonAscii * 2];
                int pos = 0;
                for (int i = 0; i < count; i++)
                {
                    byte b = bytes[i];

                    if ((b & 0x80) == 0)
                    {
                        expandedBytes[pos++] = b;
                    }
                    else
                    {
                        expandedBytes[pos++] = (byte)'%';
                        expandedBytes[pos++] = (byte)IntToHex[(b >> 4) & 0xf];
                        expandedBytes[pos++] = (byte)IntToHex[b & 0xf];
                    }
                }

                path = Encoding.ASCII.GetString(expandedBytes);
            }

            // encode spaces into %20
            if (path.IndexOf(' ') >= 0)
            {
                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 = 0;
            }

            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 > 0 && _bytes[i - 1] == (byte)'\r')
                        {
                            len--;
                        }

                        line = new ByteString(_bytes, _pos, len);
                        _pos = i + 1;
                        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 == 0); }
            }

            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 > 0) Buffer.BlockCopy(_bytes, _offset, bytes, 0, _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, 0);
            }

            public int IndexOf(char ch, int offset)
            {
                for (int i = offset; i < _length; i++)
                {
                    if (this[i] == (byte)ch) return i;
                }
                return -1;
            }

            public ByteString[] Split(char sep)
            {
                var list = new List<ByteString>();

                int pos = 0;
                while (pos < _length)
                {
                    int i = IndexOf(sep, pos);
                    if (i < 0)
                    {
                        break;
                    }

                    list.Add(Substring(pos, i - pos));
                    pos = i + 1;

                    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

代码出自:cassinidev.codeplex.com

posted @ 2014-02-19 14:27  zhaocj  阅读(1442)  评论(5编辑  收藏  举报