您的位置:首页 > 编程语言 > ASP

开发自定义的web IIS服务器 WebDev.WebHost 用控制台托起web服务 上次写了一篇ASP.NET一个简易的WebServer,用控制台程序模拟IIS 托起web服务 看见有一朋友说在

2017-09-25 14:18 1216 查看


开发自定义的web IIS服务器 WebDev.WebHost 用控制台托起web服务

http://www.cnblogs.com/majiang/archive/2012/09/07/2674535.html

上次写了一篇ASP.NET一个简易的WebServer,用控制台程序模拟IIS 托起web服务 看见有一朋友说在中文情况下返回乱码。我平时用的都是英文开发环境,即使涉及到中文也不是乱码,但是在公司中文的vs环境下也出现了乱码。一时半会不中的怎么解决。后来想起vs内嵌的那个服务器。。。。,于是乎拿来改写一下。
先说说几个帮助类吧,我们中的http协议中请求头都是以\r\n\r\n结束的 在请求头中每个指令都是以\r\n分隔的, ByteParser就是用来分隔请求类容,再把一行的内容装到ByteString里面,ByteString主要作用是把字节转为字符。而Messages只是返回一些默认消息。Host就像原先的WebServer一样用来处理请求,Request是实现SimpleWorkerRequest的,用来真正处理用户请求。Server就是用来封装Host的暴露给调用者。至于NtlmAuth类没怎么明白好像是处理身份认证之类的东东。。。
还是吧修改后的代码贴出来吧:



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\n";
private const string _dirListingFileFormat = "{0,38:dddd, MMMM dd, yyyy hh:mm tt} {1,12:n0} <A href=\"{2}\">{3}</A>\r\n";
private const string _dirListingFormat1 = "<html>\r\n    <head>\r\n    <title>{0}</title>\r\n";
private const string _dirListingFormat2 = "    </head>\r\n    <body bgcolor=\"white\">\r\n\r\n    <h2> <i>{0}</i> </h2></span>\r\n\r\n            <hr width=100% size=1 color=silver>\r\n\r\n<PRE>\r\n";
private const string _dirListingParentFormat = "<A href=\"{0}\">[To Parent Directory]</A>\r\n\r\n";
private static string _dirListingTail = ("</PRE>\r\n            <hr width=100% size=1 color=silver>\r\n\r\n              <b>{0}:</b> {1} " + VersionString + "\r\n\r\n            </font>\r\n\r\n    </body>\r\n</html>\r\n");
private const string _httpErrorFormat1 = "<html>\r\n    <head>\r\n        <title>{0}</title>\r\n";
private static string _httpErrorFormat2 = ("    </head>\r\n    <body bgcolor=\"white\">\r\n\r\n            <span><h1>{0}<hr width=100% size=1 color=silver></h1>\r\n\r\n            <h2> <i>{1}</i> </h2></span>\r\n\r\n            <hr width=100% size=1 color=silver>\r\n\r\n            <b>{2}:</b> {3} " + VersionString + "\r\n\r\n            </font>\r\n\r\n    </body>\r\n</html>\r\n");
private const string _httpStyle = "        <style>\r\n        \tbody {font-family:\"Verdana\";font-weight:normal;font-size: 8pt;color:black;} \r\n        \tp {font-family:\"Verdana\";font-weight:normal;color:black;margin-top: -5px}\r\n        \tb {font-family:\"Verdana\";font-weight:bold;color:black;margin-top: -5px}\r\n        \th1 { font-family:\"Verdana\";font-weight:normal;font-size:18pt;color:red }\r\n        \th2 { font-family:\"Verdana\";font-weight:normal;font-size:14pt;color:maroon }\r\n        \tpre {font-family:\"Lucida Console\";font-size: 8pt}\r\n        \t.marker {font-weight: bold; color: black;text-decoration: none;}\r\n        \t.version {color: gray;}\r\n        \t.error {margin-bottom: 10px;}\r\n        \t.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }\r\n        </style>\r\n";
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\n    <head>\r\n    <title>{0}</title>\r\n", new object[] { str }));
builder.Append("        <style>\r\n        \tbody {font-family:\"Verdana\";font-weight:normal;font-size: 8pt;color:black;} \r\n        \tp {font-family:\"Verdana\";font-weight:normal;color:black;margin-top: -5px}\r\n        \tb {font-family:\"Verdana\";font-weight:bold;color:black;margin-top: -5px}\r\n        \th1 { font-family:\"Verdana\";font-weight:normal;font-size:18pt;color:red }\r\n        \th2 { font-family:\"Verdana\";font-weight:normal;font-size:14pt;color:maroon }\r\n        \tpre {font-family:\"Lucida Console\";font-size: 8pt}\r\n        \t.marker {font-weight: bold; color: black;text-decoration: none;}\r\n        \t.version {color: gray;}\r\n        \t.error {margin-bottom: 10px;}\r\n        \t.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }\r\n        </style>\r\n");
builder.Append(string.Format(CultureInfo.InvariantCulture, "    </head>\r\n    <body bgcolor=\"white\">\r\n\r\n    <h2> <i>{0}</i> </h2></span>\r\n\r\n            <hr width=100% size=1 color=silver>\r\n\r\n<PRE>\r\n", 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\n\r\n", 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\n", 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\n", 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\n    <head>\r\n        <title>{0}</title>\r\n", new object[] { statusDescription }) + "        <style>\r\n        \tbody {font-family:\"Verdana\";font-weight:normal;font-size: 8pt;color:black;} \r\n        \tp {font-family:\"Verdana\";font-weight:normal;color:black;margin-top: -5px}\r\n        \tb {font-family:\"Verdana\";font-weight:bold;color:black;margin-top: -5px}\r\n        \th1 { font-family:\"Verdana\";font-weight:normal;font-size:18pt;color:red }\r\n        \th2 { font-family:\"Verdana\";font-weight:normal;font-size:14pt;color:maroon }\r\n        \tpre {font-family:\"Lucida Console\";font-size: 8pt}\r\n        \t.marker {font-weight: bold; color: black;text-decoration: none;}\r\n        \t.version {color: gray;}\r\n        \t.error {margin-bottom: 10px;}\r\n        \t.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }\r\n        </style>\r\n" + 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.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 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\n<!--\r\n" + message + "\r\n-->";
}
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\n");
}

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\n" }));
builder.Append("Server: ASP.NET Development Server/" + Messages.VersionString + "\r\n");
builder.Append("Date: " + DateTime.Now.ToUniversalTime().ToString("R", DateTimeFormatInfo.InvariantInfo) + "\r\n");
if (contentLength >= 0)
{
builder.Append("Content-Length: " + contentLength + "\r\n");
}
if (moreHeaders != null)
{
builder.Append(moreHeaders);
}
if (!keepAlive)
{
builder.Append("Connection: Close\r\n");
}
builder.Append("\r\n");
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\n", 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 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\n";
string body = "<html><head><title>Object moved</title></head><body>\r\n<h2>Object moved to <a href='" + str2 + "'>here</a>.</h2>\r\n</body></html>\r\n";
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\n", 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\n");
}
}

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\n");
}
}

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\n");
}
}

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\n";
}
else
{
extraHeaders = "WWW-Authenticate: NTLM\r\n";
}
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();
欢迎大家拍砖
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐