사용자 정의 웹 IIS 서버 WebDev를 개발합니다.WebHost는 콘솔을 사용하여 웹 서비스를 받친다

89268 단어
저번에 한 편 썼어요.
ASP.NET는 간편한 웹 서버로 컨트롤러 프로그램으로 IIS 서버를 시뮬레이션하여 웹 서비스를 받쳐 놓았는데 한 친구가 중국어로 난타를 되돌려준다고 하는 것을 보았다.제가 평소에 사용하는 것은 모두 영어 개발 환경입니다. 중국어와 관련되어도 코드가 깨지지 않지만 회사의 중국어 vs 환경에서도 코드가 깨졌습니다.당분간 안 맞을 거야. 어떻게 해결해?나중에 vs 내장된 서버가 생각났어요...그래서 가져와서 고쳐 쓰자.
먼저 몇 가지 도움말 클래스를 말해 봅시다. 우리의 http 프로토콜에서 요청 헤더는\r\r로 끝납니다. 요청 헤더에서 모든 명령은\r로 구분됩니다. ByteParser는 요청 클래스를 구분하고 한 줄의 내용을 ByteString에 넣는 데 사용됩니다. ByteString의 주요 역할은 바이트를 문자로 바꾸는 것입니다.Messages는 기본 메시지만 반환합니다.Host는 원래의 WebServer처럼 요청을 처리하는데, Request는SimpleWorkerRequest를 실현하여 사용자의 요청을 진정으로 처리하는 데 사용된다.서버는 호스트를 캡슐화하는 데 사용되는 호출자에게 노출됩니다.Ntlm Auth류는 잘 몰라요. 신분인증 같은 거 처리하는 것 같아서...
그냥 수정된 코드를 붙여주세요.
namespace Microsoft.VisualStudio.WebHost
{
    using System;

    internal sealed class ByteParser
    {
        private byte[] _bytes;
        private int _pos;

        internal ByteParser(byte[] bytes)
        {
            this._bytes = bytes;
            this._pos = 0;
        }

        internal ByteString ReadLine()
        {
            ByteString str = null;
            for (int i = this._pos; i < this._bytes.Length; i++)
            {
                if (this._bytes[i] == 10)
                {
                    int length = i - this._pos;
                    if ((length > 0) && (this._bytes[i - 1] == 13))
                    {
                        length--;
                    }
                    str = new ByteString(this._bytes, this._pos, length);
                    this._pos = i + 1;
                    return str;
                }
            }
            if (this._pos < this._bytes.Length)
            {
                str = new ByteString(this._bytes, this._pos, this._bytes.Length - this._pos);
            }
            this._pos = this._bytes.Length;
            return str;
        }

        internal int CurrentOffset
        {
            get
            {
                return this._pos;
            }
        }
    }
}

namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Collections;
    using System.Reflection;
    using System.Text;

    internal sealed class ByteString
    {
        private byte[] _bytes;
        private int _length;
        private int _offset;

        public ByteString(byte[] bytes, int offset, int length)
        {
            this._bytes = bytes;
            if (((this._bytes != null) && (offset >= 0)) && ((length >= 0) && ((offset + length) <= this._bytes.Length)))
            {
                this._offset = offset;
                this._length = length;
            }
        }

        public byte[] GetBytes()
        {
            byte[] dst = new byte[this._length];
            if (this._length > 0)
            {
                Buffer.BlockCopy(this._bytes, this._offset, dst, 0, this._length);
            }
            return dst;
        }

        public string GetString()
        {
            return this.GetString(Encoding.UTF8);
        }

        public string GetString(Encoding enc)
        {
            if (this.IsEmpty)
            {
                return string.Empty;
            }
            return enc.GetString(this._bytes, this._offset, this._length);
        }

        public int IndexOf(char ch)
        {
            return this.IndexOf(ch, 0);
        }

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

        public ByteString[] Split(char sep)
        {
            ArrayList list = new ArrayList();
            int offset = 0;
            while (offset < this._length)
            {
                int index = this.IndexOf(sep, offset);
                if (index < 0)
                {
                    list.Add(this.Substring(offset));
                    break;
                }
                list.Add(this.Substring(offset, index - offset));
                for (offset = index + 1; (offset < this._length) && (this[offset] == ((byte) sep)); offset++)
                {
                }
            }
            int count = list.Count;
            ByteString[] strArray = new ByteString[count];
            for (int i = 0; i < count; i++)
            {
                strArray[i] = (ByteString) list[i];
            }
            return strArray;
        }

        public ByteString Substring(int offset)
        {
            return this.Substring(offset, this._length - offset);
        }

        public ByteString Substring(int offset, int len)
        {
            return new ByteString(this._bytes, this._offset + offset, len);
        }

        public byte[] Bytes
        {
            get
            {
                return this._bytes;
            }
        }

        public bool IsEmpty
        {
            get
            {
                if (this._bytes != null)
                {
                    return (this._length == 0);
                }
                return true;
            }
        }

        public byte this[int index]
        {
            get
            {
                return this._bytes[this._offset + index];
            }
        }

        public int Length
        {
            get
            {
                return this._length;
            }
        }

        public int Offset
        {
            get
            {
                return this._offset;
            }
        }
    }
}

namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Globalization;
    using System.IO;
    using System.Text;
    using System.Web;

    internal class Messages
    {
        private const string _dirListingDirFormat = "{0,38:dddd, MMMM dd, yyyy hh:mm tt}        <dir> <A href=\"{1}/\">{2}</A>\r
"; private const string _dirListingFileFormat = "{0,38:dddd, MMMM dd, yyyy hh:mm tt} {1,12:n0} <A href=\"{2}\">{3}</A>\r
"; private const string _dirListingFormat1 = "<html>\r
<head>\r
<title>{0}</title>\r
"; private const string _dirListingFormat2 = " </head>\r
<body bgcolor=\"white\">\r
\r
<h2> <i>{0}</i> </h2></span>\r
\r
<hr width=100% size=1 color=silver>\r
\r
<PRE>\r
"; private const string _dirListingParentFormat = "<A href=\"{0}\">[To Parent Directory]</A>\r
\r
"; private static string _dirListingTail = ("</PRE>\r
<hr width=100% size=1 color=silver>\r
\r
<b>{0}:</b> {1} " + VersionString + "\r
\r
</font>\r
\r
</body>\r
</html>\r
"); private const string _httpErrorFormat1 = "<html>\r
<head>\r
<title>{0}</title>\r
"; private static string _httpErrorFormat2 = (" </head>\r
<body bgcolor=\"white\">\r
\r
<span><h1>{0}<hr width=100% size=1 color=silver></h1>\r
\r
<h2> <i>{1}</i> </h2></span>\r
\r
<hr width=100% size=1 color=silver>\r
\r
<b>{2}:</b> {3} " + VersionString + "\r
\r
</font>\r
\r
</body>\r
</html>\r
"); private const string _httpStyle = " <style>\r
\tbody {font-family:\"Verdana\";font-weight:normal;font-size: 8pt;color:black;} \r
\tp {font-family:\"Verdana\";font-weight:normal;color:black;margin-top: -5px}\r
\tb {font-family:\"Verdana\";font-weight:bold;color:black;margin-top: -5px}\r
\th1 { font-family:\"Verdana\";font-weight:normal;font-size:18pt;color:red }\r
\th2 { font-family:\"Verdana\";font-weight:normal;font-size:14pt;color:maroon }\r
\tpre {font-family:\"Lucida Console\";font-size: 8pt}\r
\t.marker {font-weight: bold; color: black;text-decoration: none;}\r
\t.version {color: gray;}\r
\t.error {margin-bottom: 10px;}\r
\t.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }\r
</style>\r
"; public static string VersionString = GetVersionString(); public static string FormatDirectoryListing(string dirPath, string parentPath, FileSystemInfo[] elements) { StringBuilder builder = new StringBuilder(); string str = string.Format("Directory Listing -- {0}", dirPath ); string str2 = "Version Information"; string str3 = "ASP.NET Development Server"; string str4 = string.Format(CultureInfo.InvariantCulture, _dirListingTail, new object[] { str2, str3 }); builder.Append(string.Format(CultureInfo.InvariantCulture, "<html>\r
<head>\r
<title>{0}</title>\r
", new object[] { str })); builder.Append(" <style>\r
\tbody {font-family:\"Verdana\";font-weight:normal;font-size: 8pt;color:black;} \r
\tp {font-family:\"Verdana\";font-weight:normal;color:black;margin-top: -5px}\r
\tb {font-family:\"Verdana\";font-weight:bold;color:black;margin-top: -5px}\r
\th1 { font-family:\"Verdana\";font-weight:normal;font-size:18pt;color:red }\r
\th2 { font-family:\"Verdana\";font-weight:normal;font-size:14pt;color:maroon }\r
\tpre {font-family:\"Lucida Console\";font-size: 8pt}\r
\t.marker {font-weight: bold; color: black;text-decoration: none;}\r
\t.version {color: gray;}\r
\t.error {margin-bottom: 10px;}\r
\t.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }\r
</style>\r
"); builder.Append(string.Format(CultureInfo.InvariantCulture, " </head>\r
<body bgcolor=\"white\">\r
\r
<h2> <i>{0}</i> </h2></span>\r
\r
<hr width=100% size=1 color=silver>\r
\r
<PRE>\r
", new object[] { str })); if (parentPath != null) { if (!parentPath.EndsWith("/", StringComparison.Ordinal)) { parentPath = parentPath + "/"; } builder.Append(string.Format(CultureInfo.InvariantCulture, "<A href=\"{0}\">[To Parent Directory]</A>\r
\r
", new object[] { parentPath })); } if (elements != null) { for (int i = 0; i < elements.Length; i++) { if (elements[i] is FileInfo) { FileInfo info = (FileInfo) elements[i]; builder.Append(string.Format(CultureInfo.InvariantCulture, "{0,38:dddd, MMMM dd, yyyy hh:mm tt} {1,12:n0} <A href=\"{2}\">{3}</A>\r
", new object[] { info.LastWriteTime, info.Length, info.Name, info.Name })); } else if (elements[i] is DirectoryInfo) { DirectoryInfo info2 = (DirectoryInfo) elements[i]; builder.Append(string.Format(CultureInfo.InvariantCulture, "{0,38:dddd, MMMM dd, yyyy hh:mm tt} <dir> <A href=\"{1}/\">{2}</A>\r
", new object[] { info2.LastWriteTime, info2.Name, info2.Name })); } } } builder.Append(str4); return builder.ToString(); } public static string FormatErrorMessageBody(int statusCode, string appName) { string statusDescription = HttpWorkerRequest.GetStatusDescription(statusCode); string str2 = string.Format("Server Error in '{0}' Application.", appName); string str3 = string.Format("HTTP Error {0} - {1}.", statusCode, statusDescription); string str4 = "Version Information"; string str5 = "ASP.NET Development Server"; return (string.Format(CultureInfo.InvariantCulture, "<html>\r
<head>\r
<title>{0}</title>\r
", new object[] { statusDescription }) + " <style>\r
\tbody {font-family:\"Verdana\";font-weight:normal;font-size: 8pt;color:black;} \r
\tp {font-family:\"Verdana\";font-weight:normal;color:black;margin-top: -5px}\r
\tb {font-family:\"Verdana\";font-weight:bold;color:black;margin-top: -5px}\r
\th1 { font-family:\"Verdana\";font-weight:normal;font-size:18pt;color:red }\r
\th2 { font-family:\"Verdana\";font-weight:normal;font-size:14pt;color:maroon }\r
\tpre {font-family:\"Lucida Console\";font-size: 8pt}\r
\t.marker {font-weight: bold; color: black;text-decoration: none;}\r
\t.version {color: gray;}\r
\t.error {margin-bottom: 10px;}\r
\t.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }\r
</style>\r
" + string.Format(CultureInfo.InvariantCulture, _httpErrorFormat2, new object[] { str2, str3, str4, str5 })); } private static string GetVersionString() { return "10.0.0.0"; } } }
namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Security.Principal;

    [SuppressUnmanagedCodeSecurity]
    internal sealed class NtlmAuth : IDisposable
    {
        private string _blob;
        private bool _completed;
        private SecHandle _credentialsHandle;
        private bool _credentialsHandleAcquired;
        private SecBuffer _inputBuffer;
        private SecBufferDesc _inputBufferDesc;
        private SecBuffer _outputBuffer;
        private SecBufferDesc _outputBufferDesc;
        private SecHandle _securityContext;
        private bool _securityContextAcquired;
        private uint _securityContextAttributes;
        private SecurityIdentifier _sid;
        private long _timestamp;
        private const int ISC_REQ_ALLOCATE_MEMORY = 0x100;
        private const int ISC_REQ_CONFIDENTIALITY = 0x10;
        private const int ISC_REQ_DELEGATE = 1;
        private const int ISC_REQ_MUTUAL_AUTH = 2;
        private const int ISC_REQ_PROMPT_FOR_CREDS = 0x40;
        private const int ISC_REQ_REPLAY_DETECT = 4;
        private const int ISC_REQ_SEQUENCE_DETECT = 8;
        private const int ISC_REQ_STANDARD_FLAGS = 20;
        private const int ISC_REQ_USE_SESSION_KEY = 0x20;
        private const int ISC_REQ_USE_SUPPLIED_CREDS = 0x80;
        private const int SEC_E_OK = 0;
        private const int SEC_I_COMPLETE_AND_CONTINUE = 0x90314;
        private const int SEC_I_COMPLETE_NEEDED = 0x90313;
        private const int SEC_I_CONTINUE_NEEDED = 0x90312;
        private const int SECBUFFER_DATA = 1;
        private const int SECBUFFER_EMPTY = 0;
        private const int SECBUFFER_TOKEN = 2;
        private const int SECBUFFER_VERSION = 0;
        private const int SECPKG_CRED_INBOUND = 1;
        private const int SECURITY_NETWORK_DREP = 0;

        public NtlmAuth()
        {
            if (AcquireCredentialsHandle(null, "NTLM", 1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref this._credentialsHandle, ref this._timestamp) != 0)
            {
                throw new InvalidOperationException();
            }
            this._credentialsHandleAcquired = true;
        }

        [DllImport("SECUR32.DLL", CharSet=CharSet.Unicode)]
        private 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)]
        private static extern int AcquireCredentialsHandle(string pszPrincipal, string pszPackage, uint fCredentialUse, IntPtr pvLogonID, IntPtr pAuthData, IntPtr pGetKeyFn, IntPtr pvGetKeyArgument, ref SecHandle phCredential, ref long ptsExpiry);
        public unsafe bool Authenticate(string blobString)
        {
            this._blob = null;
            byte[] buffer = Convert.FromBase64String(blobString);
            byte[] inArray = new byte[0x4000];
            fixed (SecHandle* voidRef = &this._securityContext)
            {
                fixed (SecBuffer* voidRef2 = &this._inputBuffer)
                {
                    fixed (SecBuffer* voidRef3 = &this._outputBuffer)
                    {
                        fixed (void* voidRef4 = buffer)
                        {
                            fixed (void* voidRef5 = inArray)
                            {
                                IntPtr zero = IntPtr.Zero;
                                if (this._securityContextAcquired)
                                {
                                    zero = (IntPtr)voidRef;
                                }
                                this._inputBufferDesc.ulVersion = 0;
                                this._inputBufferDesc.cBuffers = 1;
                                this._inputBufferDesc.pBuffers = (IntPtr)voidRef2;
                                this._inputBuffer.cbBuffer = (uint)buffer.Length;
                                this._inputBuffer.BufferType = 2;
                                this._inputBuffer.pvBuffer = (IntPtr)voidRef4;
                                this._outputBufferDesc.ulVersion = 0;
                                this._outputBufferDesc.cBuffers = 1;
                                this._outputBufferDesc.pBuffers = (IntPtr)voidRef3;
                                this._outputBuffer.cbBuffer = (uint)inArray.Length;
                                this._outputBuffer.BufferType = 2;
                                this._outputBuffer.pvBuffer = (IntPtr)voidRef5;
                                int num = AcceptSecurityContext(ref this._credentialsHandle, zero, ref this._inputBufferDesc, 20, 0, ref this._securityContext, ref this._outputBufferDesc, ref this._securityContextAttributes, ref this._timestamp);
                                if (num == 0x90312)
                                {
                                    this._securityContextAcquired = true;
                                    this._blob = Convert.ToBase64String(inArray, 0, (int)this._outputBuffer.cbBuffer);
                                }
                                else
                                {
                                    if (num != 0)
                                    {
                                        return false;
                                    }
                                    IntPtr phToken = IntPtr.Zero;
                                    if (QuerySecurityContextToken(ref this._securityContext, ref phToken) != 0)
                                    {
                                        return false;
                                    }
                                    try
                                    {
                                        using (WindowsIdentity identity = new WindowsIdentity(phToken))
                                        {
                                            this._sid = identity.User;
                                        }
                                    }
                                    finally
                                    {
                                        CloseHandle(phToken);
                                    }
                                    this._completed = true;
                                }
                            }
                        }
                    }
                }
            }
            return true;
        }


        [DllImport("KERNEL32.DLL", CharSet=CharSet.Unicode)]
        private static extern int CloseHandle(IntPtr phToken);
        [DllImport("SECUR32.DLL", CharSet=CharSet.Unicode)]
        private static extern int DeleteSecurityContext(ref SecHandle phContext);
        ~NtlmAuth()
        {
            this.FreeUnmanagedResources();
        }

        [DllImport("SECUR32.DLL", CharSet=CharSet.Unicode)]
        private static extern int FreeCredentialsHandle(ref SecHandle phCredential);
        private void FreeUnmanagedResources()
        {
            if (this._securityContextAcquired)
            {
                DeleteSecurityContext(ref this._securityContext);
            }
            if (this._credentialsHandleAcquired)
            {
                FreeCredentialsHandle(ref this._credentialsHandle);
            }
        }

        [DllImport("SECUR32.DLL", CharSet=CharSet.Unicode)]
        private static extern int QuerySecurityContextToken(ref SecHandle phContext, ref IntPtr phToken);
        void IDisposable.Dispose()
        {
            this.FreeUnmanagedResources();
            GC.SuppressFinalize(this);
        }

        public string Blob
        {
            get
            {
                return this._blob;
            }
        }

        public bool Completed
        {
            get
            {
                return this._completed;
            }
        }

        public SecurityIdentifier SID
        {
            get
            {
                return this._sid;
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct SecBuffer
        {
            public uint cbBuffer;
            public uint BufferType;
            public IntPtr pvBuffer;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct SecBufferDesc
        {
            public uint ulVersion;
            public uint cBuffers;
            public IntPtr pBuffers;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct SecHandle
        {
            public IntPtr dwLower;
            public IntPtr dwUpper;
        }
    }
}

namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Globalization;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Web;

    internal sealed class Connection : MarshalByRefObject
    {
        private static string _defaultLoalhostIP;
        private static string _localServerIP;
        private Server _server;
        private Socket _socket;

        internal Connection(Server server, Socket socket)
        {
            this._server = server;
            this._socket = socket;
        }

        internal void Close()
        {
            try
            {
                this._socket.Shutdown(SocketShutdown.Both);
                this._socket.Close();
            }
            catch
            {
            }
            finally
            {
                this._socket = null;
            }
        }

        private string GetErrorResponseBody(int statusCode, string message)
        {
            string str = Messages.FormatErrorMessageBody(statusCode, this._server.VirtualPath);
            if ((message != null) && (message.Length > 0))
            {
                str = str + "\r
<!--\r
" + message + "\r
-->"; } return str; } public override object InitializeLifetimeService() { return null; } private static string MakeContentTypeHeader(string fileName) { string str = null; FileInfo info = new FileInfo(fileName); switch (info.Extension.ToLowerInvariant()) { case ".bmp": str = "image/bmp"; break; case ".css": str = "text/css"; break; case ".gif": str = "image/gif"; break; case ".ico": str = "image/x-icon"; break; case ".htm": case ".html": str = "text/html"; break; case ".jpe": case ".jpeg": case ".jpg": str = "image/jpeg"; break; case ".js": str = "application/x-javascript"; break; } if (str == null) { return null; } return ("Content-Type: " + str + "\r
"); } private static string MakeResponseHeaders(int statusCode, string moreHeaders, int contentLength, bool keepAlive) { StringBuilder builder = new StringBuilder(); builder.Append(string.Concat(new object[] { "HTTP/1.1 ", statusCode, " ", HttpWorkerRequest.GetStatusDescription(statusCode), "\r
" })); builder.Append("Server: ASP.NET Development Server/" + Messages.VersionString + "\r
"); builder.Append("Date: " + DateTime.Now.ToUniversalTime().ToString("R", DateTimeFormatInfo.InvariantInfo) + "\r
"); if (contentLength >= 0) { builder.Append("Content-Length: " + contentLength + "\r
"); } if (moreHeaders != null) { builder.Append(moreHeaders); } if (!keepAlive) { builder.Append("Connection: Close\r
"); } builder.Append("\r
"); return builder.ToString(); } internal byte[] ReadRequestBytes(int maxBytes) { try { if (this.WaitForRequestBytes() == 0) { return null; } int available = this._socket.Available; if (available > maxBytes) { available = maxBytes; } int count = 0; byte[] buffer = new byte[available]; if (available > 0) { count = this._socket.Receive(buffer, 0, available, SocketFlags.None); } if (count < available) { byte[] dst = new byte[count]; if (count > 0) { Buffer.BlockCopy(buffer, 0, dst, 0, count); } buffer = dst; } return buffer; } catch { return null; } } internal int WaitForRequestBytes() { int available = 0; try { if (this._socket.Available == 0) { this._socket.Poll(0x186a0, SelectMode.SelectRead); if ((this._socket.Available == 0) && this._socket.Connected) { this._socket.Poll(0x1c9c380, SelectMode.SelectRead); } } available = this._socket.Available; } catch { } return available; } internal void Write100Continue() { this.WriteEntireResponseFromString(100, null, null, true); } internal void WriteBody(byte[] data, int offset, int length) { try { this._socket.Send(data, offset, length, SocketFlags.None); } catch (SocketException) { } } internal void WriteEntireResponseFromFile(string fileName, bool keepAlive) { if (!System.IO.File.Exists(fileName)) { this.WriteErrorAndClose(0x194); } else { string moreHeaders = MakeContentTypeHeader(fileName); if (moreHeaders == null) { this.WriteErrorAndClose(0x193); } else { bool flag = false; FileStream stream = null; try { stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); int length = (int) stream.Length; byte[] buffer = new byte[length]; int contentLength = stream.Read(buffer, 0, length); string s = MakeResponseHeaders(200, moreHeaders, contentLength, keepAlive); this._socket.Send(Encoding.UTF8.GetBytes(s)); this._socket.Send(buffer, 0, contentLength, SocketFlags.None); flag = true; } catch (SocketException) { } finally { if (!keepAlive || !flag) { this.Close(); } if (stream != null) { stream.Close(); } } } } } internal void WriteEntireResponseFromString(int statusCode, string extraHeaders, string body, bool keepAlive) { try { int contentLength = (body != null) ? Encoding.UTF8.GetByteCount(body) : 0; string str = MakeResponseHeaders(statusCode, extraHeaders, contentLength, keepAlive); this._socket.Send(Encoding.UTF8.GetBytes(str + body)); } catch (SocketException) { } finally { if (!keepAlive) { this.Close(); } } } internal void WriteErrorAndClose(int statusCode) { this.WriteErrorAndClose(statusCode, null); } internal void WriteErrorAndClose(int statusCode, string message) { this.WriteEntireResponseFromString(statusCode, "Content-type:text/html;charset=utf-8\r
", this.GetErrorResponseBody(statusCode, message), false); } internal void WriteErrorWithExtraHeadersAndKeepAlive(int statusCode, string extraHeaders) { this.WriteEntireResponseFromString(statusCode, extraHeaders, this.GetErrorResponseBody(statusCode, null), true); } internal void WriteHeaders(int statusCode, string extraHeaders) { string s = MakeResponseHeaders(statusCode, extraHeaders, -1, false); try { this._socket.Send(Encoding.UTF8.GetBytes(s)); } catch (SocketException) { } } internal bool Connected { get { return this._socket.Connected; } } private string DefaultLocalHostIP { get { if (string.IsNullOrEmpty(_defaultLoalhostIP)) { if (!Socket.OSSupportsIPv4 && Socket.OSSupportsIPv6) { _defaultLoalhostIP = "::1"; } else { _defaultLoalhostIP = "127.0.0.1"; } } return _defaultLoalhostIP; } } internal bool IsLocal { get { string remoteIP = this.RemoteIP; if (string.IsNullOrEmpty(remoteIP)) { return false; } if ((!remoteIP.Equals("127.0.0.1") && !remoteIP.Equals("::1")) && !remoteIP.Equals("::ffff:127.0.0.1")) { return LocalServerIP.Equals(remoteIP); } return true; } } internal string LocalIP { get { IPEndPoint localEndPoint = (IPEndPoint) this._socket.LocalEndPoint; if ((localEndPoint != null) && (localEndPoint.Address != null)) { return localEndPoint.Address.ToString(); } return this.DefaultLocalHostIP; } } private static string LocalServerIP { get { if (_localServerIP == null) { _localServerIP = Dns.GetHostEntry(Environment.MachineName).AddressList[0].ToString(); } return _localServerIP; } } internal string RemoteIP { get { IPEndPoint remoteEndPoint = (IPEndPoint) this._socket.RemoteEndPoint; if ((remoteEndPoint != null) && (remoteEndPoint.Address != null)) { return remoteEndPoint.Address.ToString(); } return ""; } } } }
namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Globalization;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    using System.Security.Principal;
    using System.Threading;
    using System.Web;
    using System.Web.Hosting;

    internal sealed class Host : MarshalByRefObject, IRegisteredObject
    {
        private bool _disableDirectoryListing;
        private string _installPath;
        private string _lowerCasedClientScriptPathWithTrailingSlash;
        private string _lowerCasedVirtualPath;
        private string _lowerCasedVirtualPathWithTrailingSlash;
        //private volatile int _pendingCallsCount;
        private  int _pendingCallsCount;
        private string _physicalClientScriptPath;
        private string _physicalPath;
        private int _port;
        private bool _requireAuthentication;
        private Server _server;
        private string _virtualPath;

        public Host()
        {
            HostingEnvironment.RegisterObject(this);
        }

        private void AddPendingCall()
        {
            Interlocked.Increment(ref this._pendingCallsCount);
        }

        public void Configure(Server server, int port, string virtualPath, string physicalPath, bool requireAuthentication)
        {
            this.Configure(server, port, virtualPath, physicalPath, requireAuthentication, false);
        }

        public void Configure(Server server, int port, string virtualPath, string physicalPath, bool requireAuthentication, bool disableDirectoryListing)
        {
            this._server = server;
            this._port = port;
            this._installPath = null;
            this._virtualPath = virtualPath;
            this._requireAuthentication = requireAuthentication;
            this._disableDirectoryListing = disableDirectoryListing;
            this._lowerCasedVirtualPath = CultureInfo.InvariantCulture.TextInfo.ToLower(this._virtualPath);
            this._lowerCasedVirtualPathWithTrailingSlash = virtualPath.EndsWith("/", StringComparison.Ordinal) ? virtualPath : (virtualPath + "/");
            this._lowerCasedVirtualPathWithTrailingSlash = CultureInfo.InvariantCulture.TextInfo.ToLower(this._lowerCasedVirtualPathWithTrailingSlash);
            this._physicalPath = physicalPath;
            this._physicalClientScriptPath = HttpRuntime.AspClientScriptPhysicalPath + @"\";
            this._lowerCasedClientScriptPathWithTrailingSlash = CultureInfo.InvariantCulture.TextInfo.ToLower(HttpRuntime.AspClientScriptVirtualPath + "/");
        }

        public SecurityIdentifier GetProcessSID()
        {
            using (WindowsIdentity identity = new WindowsIdentity(this._server.GetProcessToken()))
            {
                return identity.User;
            }
        }

        public IntPtr GetProcessToken()
        {
            new SecurityPermission(PermissionState.Unrestricted).Assert();
            return this._server.GetProcessToken();
        }

        public string GetProcessUser()
        {
            return this._server.GetProcessUser();
        }

        public override object InitializeLifetimeService()
        {
            return null;
        }

        public bool IsVirtualPathAppPath(string path)
        {
            if (path == null)
            {
                return false;
            }
            path = CultureInfo.InvariantCulture.TextInfo.ToLower(path);
            if (!(path == this._lowerCasedVirtualPath))
            {
                return (path == this._lowerCasedVirtualPathWithTrailingSlash);
            }
            return true;
        }

        public bool IsVirtualPathInApp(string path)
        {
            bool flag;
            return this.IsVirtualPathInApp(path, out flag);
        }

        public bool IsVirtualPathInApp(string path, out bool isClientScriptPath)
        {
            isClientScriptPath = false;
            if (path != null)
            {
                path = CultureInfo.InvariantCulture.TextInfo.ToLower(path);
                if ((this._virtualPath == "/") && path.StartsWith("/", StringComparison.Ordinal))
                {
                    if (path.StartsWith(this._lowerCasedClientScriptPathWithTrailingSlash, StringComparison.Ordinal))
                    {
                        isClientScriptPath = true;
                    }
                    return true;
                }
                if (path.StartsWith(this._lowerCasedVirtualPathWithTrailingSlash, StringComparison.Ordinal))
                {
                    return true;
                }
                if (path == this._lowerCasedVirtualPath)
                {
                    return true;
                }
                if (path.StartsWith(this._lowerCasedClientScriptPathWithTrailingSlash, StringComparison.Ordinal))
                {
                    isClientScriptPath = true;
                    return true;
                }
            }
            return false;
        }

        public void ProcessRequest(Connection conn)
        {
            this.AddPendingCall();
            try
            {
                new Request(this, conn).Process();
            }
            finally
            {
                this.RemovePendingCall();
            }
        }

        private void RemovePendingCall()
        {
            Interlocked.Decrement(ref this._pendingCallsCount);
        }

        [SecurityPermission(SecurityAction.Assert, Unrestricted=true)]
        public void Shutdown()
        {
            HostingEnvironment.InitiateShutdown();
        }

        void IRegisteredObject.Stop(bool immediate)
        {
            if (this._server != null)
            {
                this._server.HostStopped();
            }
            this.WaitForPendingCallsToFinish();
            HostingEnvironment.UnregisterObject(this);
        }

        private void WaitForPendingCallsToFinish()
        {
            while (this._pendingCallsCount > 0)
            {
                Thread.Sleep(250);
            }
        }

        public bool DisableDirectoryListing
        {
            get
            {
                return this._disableDirectoryListing;
            }
        }

        public string InstallPath
        {
            get
            {
                return this._installPath;
            }
        }

        public string NormalizedClientScriptPath
        {
            get
            {
                return this._lowerCasedClientScriptPathWithTrailingSlash;
            }
        }

        public string NormalizedVirtualPath
        {
            get
            {
                return this._lowerCasedVirtualPathWithTrailingSlash;
            }
        }

        public string PhysicalClientScriptPath
        {
            get
            {
                return this._physicalClientScriptPath;
            }
        }

        public string PhysicalPath
        {
            get
            {
                return this._physicalPath;
            }
        }

        public int Port
        {
            get
            {
                return this._port;
            }
        }

        public bool RequireAuthentication
        {
            get
            {
                return this._requireAuthentication;
            }
        }

        public string VirtualPath
        {
            get
            {
                return this._virtualPath;
            }
        }
    }
}

namespace Microsoft.VisualStudio.WebHost
{
    using Microsoft.Win32.SafeHandles;
    using System;
    using System.Collections;
    using System.Globalization;
    using System.IO;
    using System.Security;
    using System.Security.Permissions;
    using System.Text;
    using System.Web;
    using System.Web.Hosting;

    internal sealed class Request : SimpleWorkerRequest
    {
        private string _allRawHeaders;
        private Connection _connection;
        private IStackWalk _connectionPermission;
        private int _contentLength;
        private int _endHeadersOffset;
        private string _filePath;
        private byte[] _headerBytes;
        private ArrayList _headerByteStrings;
        private bool _headersSent;
        private Host _host;
        private bool _isClientScriptPath;
        private string[] _knownRequestHeaders;
        private string _path;
        private string _pathInfo;
        private string _pathTranslated;
        private byte[] _preloadedContent;
        private int _preloadedContentLength;
        private string _prot;
        private string _queryString;
        private byte[] _queryStringBytes;
        private ArrayList _responseBodyBytes;
        private StringBuilder _responseHeadersBuilder;
        private int _responseStatus;
        private bool _specialCaseStaticFileHeaders;
        private int _startHeadersOffset;
        private string[][] _unknownRequestHeaders;
        private string _url;
        private string _verb;
        private static char[] badPathChars = new char[] { '%', '>', '<', ':', '\\' };
        private static string[] defaultFileNames = new string[] { "default.aspx", "default.htm", "default.html" };
        private static char[] IntToHex = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        private const int MaxChunkLength = 0x10000;
        private const int maxHeaderBytes = 0x8000;
        private static string[] restrictedDirs = new string[] { "/bin", "/app_browsers", "/app_code", "/app_data", "/app_localresources", "/app_globalresources", "/app_webreferences" };

        public Request(Host host, Connection connection) : base(string.Empty, string.Empty, null)
        {
            this._connectionPermission = new PermissionSet(PermissionState.Unrestricted);
            this._host = host;
            this._connection = connection;
        }

        public override void CloseConnection()
        {
            this._connectionPermission.Assert();
            this._connection.Close();
        }

        public override void EndOfRequest()
        {
        }

        public override void FlushResponse(bool finalFlush)
        {
            if ((((this._responseStatus != 0x194) || this._headersSent) || (!finalFlush || (this._verb != "GET"))) || !this.ProcessDirectoryListingRequest())
            {
                this._connectionPermission.Assert();
                if (!this._headersSent)
                {
                    this._connection.WriteHeaders(this._responseStatus, this._responseHeadersBuilder.ToString());
                    this._headersSent = true;
                }
                for (int i = 0; i < this._responseBodyBytes.Count; i++)
                {
                    byte[] data = (byte[]) this._responseBodyBytes[i];
                    this._connection.WriteBody(data, 0, data.Length);
                }
                this._responseBodyBytes = new ArrayList();
                if (finalFlush)
                {
                    this._connection.Close();
                }
            }
        }

        public override string GetAppPath()
        {
            return this._host.VirtualPath;
        }

        public override string GetAppPathTranslated()
        {
            return this._host.PhysicalPath;
        }

        public override string GetFilePath()
        {
            return this._filePath;
        }

        public override string GetFilePathTranslated()
        {
            return this._pathTranslated;
        }

        public override string GetHttpVerbName()
        {
            return this._verb;
        }

        public override string GetHttpVersion()
        {
            return this._prot;
        }

        public override string GetKnownRequestHeader(int index)
        {
            return this._knownRequestHeaders[index];
        }

        public override string GetLocalAddress()
        {
            this._connectionPermission.Assert();
            return this._connection.LocalIP;
        }

        public override int GetLocalPort()
        {
            return this._host.Port;
        }

        public override string GetPathInfo()
        {
            return this._pathInfo;
        }

        public override byte[] GetPreloadedEntityBody()
        {
            return this._preloadedContent;
        }

        public override string GetQueryString()
        {
            return this._queryString;
        }

        public override byte[] GetQueryStringRawBytes()
        {
            return this._queryStringBytes;
        }

        public override string GetRawUrl()
        {
            return this._url;
        }

        public override string GetRemoteAddress()
        {
            this._connectionPermission.Assert();
            return this._connection.RemoteIP;
        }

        public override int GetRemotePort()
        {
            return 0;
        }

        public override string GetServerName()
        {
            string localAddress = this.GetLocalAddress();
            if ((!localAddress.Equals("127.0.0.1") && !localAddress.Equals("::1")) && !localAddress.Equals("::ffff:127.0.0.1"))
            {
                return localAddress;
            }
            return "localhost";
        }

        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 (this.GetUserToken() != IntPtr.Zero)
                        {
                            processUser = this._host.GetProcessUser();
                        }
                        return processUser;
                    }
                    if ((str2 == "AUTH_TYPE") && (this.GetUserToken() != IntPtr.Zero))
                    {
                        processUser = "NTLM";
                    }
                    return processUser;
                }
            }
            else
            {
                return this._allRawHeaders;
            }
            return this._prot;
        }

        public override string GetUnknownRequestHeader(string name)
        {
            int length = this._unknownRequestHeaders.Length;
            for (int i = 0; i < length; i++)
            {
                if (string.Compare(name, this._unknownRequestHeaders[i][0], StringComparison.OrdinalIgnoreCase) == 0)
                {
                    return this._unknownRequestHeaders[i][1];
                }
            }
            return null;
        }

        public override string[][] GetUnknownRequestHeaders()
        {
            return this._unknownRequestHeaders;
        }

        public override string GetUriPath()
        {
            return this._path;
        }

        public override IntPtr GetUserToken()
        {
            return this._host.GetProcessToken();
        }

        public override bool HeadersSent()
        {
            return this._headersSent;
        }

        private bool IsBadPath()
        {
            return ((this._path.IndexOfAny(badPathChars) >= 0) || ((CultureInfo.InvariantCulture.CompareInfo.IndexOf(this._path, "..", CompareOptions.Ordinal) >= 0) || (CultureInfo.InvariantCulture.CompareInfo.IndexOf(this._path, "//", CompareOptions.Ordinal) >= 0)));
        }

        public override bool IsClientConnected()
        {
            this._connectionPermission.Assert();
            return this._connection.Connected;
        }

        public override bool IsEntireEntityBodyIsPreloaded()
        {
            return (this._contentLength == this._preloadedContentLength);
        }

        private bool IsRequestForRestrictedDirectory()
        {
            string str = CultureInfo.InvariantCulture.TextInfo.ToLower(this._path);
            if (this._host.VirtualPath != "/")
            {
                str = str.Substring(this._host.VirtualPath.Length);
            }
            foreach (string str2 in restrictedDirs)
            {
                if (str.StartsWith(str2, StringComparison.Ordinal) && ((str.Length == str2.Length) || (str[str2.Length] == '/')))
                {
                    return true;
                }
            }
            return false;
        }

        public override string MapPath(string path)
        {
            string physicalPath = string.Empty;
            bool isClientScriptPath = false;
            if (((path == null) || (path.Length == 0)) || path.Equals("/"))
            {
                if (this._host.VirtualPath == "/")
                {
                    physicalPath = this._host.PhysicalPath;
                }
                else
                {
                    physicalPath = Environment.SystemDirectory;
                }
            }
            else if (this._host.IsVirtualPathAppPath(path))
            {
                physicalPath = this._host.PhysicalPath;
            }
            else if (this._host.IsVirtualPathInApp(path, out isClientScriptPath))
            {
                if (isClientScriptPath)
                {
                    physicalPath = this._host.PhysicalClientScriptPath + path.Substring(this._host.NormalizedClientScriptPath.Length);
                }
                else
                {
                    physicalPath = this._host.PhysicalPath + path.Substring(this._host.NormalizedVirtualPath.Length);
                }
            }
            else if (path.StartsWith("/", StringComparison.Ordinal))
            {
                physicalPath = this._host.PhysicalPath + path.Substring(1);
            }
            else
            {
                physicalPath = this._host.PhysicalPath + path;
            }
            physicalPath = physicalPath.Replace('/', '\\');
            if (physicalPath.EndsWith(@"\", StringComparison.Ordinal) && !physicalPath.EndsWith(@":\", StringComparison.Ordinal))
            {
                physicalPath = physicalPath.Substring(0, physicalPath.Length - 1);
            }
            return physicalPath;
        }

        private void ParseHeaders()
        {
            this._knownRequestHeaders = new string[40];
            ArrayList list = new ArrayList();
            for (int i = 1; i < this._headerByteStrings.Count; i++)
            {
                string str = ((ByteString) this._headerByteStrings[i]).GetString();
                int index = str.IndexOf(':');
                if (index >= 0)
                {
                    string header = str.Substring(0, index).Trim();
                    string str3 = str.Substring(index + 1).Trim();
                    int knownRequestHeaderIndex = HttpWorkerRequest.GetKnownRequestHeaderIndex(header);
                    if (knownRequestHeaderIndex >= 0)
                    {
                        this._knownRequestHeaders[knownRequestHeaderIndex] = str3;
                    }
                    else
                    {
                        list.Add(header);
                        list.Add(str3);
                    }
                }
            }
            int num4 = list.Count / 2;
            this._unknownRequestHeaders = new string[num4][];
            int num5 = 0;
            for (int j = 0; j < num4; j++)
            {
                this._unknownRequestHeaders[j] = new string[] { (string) list[num5++], (string) list[num5++] };
            }
            if (this._headerByteStrings.Count > 1)
            {
                this._allRawHeaders = Encoding.UTF8.GetString(this._headerBytes, this._startHeadersOffset, this._endHeadersOffset - this._startHeadersOffset);
            }
            else
            {
                this._allRawHeaders = string.Empty;
            }
        }

        private void ParsePostedContent()
        {
            this._contentLength = 0;
            this._preloadedContentLength = 0;
            string s = this._knownRequestHeaders[11];
            if (s != null)
            {
                try
                {
                    this._contentLength = int.Parse(s, CultureInfo.InvariantCulture);
                }
                catch
                {
                }
            }
            if (this._headerBytes.Length > this._endHeadersOffset)
            {
                this._preloadedContentLength = this._headerBytes.Length - this._endHeadersOffset;
                if (this._preloadedContentLength > this._contentLength)
                {
                    this._preloadedContentLength = this._contentLength;
                }
                if (this._preloadedContentLength > 0)
                {
                    this._preloadedContent = new byte[this._preloadedContentLength];
                    Buffer.BlockCopy(this._headerBytes, this._endHeadersOffset, this._preloadedContent, 0, this._preloadedContentLength);
                }
            }
        }

        private void ParseRequestLine()
        {
            ByteString[] strArray = ((ByteString) this._headerByteStrings[0]).Split(' ');
            if (((strArray == null) || (strArray.Length < 2)) || (strArray.Length > 3))
            {
                this._connection.WriteErrorAndClose(400);
            }
            else
            {
                this._verb = strArray[0].GetString();
                ByteString str2 = strArray[1];
                this._url = str2.GetString();
                if (this._url.IndexOf((char)0xfffd) >= 0)
                {
                    this._url = str2.GetString(Encoding.Default);
                }
                if (strArray.Length == 3)
                {
                    this._prot = strArray[2].GetString();
                }
                else
                {
                    this._prot = "HTTP/1.0";
                }
                int index = str2.IndexOf('?');
                if (index > 0)
                {
                    this._queryStringBytes = str2.Substring(index + 1).GetBytes();
                }
                else
                {
                    this._queryStringBytes = new byte[0];
                }
                index = this._url.IndexOf('?');
                if (index > 0)
                {
                    this._path = this._url.Substring(0, index);
                    this._queryString = this._url.Substring(index + 1);
                }
                else
                {
                    this._path = this._url;
                    this._queryString = string.Empty;
                }
                if (this._path.IndexOf('%') >= 0)
                {
                    this._path = HttpUtility.UrlDecode(this._path, Encoding.UTF8);
                    index = this._url.IndexOf('?');
                    if (index >= 0)
                    {
                        this._url = this._path + this._url.Substring(index);
                    }
                    else
                    {
                        this._url = this._path;
                    }
                }
                int startIndex = this._path.LastIndexOf('.');
                int num3 = this._path.LastIndexOf('/');
                if (((startIndex >= 0) && (num3 >= 0)) && (startIndex < num3))
                {
                    int length = this._path.IndexOf('/', startIndex);
                    this._filePath = this._path.Substring(0, length);
                    this._pathInfo = this._path.Substring(length);
                }
                else
                {
                    this._filePath = this._path;
                    this._pathInfo = string.Empty;
                }
                this._pathTranslated = this.MapPath(this._filePath);
            }
        }

        private void PrepareResponse()
        {
            this._headersSent = false;
            this._responseStatus = 200;
            this._responseHeadersBuilder = new StringBuilder();
            this._responseBodyBytes = new ArrayList();
        }

        [AspNetHostingPermission(SecurityAction.Assert, Level=AspNetHostingPermissionLevel.Medium)]
        public void Process()
        {
            if (this.TryParseRequest())
            {
                if (((this._verb == "POST") && (this._contentLength > 0)) && (this._preloadedContentLength < this._contentLength))
                {
                    this._connection.Write100Continue();
                }
                if (!this._host.RequireAuthentication || this.TryNtlmAuthenticate())
                {
                    if (this._isClientScriptPath)
                    {
                        this._connection.WriteEntireResponseFromFile(this._host.PhysicalClientScriptPath + this._path.Substring(this._host.NormalizedClientScriptPath.Length), false);
                    }
                    else if (this.IsRequestForRestrictedDirectory())
                    {
                        this._connection.WriteErrorAndClose(0x193);
                    }
                    else if (!this.ProcessDefaultDocumentRequest())
                    {
                        this.PrepareResponse();
                        HttpRuntime.ProcessRequest(this);
                    }
                }
            }
        }

        private bool ProcessDefaultDocumentRequest()
        {
            if (this._verb == "GET")
            {
                string path = this._pathTranslated;
                if (this._pathInfo.Length > 0)
                {
                    path = this.MapPath(this._path);
                }
                if (!Directory.Exists(path))
                {
                    return false;
                }
                if (!this._path.EndsWith("/", StringComparison.Ordinal))
                {
                    string str2 = this._path + "/";
                    string extraHeaders = "Location: " + UrlEncodeRedirect(str2) + "\r
"; string body = "<html><head><title>Object moved</title></head><body>\r
<h2>Object moved to <a href='" + str2 + "'>here</a>.</h2>\r
</body></html>\r
"; this._connection.WriteEntireResponseFromString(0x12e, extraHeaders, body, false); return true; } foreach (string str5 in defaultFileNames) { string str6 = path + @"\" + str5; if (File.Exists(str6)) { this._path = this._path + str5; this._filePath = this._path; this._url = (this._queryString != null) ? (this._path + "?" + this._queryString) : this._path; this._pathTranslated = str6; return false; } } } return false; } private bool ProcessDirectoryListingRequest() { if (this._verb != "GET") { return false; } string path = this._pathTranslated; if (this._pathInfo.Length > 0) { path = this.MapPath(this._path); } if (!Directory.Exists(path)) { return false; } if (this._host.DisableDirectoryListing) { return false; } FileSystemInfo[] elements = null; try { elements = new DirectoryInfo(path).GetFileSystemInfos(); } catch { } string str2 = null; if (this._path.Length > 1) { int length = this._path.LastIndexOf('/', this._path.Length - 2); str2 = (length > 0) ? this._path.Substring(0, length) : "/"; if (!this._host.IsVirtualPathInApp(str2)) { str2 = null; } } this._connection.WriteEntireResponseFromString(200, "Content-type: text/html; charset=utf-8\r
", Messages.FormatDirectoryListing(this._path, str2, elements), false); return true; } private void ReadAllHeaders() { this._headerBytes = null; do { if (!this.TryReadAllHeaders()) { return; } } while (this._endHeadersOffset < 0); } public override int ReadEntityBody(byte[] buffer, int size) { int count = 0; this._connectionPermission.Assert(); byte[] src = this._connection.ReadRequestBytes(size); if ((src != null) && (src.Length > 0)) { count = src.Length; Buffer.BlockCopy(src, 0, buffer, 0, count); } return count; } private void Reset() { this._headerBytes = null; this._startHeadersOffset = 0; this._endHeadersOffset = 0; this._headerByteStrings = null; this._isClientScriptPath = false; this._verb = null; this._url = null; this._prot = null; this._path = null; this._filePath = null; this._pathInfo = null; this._pathTranslated = null; this._queryString = null; this._queryStringBytes = null; this._contentLength = 0; this._preloadedContentLength = 0; this._preloadedContent = null; this._allRawHeaders = null; this._unknownRequestHeaders = null; this._knownRequestHeaders = null; this._specialCaseStaticFileHeaders = false; } public override void SendCalculatedContentLength(int contentLength) { if (!this._headersSent) { this._responseHeadersBuilder.Append("Content-Length: "); this._responseHeadersBuilder.Append(contentLength.ToString(CultureInfo.InvariantCulture)); this._responseHeadersBuilder.Append("\r
"); } } public override void SendKnownResponseHeader(int index, string value) { if (!this._headersSent) { switch (index) { case 1: case 2: case 0x1a: return; case 0x12: case 0x13: if (!this._specialCaseStaticFileHeaders) { break; } return; case 20: if (!(value == "bytes")) { break; } this._specialCaseStaticFileHeaders = true; return; } this._responseHeadersBuilder.Append(HttpWorkerRequest.GetKnownResponseHeaderName(index)); this._responseHeadersBuilder.Append(": "); this._responseHeadersBuilder.Append(value); this._responseHeadersBuilder.Append("\r
"); } } public override void SendResponseFromFile(IntPtr handle, long offset, long length) { if (length != 0) { FileStream f = null; try { SafeFileHandle handle2 = new SafeFileHandle(handle, false); f = new FileStream(handle2, FileAccess.Read); this.SendResponseFromFileStream(f, offset, length); } finally { if (f != null) { f.Close(); f = null; } } } } public override void SendResponseFromFile(string filename, long offset, long length) { if (length != 0) { FileStream f = null; try { f = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); this.SendResponseFromFileStream(f, offset, length); } finally { if (f != null) { f.Close(); } } } } private void SendResponseFromFileStream(FileStream f, long offset, long length) { long num = f.Length; if (length == -1) { length = num - offset; } if (((length != 0) && (offset >= 0)) && (length <= (num - offset))) { if (offset > 0) { f.Seek(offset, SeekOrigin.Begin); } if (length <= 0x10000) { byte[] buffer = new byte[(int) length]; int num2 = f.Read(buffer, 0, (int) length); this.SendResponseFromMemory(buffer, num2); } else { byte[] buffer2 = new byte[0x10000]; int num3 = (int) length; while (num3 > 0) { int count = (num3 < 0x10000) ? num3 : 0x10000; int num5 = f.Read(buffer2, 0, count); this.SendResponseFromMemory(buffer2, num5); num3 -= num5; if ((num3 > 0) && (num5 > 0)) { this.FlushResponse(false); } } } } } public override void SendResponseFromMemory(byte[] data, int length) { if (length > 0) { byte[] dst = new byte[length]; Buffer.BlockCopy(data, 0, dst, 0, length); this._responseBodyBytes.Add(dst); } } public override void SendStatus(int statusCode, string statusDescription) { this._responseStatus = statusCode; } public override void SendUnknownResponseHeader(string name, string value) { if (!this._headersSent) { this._responseHeadersBuilder.Append(name); this._responseHeadersBuilder.Append(": "); this._responseHeadersBuilder.Append(value); this._responseHeadersBuilder.Append("\r
"); } } private void SkipAllPostedContent() { if ((this._contentLength > 0) && (this._preloadedContentLength < this._contentLength)) { byte[] buffer; for (int i = this._contentLength - this._preloadedContentLength; i > 0; i -= buffer.Length) { buffer = this._connection.ReadRequestBytes(i); if ((buffer == null) || (buffer.Length == 0)) { return; } } } } [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true), SecurityPermission(SecurityAction.Assert, ControlPrincipal=true)] private bool TryNtlmAuthenticate() { try { using (NtlmAuth auth = new NtlmAuth()) { do { string blobString = null; string extraHeaders = this._knownRequestHeaders[0x18]; if ((extraHeaders != null) && extraHeaders.StartsWith("NTLM ", StringComparison.Ordinal)) { blobString = extraHeaders.Substring(5); } if (blobString != null) { if (!auth.Authenticate(blobString)) { this._connection.WriteErrorAndClose(0x193); return false; } if (auth.Completed) { goto Label_009A; } extraHeaders = "WWW-Authenticate: NTLM " + auth.Blob + "\r
"; } else { extraHeaders = "WWW-Authenticate: NTLM\r
"; } this.SkipAllPostedContent(); this._connection.WriteErrorWithExtraHeadersAndKeepAlive(0x191, extraHeaders); } while (this.TryParseRequest()); return false; Label_009A: if (this._host.GetProcessSID() != auth.SID) { this._connection.WriteErrorAndClose(0x193); return false; } } } catch { try { this._connection.WriteErrorAndClose(500); } catch { } return false; } return true; } private bool TryParseRequest() { this.Reset(); this.ReadAllHeaders(); //if (!this._connection.IsLocal) //{ // this._connection.WriteErrorAndClose(0x193); // return false; //} if (((this._headerBytes == null) || (this._endHeadersOffset < 0)) || ((this._headerByteStrings == null) || (this._headerByteStrings.Count == 0))) { this._connection.WriteErrorAndClose(400); return false; } this.ParseRequestLine(); if (this.IsBadPath()) { this._connection.WriteErrorAndClose(400); return false; } if (!this._host.IsVirtualPathInApp(this._path, out this._isClientScriptPath)) { this._connection.WriteErrorAndClose(0x194); return false; } this.ParseHeaders(); this.ParsePostedContent(); return true; } private bool TryReadAllHeaders() { byte[] src = this._connection.ReadRequestBytes(0x8000); if ((src == null) || (src.Length == 0)) { return false; } if (this._headerBytes != null) { int num = src.Length + this._headerBytes.Length; if (num > 0x8000) { return false; } byte[] dst = new byte[num]; Buffer.BlockCopy(this._headerBytes, 0, dst, 0, this._headerBytes.Length); Buffer.BlockCopy(src, 0, dst, this._headerBytes.Length, src.Length); this._headerBytes = dst; } else { this._headerBytes = src; } this._startHeadersOffset = -1; this._endHeadersOffset = -1; this._headerByteStrings = new ArrayList(); ByteParser parser = new ByteParser(this._headerBytes); while (true) { ByteString str = parser.ReadLine(); if (str == null) { break; } if (this._startHeadersOffset < 0) { this._startHeadersOffset = parser.CurrentOffset; } if (str.IsEmpty) { this._endHeadersOffset = parser.CurrentOffset; break; } this._headerByteStrings.Add(str); } return true; } private static string UrlEncodeRedirect(string path) { byte[] bytes = Encoding.UTF8.GetBytes(path); int length = bytes.Length; int num2 = 0; for (int i = 0; i < length; i++) { if ((bytes[i] & 0x80) != 0) { num2++; } } if (num2 > 0) { byte[] buffer2 = new byte[length + (num2 * 2)]; int num4 = 0; for (int j = 0; j < length; j++) { byte num6 = bytes[j]; if ((num6 & 0x80) == 0) { buffer2[num4++] = num6; } else { buffer2[num4++] = 0x25; buffer2[num4++] = (byte) IntToHex[(num6 >> 4) & 15]; buffer2[num4++] = (byte) IntToHex[num6 & 15]; } } path = Encoding.ASCII.GetString(buffer2); } if (path.IndexOf(' ') >= 0) { path = path.Replace(" ", "%20"); } return path; } } }
namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Globalization;
    using System.Net;
    using System.Net.Sockets;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    using System.Security.Principal;
    using System.Threading;
    using System.Web.Hosting;
    using System.Web;
    using System.Reflection;

    [PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust"), PermissionSet(SecurityAction.LinkDemand, Name = "Everything")]
    public class Server : MarshalByRefObject
    {
        private ApplicationManager _appManager;
        private bool _disableDirectoryListing;
        private Host _host;
        private object _lockObject;
        private WaitCallback _onSocketAccept;
        private WaitCallback _onStart;
        private string _physicalPath;
        private int _port;
        private IntPtr _processToken;
        private string _processUser;
        private bool _requireAuthentication;
        private bool _shutdownInProgress;
        private Socket _socketIpv4;
        private Socket _socketIpv6;
        private string _virtualPath;
        private const int SecurityImpersonation = 2;
        private const int TOKEN_ALL_ACCESS = 0xf01ff;
        private const int TOKEN_EXECUTE = 0x20000;
        private const int TOKEN_IMPERSONATE = 4;
        private const int TOKEN_READ = 0x20008;

        public Server(int port, string virtualPath, string physicalPath)
            : this(port, virtualPath, physicalPath, false, false)
        {
        }

        public Server(int port, string virtualPath, string physicalPath, bool requireAuthentication)
            : this(port, virtualPath, physicalPath, requireAuthentication, false)
        {
        }

        public Server(int port, string virtualPath, string physicalPath, bool requireAuthentication, bool disableDirectoryListing)
        {
            this._lockObject = new object();
            this._port = port;
            this._virtualPath = virtualPath;
            this._physicalPath = physicalPath.EndsWith(@"\", StringComparison.Ordinal) ? physicalPath : (physicalPath + @"\");
            this._requireAuthentication = requireAuthentication;
            this._disableDirectoryListing = disableDirectoryListing;
            this._onSocketAccept = new WaitCallback(this.OnSocketAccept);
            this._onStart = new WaitCallback(this.OnStart);
            this._appManager = ApplicationManager.GetApplicationManager();
            this.ObtainProcessToken();
        }

        private Socket CreateSocketBindAndListen(AddressFamily family, IPAddress ipAddress, int port)
        {
            Socket socket = new Socket(family, SocketType.Stream, ProtocolType.Tcp)
            {
                ExclusiveAddressUse = false
            };
            try
            {
                socket.Bind(new IPEndPoint(ipAddress, port));
            }
            catch
            {
                socket.Close();
                socket = null;
                throw;
            }
            socket.Listen(0x7fffffff);
            return socket;
        }

        [DllImport("KERNEL32.DLL", SetLastError = true)]
        private static extern IntPtr GetCurrentThread();
        private Host GetHost()
        {
            if (this._shutdownInProgress)
            {
                return null;
            }
            Host host = this._host;
            if (host == null)
            {
                lock (this._lockObject)
                {
                    host = this._host;
                    if (host == null)
                    {
                        string appId = (this._virtualPath + this._physicalPath).ToLowerInvariant().GetHashCode().ToString("x", CultureInfo.InvariantCulture);
                        //this._host = (Host) this._appManager.CreateObject(appId, typeof(Host), this._virtualPath, this._physicalPath, false);
                        Type hostType = typeof(Host);
                        var buildManagerHostType = typeof(HttpRuntime).Assembly.GetType("System.Web.Compilation.BuildManagerHost");
                        var buildManagerHost = _appManager.CreateObject(appId, buildManagerHostType, _virtualPath, _physicalPath, false);
                        buildManagerHostType.InvokeMember("RegisterAssembly", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic, null, buildManagerHost, new object[] { hostType.Assembly.FullName, hostType.Assembly.Location });
                       
                        this._host = (Host) this._appManager.CreateObject(appId, hostType, this._virtualPath, this._physicalPath, false);
                        this._host.Configure(this, this._port, this._virtualPath, this._physicalPath, this._requireAuthentication, this._disableDirectoryListing);
                        host = this._host;
                    }
                }
            }
            return host;
        }
      
        public IntPtr GetProcessToken()
        {
            return this._processToken;
        }

        public string GetProcessUser()
        {
            return this._processUser;
        }

        internal void HostStopped()
        {
            this._host = null;
        }

        [DllImport("ADVAPI32.DLL", SetLastError = true)]
        private static extern bool ImpersonateSelf(int level);
        public override object InitializeLifetimeService()
        {
            return null;
        }

        private void ObtainProcessToken()
        {
            if (ImpersonateSelf(2))
            {
                OpenThreadToken(GetCurrentThread(), 0xf01ff, true, ref this._processToken);
                RevertToSelf();
                this._processUser = WindowsIdentity.GetCurrent().Name;
            }
        }

        private void OnSocketAccept(object acceptedSocket)
        {
            if (!this._shutdownInProgress)
            {
                Microsoft.VisualStudio.WebHost.Connection conn = new Microsoft.VisualStudio.WebHost.Connection(this, (Socket)acceptedSocket);
                if (conn.WaitForRequestBytes() == 0)
                {
                    conn.WriteErrorAndClose(400);
                }
                else
                {
                    Host host = this.GetHost();
                    if (host == null)
                    {
                        conn.WriteErrorAndClose(500);
                    }
                    else
                    {
                        host.ProcessRequest(conn);
                    }
                }
            }
        }

        private void OnStart(object listeningSocket)
        {
            while (!this._shutdownInProgress)
            {
                try
                {
                    if (listeningSocket != null)
                    {
                        Socket state = ((Socket)listeningSocket).Accept();
                        ThreadPool.QueueUserWorkItem(this._onSocketAccept, state);
                    }
                    continue;
                }
                catch
                {
                    Thread.Sleep(100);
                    continue;
                }
            }
        }

        [DllImport("ADVAPI32.DLL", SetLastError = true)]
        private static extern int OpenThreadToken(IntPtr thread, int access, bool openAsSelf, ref IntPtr hToken);
        [DllImport("ADVAPI32.DLL", SetLastError = true)]
        private static extern int RevertToSelf();
        public void Start()
        {
            bool flag = false;
            flag = Socket.OSSupportsIPv4;
            if (Socket.OSSupportsIPv6)
            {
                try
                {
                    this._socketIpv6 = this.CreateSocketBindAndListen(AddressFamily.InterNetworkV6, IPAddress.IPv6Loopback, this._port);
                }
                catch (SocketException exception)
                {
                    if ((exception.SocketErrorCode == SocketError.AddressAlreadyInUse) || !flag)
                    {
                        throw;
                    }
                }
            }
            if (flag)
            {
                try
                {
                  // Environment.MachineName
                    IPHostEntry hosts = Dns.GetHostByName(Environment.MachineName);
                    IPAddress address = IPAddress.Loopback;
                    if (hosts.AddressList.Length > 0)
                        address = hosts.AddressList[0];
                    this._socketIpv4 = this.CreateSocketBindAndListen(AddressFamily.InterNetwork, address, this._port);
                }
                catch (SocketException)
                {
                    if (this._socketIpv6 == null)
                    {
                        throw;
                    }
                }
            }
            if (this._socketIpv6 != null)
            {
                ThreadPool.QueueUserWorkItem(this._onStart, this._socketIpv6);
            }
            if (this._socketIpv4 != null)
            {
                ThreadPool.QueueUserWorkItem(this._onStart, this._socketIpv4);
            }
        }

        public void Stop()
        {
            this._shutdownInProgress = true;
            try
            {
                if (this._socketIpv4 != null)
                {
                    this._socketIpv4.Close();
                }
                if (this._socketIpv6 != null)
                {
                    this._socketIpv6.Close();
                }
            }
            catch
            {
            }
            finally
            {
                this._socketIpv4 = null;
                this._socketIpv6 = null;
            }
            try
            {
                if (this._host != null)
                {
                    this._host.Shutdown();
                }
                while (this._host != null)
                {
                    Thread.Sleep(100);
                }
            }
            catch
            {
            }
            finally
            {
                this._host = null;
            }
        }

        public string PhysicalPath
        {
            get
            {
                return this._physicalPath;
            }
        }

        public int Port
        {
            get
            {
                return this._port;
            }
        }

        public string RootUrl
        {
            get
            {
                if (this._port != 80)
                {
                    return ("http://localhost:" + this._port + this._virtualPath);
                }
                return ("http://localhost" + this._virtualPath);
            }
        }

        public string VirtualPath
        {
            get
            {
                return this._virtualPath;
            }
        }
    }
}


호출 코드:
     Server s = new Server(49152, "/", @"C:\Users\majiang\Documents\Visual Studio 2010\Projects\ConsoleApp\WebApp");             s.Start();
벽돌을 두드리는 걸 환영합니다.

좋은 웹페이지 즐겨찾기