Ver Fonte

2002-04-10 Patrik Torstensson <[email protected]>

    * HttpWorkerRequest.EndOfSendNotification.cs Removed (included in WorkerRequest)
    * Checkin of all new files (noted in last changenote)

svn path=/trunk/mcs/; revision=3732
Patrik Torstensson há 24 anos atrás
pai
commit
e79159ff2d

+ 5 - 0
mcs/class/System.Web/System.Web/ChangeLog

@@ -1,3 +1,8 @@
+2002-04-10  Patrik Torstensson <[email protected]>
+
+    * HttpWorkerRequest.EndOfSendNotification.cs Removed (included in WorkerRequest)
+    * Checkin of all new files (noted in last changenote)
+
 2002-04-10  Patrik Torstensson <[email protected]>
 
     * HttpContext.cs: First implementation (basic support, few methods left to impl)

+ 18 - 0
mcs/class/System.Web/System.Web/HttpApplication.cs

@@ -0,0 +1,18 @@
+   // 
+// System.Web.HttpApplication
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+
+namespace System.Web {
+   [MonoTODO()]
+   public class HttpApplication {
+      public HttpApplication() {
+         //
+         // TODO: Add constructor logic here
+         //
+      }
+   }
+}

+ 20 - 0
mcs/class/System.Web/System.Web/HttpApplicationState.cs

@@ -0,0 +1,20 @@
+// 
+// System.Web.HttpApplicationState
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+
+namespace System.Web {
+
+   [MonoTODO()]
+   public class HttpApplicationState {
+      [MonoTODO()]
+      internal HttpApplicationState() {
+         //
+         // TODO: Add constructor logic here
+         //
+      }
+   }
+}

+ 18 - 0
mcs/class/System.Web/System.Web/HttpBrowserCapabilites.cs

@@ -0,0 +1,18 @@
+// 
+// System.Web.HttpBrowserCapabilites
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+
+namespace System.Web {
+   [MonoTODO()]
+   public class HttpBrowserCapabilites {
+      public HttpBrowserCapabilites() {
+         //
+         // TODO: Add constructor logic here
+         //
+      }
+   }
+}

+ 18 - 0
mcs/class/System.Web/System.Web/HttpCachePolicy.cs

@@ -0,0 +1,18 @@
+// 
+// System.Web.HttpCachePolicy
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+
+namespace System.Web {
+
+   public class HttpCachePolicy {
+      public HttpCachePolicy() {
+         //
+         // TODO: Add constructor logic here
+         //
+      }
+   }
+}

+ 18 - 0
mcs/class/System.Web/System.Web/HttpClientCertificate.cs

@@ -0,0 +1,18 @@
+// 
+// System.Web.HttpClientCertificate
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+
+namespace System.Web {
+   [MonoTODO()]
+   public class HttpClientCertificate {
+      public HttpClientCertificate() {
+         //
+         // TODO: Add constructor logic here
+         //
+      }
+   }
+}

+ 243 - 0
mcs/class/System.Web/System.Web/HttpContext.cs

@@ -0,0 +1,243 @@
+// 
+// System.Web.HttpContext
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+using System.Collections;
+using System.Security.Principal;
+using System.Web.Caching;
+using System.Threading;
+
+namespace System.Web {
+   [MonoTODO("HttpContext - Should also keep the script timeout info")]
+   public class HttpContext : IServiceProvider {
+      private Exception []	_arrExceptions;
+
+      private HttpResponse	_oResponse;
+      private HttpRequest _oRequest;
+      private HttpServerUtility _Server;
+      private HttpApplication _oApplication;
+      private IHttpHandler _Handler;
+      private IPrincipal _User;
+      
+      private Hashtable		_oItems;
+      private DateTime		_oTimestamp;
+
+      public HttpContext(HttpRequest Request, HttpResponse Response) {
+         Context = this;
+
+         _arrExceptions = null;
+         _oItems = null;
+         _oTimestamp = DateTime.Now;
+         _oRequest = Request;
+         _oResponse = Response;
+      }
+
+      public HttpContext(HttpWorkerRequest WorkerRequest) {
+         Context = this;
+
+         _arrExceptions = null;
+         _oItems = null;
+         _oTimestamp = DateTime.Now;
+         _oRequest = new HttpRequest(WorkerRequest, this);
+         _oResponse = new HttpResponse(WorkerRequest, this);
+      }
+      
+      [MonoTODO("Context - Use System.Remoting.Messaging.CallContext instead of Thread storage")]
+      internal static HttpContext Context {
+         get {
+            return (HttpContext) Thread.GetData(Thread.GetNamedDataSlot("Context"));
+         }
+
+         set {
+            Thread.SetData(Thread.GetNamedDataSlot("Context"), value);
+         }
+      }
+
+      public Exception [] AllErrors {
+         get {
+            return _arrExceptions;
+         }
+      }
+
+      [MonoTODO("HttpApplicationState Application")]
+      public HttpApplicationState Application {
+         get {
+            // Should get the state from a app factory (or the app it self) static method?
+            throw new NotImplementedException();
+         }
+      }
+
+      public HttpApplication ApplicationInstance {
+         get {
+            return _oApplication;
+         }
+         set {
+            _oApplication = value;
+         }
+      }
+
+      [MonoTODO("HttpCache Cache")]
+      public Cache Cache {
+         get {
+            // Get the cache from the runtime
+            throw new NotImplementedException();
+         }
+      }
+
+      public static HttpContext Current {
+         get {
+            return Context;
+         }
+      }
+
+      public Exception Error {
+         get {
+            if (_arrExceptions == null) {
+               return null;
+            } 
+            else {
+               return _arrExceptions[0];
+            }
+         }
+      }
+
+      public IHttpHandler Handler {
+         get {    
+            return _Handler;
+         }
+         
+         set {
+            _Handler = value;
+         }
+      }
+
+      [MonoTODO("bool IsCustomErrorEnabled")]
+      public bool IsCustomErrorEnabled {
+         get {
+            throw new NotImplementedException();
+         }
+      }
+
+      [MonoTODO("bool IsDebuggingEnabled")]
+      public bool IsDebuggingEnabled {
+         get {
+            throw new NotImplementedException();
+         }
+      }
+
+      public IDictionary Items {
+         get {
+            if (_oItems == null) {
+               _oItems = new Hashtable();
+            }
+				
+            return _oItems;
+         }
+      }
+
+      public HttpRequest Request {
+         get {
+            return _oRequest;
+         }
+      }
+
+      public HttpResponse Response {
+         get {
+            return _oResponse;
+         }
+      }
+
+      public HttpServerUtility Server {
+         get {
+            if (null == _Server) {
+               _Server = new HttpServerUtility(this);
+            }
+            
+            return _Server; 
+         }
+      }
+      
+      [MonoTODO("HttpSessionState Session")]
+      public HttpSessionState Session {
+         get {
+            throw new NotImplementedException();
+         }
+      }
+
+      [MonoTODO("bool SkipAuthorization")]
+      public bool SkipAuthorization {
+         get {
+            throw new NotImplementedException();
+         }
+      }
+
+      public DateTime Timestamp {
+         get {
+            return _oTimestamp;
+         }
+      }
+      
+      [MonoTODO("TraceContext Trace")]
+      public TraceContext Trace {
+         get {
+            // TODO: Should be initialized in the constructor (holds current trace)
+            throw new NotImplementedException();
+         }
+      }
+      
+      public IPrincipal User {
+         get {
+            return _User;
+         }
+         set {
+            // TODO: Should check security (ControlPrincipal flag)
+            _User = value;
+         }
+      }
+		
+      public void AddError(Exception errorInfo) {
+         int iSize;
+
+         if (_arrExceptions == null) {
+            iSize = 1;
+         } 
+         else {
+            iSize = _arrExceptions.Length + 1;
+         }
+
+         Exception [] arrNew = new Exception[iSize];
+
+         _arrExceptions.CopyTo(arrNew, 0);
+         _arrExceptions = arrNew;
+
+         _arrExceptions[iSize - 1] = errorInfo;
+      }
+
+      public void ClearError() {
+         _arrExceptions = null;
+      }
+
+      [MonoTODO("GetConfig(string name)")]
+      public object GetConfig(string name) {
+         throw new NotImplementedException();
+      }
+
+      [MonoTODO("GetAppConfig(string name)")]
+      public static object GetAppConfig(string name) {
+         throw new NotImplementedException();
+      }
+      
+      [MonoTODO("IServiceProvider.GetService(Type service)")]
+      object IServiceProvider.GetService(Type service) {
+         throw new NotImplementedException();
+      }
+
+      [MonoTODO("void RewritePath(string path)")]
+      public void RewritePath(string Path) {
+         throw new NotImplementedException();
+      }
+   }
+}

+ 33 - 0
mcs/class/System.Web/System.Web/HttpException.cs

@@ -0,0 +1,33 @@
+// 
+// System.Web.HttpException
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+using System.Runtime.InteropServices;
+
+namespace System.Web {
+   [MonoTODO("This class contains a lot of windows specific methods, solve this.. :)")]
+   public class HttpException : ExternalException {
+      private int _HttpCode;
+
+      public HttpException(string sMessage) : base(sMessage) {
+      }
+
+      public HttpException(string sMessage, Exception InnerException) : base(sMessage, InnerException) {
+      }
+
+      public HttpException(int iHttpCode, string sMessage) : base(sMessage) {
+         _HttpCode = iHttpCode;
+      }
+
+      public HttpException(int iHttpCode, string sMessage, Exception InnerException) : base(sMessage, InnerException) {
+         _HttpCode = iHttpCode;
+      }
+
+      public int GetHttpCode() {
+         return _HttpCode;
+      }
+   }
+}

+ 18 - 0
mcs/class/System.Web/System.Web/HttpFileCollection.cs

@@ -0,0 +1,18 @@
+// 
+// System.Web.HttpFileCollection
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+
+namespace System.Web {
+   [MonoTODO()]
+   public class HttpFileCollection {
+      public HttpFileCollection() {
+         //
+         // TODO: Add constructor logic here
+         //
+      }
+   }
+}

+ 48 - 0
mcs/class/System.Web/System.Web/HttpHelper.cs

@@ -0,0 +1,48 @@
+// 
+// System.Web.HttpHelper
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+using System.Collections;
+using System.IO;
+
+namespace System.Web {
+   internal class HttpHelper {
+      internal static string [] ParseMultiValueHeader(string header) {
+         if (null == header) {
+            return null;
+         }
+
+         if (header.Length == 0) {
+            return null;
+         }
+
+         // Parse the , chars
+         Stack oValues = new Stack();
+
+         string sValue;
+
+         int iLastPos = -1;
+         int iPos = header.IndexOf(",");
+
+         while (iPos != -1) {
+            sValue = header.Substring(iLastPos + 1, iPos - iLastPos - 1).Trim();
+            iLastPos = iPos;
+
+            iPos = header.IndexOf(",", iPos + 1);
+            oValues.Push(sValue);
+         }
+
+         sValue = header.Substring(iLastPos + 1).Trim();
+         oValues.Push(sValue);
+
+         string [] arrValues = new string[oValues.Count];
+
+         Array.Copy(oValues.ToArray(), 0, arrValues, 0, oValues.Count);
+
+         return arrValues;
+      }
+   }
+}

+ 841 - 0
mcs/class/System.Web/System.Web/HttpRequest.cs

@@ -0,0 +1,841 @@
+// 
+// System.Web.HttpRequest
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.IO;
+using System.Text;
+
+namespace System.Web {
+   //-- Methods from HttpRequest not implemented
+   //		public HttpFileCollection Files {get;}
+   //		public HttpBrowserCapabilities Browser {get; set;}
+   //		public HttpClientCertificate ClientCertificate {get;}
+   //		public string ApplicationPath {get;}
+   //		public HttpCookieCollection Cookies {get;}
+   //		public Stream Filter {get; set;}
+   //		public string MapPath(string virtualPath, string baseVirtualDir, bool allowCrossAppMapping);
+   //		public string MapPath(string virtualPath);
+   //		public int [] MapImageCoordinates(string imageFieldName);
+   //		public string FilePath {get;}
+   //		public Uri UrlReferrer 
+
+   [MonoTODO("Review security in all path access function")]
+   public class HttpRequest {
+      private string []	_arrAcceptTypes;
+      private string []	_arrUserLanguages;
+
+      private byte [] _arrRawContent;
+      private int	_iContentLength;
+
+      private string	_sContentType;
+      private string	_sHttpMethod;
+      private string	_sRawUrl;
+      private string	_sUserAgent;
+      private string	_sUserHostAddress;
+      private string	_sUserHostName;
+      private string	_sPath;
+      private string	_sPathInfo;
+      private string _sFilePath;
+      private string _sPathTranslated;
+      private string _sQueryStringRaw;
+      private string _sRequestType;
+      private string _sRequestRootVirtualDir;
+
+      private Encoding _oContentEncoding;
+
+      private Uri _oUriReferrer;
+      private Uri _oUrl;
+
+      private int	_iTotalBytes;
+
+      private HttpContext	_oContext;
+
+      private HttpWorkerRequest _WorkerRequest;
+      private HttpRequestStream	_oInputStream;
+
+      private HttpValueCollection _oServerVariables;
+      private HttpValueCollection _oHeaders;
+      private HttpValueCollection _oQueryString;
+      private HttpValueCollection _oFormData;
+      private HttpValueCollection _oParams;
+
+      public HttpRequest(string Filename, string Url, string Querystring) {
+         _iContentLength = -1;
+         _iTotalBytes = -1;
+
+         _WorkerRequest = null;
+         _sPathTranslated = Filename;
+         _sRequestType = "GET";
+         _sHttpMethod = "GET";
+         _oUrl = new Uri(Url);
+         _sPath = _oUrl.AbsolutePath;
+
+         _sQueryStringRaw = Querystring;
+         _oQueryString = new HttpValueCollection(Querystring, true, Encoding.Default);
+      }
+
+      internal HttpRequest(HttpWorkerRequest WorkRequest, HttpContext Context) {
+         _WorkerRequest = WorkRequest;
+         _oContext = Context;
+
+         _iContentLength = -1;
+         _iTotalBytes = -1;
+      }
+
+      static private string MakeServerVariableFromHeader(string header) {
+         return "HTTP_" + header.ToUpper().Replace("-", "_");
+      }
+
+      [MonoTODO("Need to support non-raw mode also..")]
+      private string GetAllHeaders(bool Raw) {
+         StringBuilder oData;
+
+         if (null == _WorkerRequest) {
+            return null;
+         }
+
+         oData = new StringBuilder(512);
+
+         string sHeaderValue;
+         string sHeaderName;
+         int iCount = 0;
+
+         // Add all know headers
+         for (; iCount != 40; iCount++) {
+            sHeaderValue = _WorkerRequest.GetKnownRequestHeader(iCount);
+            if (null != sHeaderValue && sHeaderValue.Length > 0) {
+               sHeaderName = _WorkerRequest.GetKnownRequestHeader(iCount);
+               if (null != sHeaderName && sHeaderName.Length > 0) {
+                  oData.Append(sHeaderName);
+                  oData.Append(": ");
+                  oData.Append(sHeaderValue);
+                  oData.Append("\r\n");
+               }
+            }
+         }
+
+         // Get all other headers
+         string [][] arrUnknownHeaders = _WorkerRequest.GetUnknownRequestHeaders();
+         if (null != arrUnknownHeaders) {
+            for (iCount = 0; iCount != arrUnknownHeaders.Length; iCount++) {
+               oData.Append(arrUnknownHeaders[iCount][0]);
+               oData.Append(": ");
+               oData.Append(arrUnknownHeaders[iCount][1]);
+               oData.Append("\r\n");
+            }
+         }
+
+         return oData.ToString();
+      }
+      
+      [MonoTODO("We need to handly 'dynamic' variables like AUTH_USER, that can be changed during runtime... special collection")]
+      private void ParseServerVariables() {
+         if (null == _WorkerRequest) {
+            return;
+         }
+
+         if (_oServerVariables == null) {
+            string sTmp;
+
+            _oServerVariables = new HttpValueCollection();
+				
+            _oServerVariables.Add("ALL_HTTP", GetAllHeaders(false));
+            _oServerVariables.Add("ALL_RAW", GetAllHeaders(true));
+
+            _oServerVariables.Add("APPL_MD_PATH", _WorkerRequest.GetServerVariable("APPL_MD_PATH"));
+            _oServerVariables.Add("AUTH_PASSWORD", _WorkerRequest.GetServerVariable("AUTH_PASSWORD"));
+            _oServerVariables.Add("CERT_COOKIE", _WorkerRequest.GetServerVariable("CERT_COOKIE"));
+            _oServerVariables.Add("CERT_FLAGS", _WorkerRequest.GetServerVariable("CERT_FLAGS"));
+            _oServerVariables.Add("CERT_ISSUER", _WorkerRequest.GetServerVariable("CERT_ISSUER"));
+            _oServerVariables.Add("CERT_KEYSIZE", _WorkerRequest.GetServerVariable("CERT_KEYSIZE"));
+            _oServerVariables.Add("CERT_SECRETKEYSIZE", _WorkerRequest.GetServerVariable("CERT_SECRETKEYSIZE"));
+            _oServerVariables.Add("CERT_SERIALNUMBER", _WorkerRequest.GetServerVariable("CERT_SERIALNUMBER"));
+            _oServerVariables.Add("CERT_SERVER_ISSUER", _WorkerRequest.GetServerVariable("CERT_SERVER_ISSUER"));
+            _oServerVariables.Add("CERT_SERVER_SUBJECT", _WorkerRequest.GetServerVariable("CERT_SERVER_SUBJECT"));
+            _oServerVariables.Add("CERT_SUBJECT", _WorkerRequest.GetServerVariable("CERT_SUBJECT"));
+
+            _oServerVariables.Add("GATEWAY_INTERFACE", _WorkerRequest.GetServerVariable("GATEWAY_INTERFACE"));
+            _oServerVariables.Add("HTTPS", _WorkerRequest.GetServerVariable("HTTPS"));
+            _oServerVariables.Add("HTTPS_KEYSIZE", _WorkerRequest.GetServerVariable("HTTPS_KEYSIZE"));
+            _oServerVariables.Add("HTTPS_SECRETKEYSIZE", _WorkerRequest.GetServerVariable("HTTPS_SECRETKEYSIZE"));
+
+            _oServerVariables.Add("CONTENT_TYPE", ContentType);
+            _oServerVariables.Add("HTTPS_SERVER_ISSUER", _WorkerRequest.GetServerVariable("HTTPS_SERVER_ISSUER"));
+            _oServerVariables.Add("HTTPS_SERVER_SUBJECT", _WorkerRequest.GetServerVariable("HTTPS_SERVER_SUBJECT"));
+            _oServerVariables.Add("INSTANCE_ID", _WorkerRequest.GetServerVariable("INSTANCE_ID"));
+            _oServerVariables.Add("INSTANCE_META_PATH", _WorkerRequest.GetServerVariable("INSTANCE_META_PATH"));
+            _oServerVariables.Add("LOCAL_ADDR", _WorkerRequest.GetLocalAddress());
+            _oServerVariables.Add("REMOTE_ADDR", UserHostAddress);
+            _oServerVariables.Add("REMOTE_HOST", UserHostName);
+            _oServerVariables.Add("REQUEST_METHOD", HttpMethod);
+            _oServerVariables.Add("SERVER_NAME", _WorkerRequest.GetServerName());
+            _oServerVariables.Add("SERVER_PORT", _WorkerRequest.GetLocalPort().ToString());
+            _oServerVariables.Add("SERVER_PROTOCOL", _WorkerRequest.GetHttpVersion());
+            _oServerVariables.Add("SERVER_SOFTWARE", _WorkerRequest.GetServerVariable("SERVER_SOFTWARE"));
+
+            if (_WorkerRequest.IsSecure()) {
+               _oServerVariables.Add("SERVER_PORT_SECURE", "1");
+            } else {
+               _oServerVariables.Add("SERVER_PORT_SECURE", "0");
+            }
+
+            sTmp = _WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength);
+            if (null != sTmp) {
+               _oServerVariables.Add("CONTENT_LENGTH", sTmp);
+            }
+
+            // TODO: Should be dynamic
+            if (null != _oContext.User && _oContext.User.Identity.IsAuthenticated) {
+               _oServerVariables.Add("AUTH_TYPE", _oContext.User.Identity.AuthenticationType);
+               _oServerVariables.Add("AUTH_USER", _oContext.User.Identity.Name);
+            } else {
+               _oServerVariables.Add("AUTH_TYPE", "");
+               _oServerVariables.Add("AUTH_USER", "");
+            }
+
+            _oServerVariables.Add("PATH_INFO", PathInfo);
+            _oServerVariables.Add("PATH_TRANSLATED", PhysicalPath);
+            _oServerVariables.Add("QUERY_STRING", QueryStringRaw);
+            _oServerVariables.Add("SCRIPT_NAME", FilePath);
+            // end dynamic
+            
+            _oServerVariables.MakeReadOnly();
+         }
+      }
+
+      [MonoTODO("Handle Multipart data also, content-encoding check")]
+      private void ParseFormData() {
+         if (_oFormData == null) {
+            byte [] arrData = GetRawContent();
+            _oFormData = new HttpValueCollection(ContentEncoding.GetString(arrData), true, ContentEncoding);
+         }
+      }
+
+      void Dispose() {
+			
+      }
+
+      [MonoTODO("Handle Multipart data, max content length?")]
+      private byte [] GetRawContent() {
+         if (null == _arrRawContent) {
+            if (null == _WorkerRequest) {
+               return null;
+            }
+
+            // TODO: Check max length?
+            _arrRawContent = _WorkerRequest.GetPreloadedEntityBody();
+            if (!_WorkerRequest.IsEntireEntityBodyIsPreloaded()) {
+               byte [] arrTemp;
+               byte [] arrBuffer;
+					
+               arrBuffer = new byte[16384];
+               int iLoaded = 16384;
+
+               while (iLoaded == arrBuffer.Length) {
+                  iLoaded = _WorkerRequest.ReadEntityBody(arrBuffer, arrBuffer.Length);
+						
+                  // Save data
+                  arrTemp = new byte[_arrRawContent.Length + iLoaded];
+						
+                  Array.Copy(_arrRawContent, 0, arrTemp, 0, _arrRawContent.Length);
+                  Array.Copy(arrBuffer, 0, arrTemp, _arrRawContent.Length, iLoaded);
+
+                  _arrRawContent = arrTemp;
+               }
+            }
+         }
+
+         return _arrRawContent;
+      }
+
+      public string [] AcceptTypes {
+         get {
+            if (null == _arrAcceptTypes && null != _WorkerRequest) {
+               _arrAcceptTypes = HttpHelper.ParseMultiValueHeader(_WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderAccept));
+            } 
+
+            return _arrAcceptTypes;
+				
+         }
+      }
+
+      public string ApplicationPath {
+         get {
+            if (null != _WorkerRequest) {
+               return _WorkerRequest.GetAppPath();
+            }
+
+            return null;
+         }
+      }
+
+      [MonoTODO()]
+      public HttpBrowserCapabilites Browser {
+         get {
+            throw new NotImplementedException();
+         }
+
+         set {
+            throw new NotImplementedException();
+         }
+      }
+
+      [MonoTODO()]
+      public HttpClientCertificate ClientCertificate {
+         get {
+            throw new NotImplementedException();
+         }
+      }
+
+      [MonoTODO("Get content encoding from Syste.Web.Configuration namespace")]
+      public Encoding ContentEncoding {
+         get {
+            if (_oContentEncoding == null) {
+               // TODO: Get from config what is the default encoding
+               // TODO: Should we get encoding from HttpHeaders? Just get charset from ContentType and the get encoding..
+               _oContentEncoding = Encoding.Default;
+            }
+
+            return _oContentEncoding;
+         }
+
+         set {
+            _oContentEncoding = value;
+         }
+      }
+
+      public int ContentLength {
+         get {
+            if (_iContentLength == -1 && null != _WorkerRequest) {
+               string sLength = _WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength);
+               if (sLength != null) {
+                  try {
+                     _iContentLength = Int32.Parse(sLength);
+                  }
+                  catch(Exception) {
+                  }
+               } 
+            }
+
+            if (_iContentLength < 0) {
+               _iContentLength = 0;
+            }
+
+            return _iContentLength;
+         }
+      }
+
+      public string ContentType {
+         get {
+            if (null == _sContentType) {
+               if (null != _WorkerRequest) {
+                  _sContentType = _WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentType);
+               }
+
+               if (null == _sContentType) {
+                  _sContentType = string.Empty;
+               }
+            }
+
+            return _sContentType;
+         }
+      }
+
+      [MonoTODO()]
+      public HttpCookieCollection Cookies {
+         get {
+            throw new NotImplementedException();
+         }
+      }
+
+      [MonoTODO()]
+      public string CurrentExecutionFilePath {
+         get {
+            throw new NotImplementedException();
+         }
+      }
+
+      public string FilePath {
+         get {
+            if (null == _sFilePath && null != _WorkerRequest) {
+               _sFilePath = _WorkerRequest.GetFilePath();
+            }
+
+            return _sFilePath;
+         }
+      }
+
+      [MonoTODO()]
+      public HttpFileCollection Files {
+         get {
+            throw new NotImplementedException();
+         }
+      }
+
+      [MonoTODO("Use stream filter in the request stream")]
+      public Stream Filter {
+         get {
+            throw new NotImplementedException();
+         }
+
+         set {
+            throw new NotImplementedException();
+         }
+      }
+
+
+      public NameValueCollection Form {
+         get {
+            ParseFormData();
+
+            return (NameValueCollection) _oFormData;
+         }
+      }
+
+      public NameValueCollection Headers {
+         get {
+            if (_oHeaders == null) {
+               _oHeaders = new HttpValueCollection();
+
+               if (null != _WorkerRequest) {
+                  string sHeaderValue;
+                  string sHeaderName;
+                  int iCount = 0;
+
+                  // Add all know headers
+                  for (; iCount != 40; iCount++) {
+                     sHeaderValue = _WorkerRequest.GetKnownRequestHeader(iCount);
+                     if (null != sHeaderValue && sHeaderValue.Length > 0) {
+                        sHeaderName = _WorkerRequest.GetKnownRequestHeader(iCount);
+                        if (null != sHeaderName && sHeaderName.Length > 0) {
+                           _oHeaders.Add(sHeaderName, sHeaderValue);
+                        }
+                     }
+                  }
+
+                  // Get all other headers
+                  string [][] arrUnknownHeaders = _WorkerRequest.GetUnknownRequestHeaders();
+                  if (null != arrUnknownHeaders) {
+                     for (iCount = 0; iCount != arrUnknownHeaders.Length; iCount++) {
+                        _oHeaders.Add(arrUnknownHeaders[iCount][0], arrUnknownHeaders[iCount][1]);
+                     }
+                  }
+               }
+
+               // Make headers read-only
+               _oHeaders.MakeReadOnly();
+            }
+
+            return (NameValueCollection) _oHeaders;
+         }
+      }
+
+      public string HttpMethod {
+         get {
+            if (null == _sHttpMethod) {
+               if (null != _WorkerRequest) {
+                  _sHttpMethod = _WorkerRequest.GetHttpVerbName().ToUpper();
+               }
+               
+               if (_sHttpMethod == null) {
+                  _sHttpMethod = "GET";
+               }
+            }
+
+            return _sHttpMethod;
+         }
+      }
+
+      public Stream InputStream {
+         get {
+            if (_oInputStream == null) {
+               byte [] arrInputData = GetRawContent();
+
+               if (null != arrInputData) {
+                  _oInputStream = new HttpRequestStream(arrInputData, 0, arrInputData.Length);
+               } else {
+                  _oInputStream = new HttpRequestStream(null, 0, 0);
+               }
+            }
+
+            return _oInputStream;
+         } 
+      }
+
+      public bool IsAuthenticated {
+         get {
+            if (_oContext != null && _oContext.User != null && _oContext.User.Identity != null) {
+                 return _oContext.User.Identity.IsAuthenticated;
+            }
+
+            return false;
+         }
+      }
+
+      public bool IsSecureConnection {
+         get {
+            if (null != _WorkerRequest) {
+               return _WorkerRequest.IsSecure();
+            }
+
+            return false;
+         }
+      }
+
+      [MonoTODO("Call item in querystring, form, cookie and servervariables")]
+      public string this [string sKey] {
+         get {
+            throw new NotImplementedException();
+         }
+      }
+
+      [MonoTODO("Add cookie collection to our Params collection via merge")]
+      public NameValueCollection Params {
+         get {
+            if (_oParams == null) {
+               _oParams = new HttpValueCollection();
+					
+               _oParams.Merge(QueryString);
+               _oParams.Merge(Form);
+               _oParams.Merge(ServerVariables);
+               // TODO: Cookie
+
+               _oParams.MakeReadOnly();
+            }
+
+            return (NameValueCollection) _oParams;
+         }
+      }
+		
+      public string Path {
+         get {
+            if (_sPath == null) {
+               if (null != _WorkerRequest) {
+                  _sPath = _WorkerRequest.GetUriPath();
+               }
+
+               if (_sPath == null) {
+                  _sPath = string.Empty;
+               }
+            }
+
+            return _sPath;
+         }
+      }
+		
+      public string PathInfo {
+         get {
+            if (_sPathInfo == null) {
+               if (null != _WorkerRequest) {
+                  _sPathInfo = _WorkerRequest.GetPathInfo();
+               }
+
+               if (_sPathInfo == null) {
+                  _sPathInfo = string.Empty;
+               }
+            }
+				
+            return _sPathInfo;
+         }
+      }
+
+      public string PhysicalApplicationPath {
+         get {
+            if (null != _WorkerRequest) {
+               return _WorkerRequest.GetAppPathTranslated();
+            }
+
+            return null;
+         }
+      }
+
+      public string PhysicalPath {
+         get {
+            if (null != _WorkerRequest) {
+               _sPathTranslated = _WorkerRequest.GetFilePathTranslated();
+               if (null == _sPathTranslated) {
+                  _sPathTranslated = _WorkerRequest.MapPath(FilePath);
+               }
+            }
+
+            return _sPathTranslated;
+         }
+      }
+
+      public NameValueCollection QueryString {
+         get {
+            if (_oQueryString == null) {
+               _oQueryString = new HttpValueCollection(QueryStringRaw, true, Encoding.UTF8);
+            }
+
+            return _oQueryString;
+         }
+      }
+
+      // Used to parse the querystring
+      internal string QueryStringRaw {
+         get {
+            if (_sQueryStringRaw == null && null != _WorkerRequest) {
+               byte [] arrQuerystringBytes = _WorkerRequest.GetQueryStringRawBytes();
+               if (null != arrQuerystringBytes && arrQuerystringBytes.Length > 0) {
+                  _sQueryStringRaw = ContentEncoding.GetString(arrQuerystringBytes);
+               } else {
+                  _sQueryStringRaw = _WorkerRequest.GetQueryString();   
+               }
+            }
+
+            if (_sQueryStringRaw == null) {
+               _sQueryStringRaw = string.Empty;
+            }
+
+            return _sQueryStringRaw;
+         }
+      }
+
+      public string RawUrl {
+         get {
+            if (null == _sRawUrl) {
+               if (null != _WorkerRequest) {
+                  _sRawUrl = _WorkerRequest.GetRawUrl();
+               } else {
+                  _sRawUrl = Path;
+                  if (QueryStringRaw != null && QueryStringRaw.Length > 0) {
+                     _sRawUrl = _sRawUrl + "?" + QueryStringRaw;
+                  }
+               }
+            }
+
+            return _sRawUrl;
+         }
+      }
+
+      public string RequestType {
+         get {
+            if (null == _sRequestType) {
+               return HttpMethod;
+            }
+         
+            return _sRequestType;
+         }
+      }
+		
+      
+      public NameValueCollection ServerVariables {
+         get {
+            ParseServerVariables();
+
+            return (NameValueCollection) _oServerVariables;
+         }
+      }      
+
+      public int TotalBytes {
+         get {
+            if (_iTotalBytes == -1) {
+               if (null != InputStream) {
+                  _iTotalBytes = (int) InputStream.Length;
+               } else {
+                  _iTotalBytes = 0;
+               }
+            }
+
+            return _iTotalBytes;
+         }
+      }
+
+      public Uri Url {
+         get {
+            if (null == _oUrl) {
+               _oUrl = new Uri(RawUrl);
+            }
+
+            return _oUrl;
+         }
+      }
+
+      public Uri UrlReferrer {
+         get {
+            if (null == _oUriReferrer && null != _WorkerRequest) {
+               string sReferrer = _WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderReferer);
+               if (null != sReferrer && sReferrer.Length > 0) {
+                  try {
+                     if (sReferrer.IndexOf("://") >= 0) {
+                        _oUriReferrer = new Uri(sReferrer);
+                     } else {
+                        _oUriReferrer = new Uri(this.Url, sReferrer);
+                     }
+                  }
+                  catch (Exception) {
+                  }
+               }
+            }
+
+            return _oUriReferrer;
+         }
+      }
+
+      public string UserAgent {
+         get {
+            if (_sUserAgent == null && _WorkerRequest != null) {
+               _sUserAgent = _WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderUserAgent);
+            }
+
+            if (_sUserAgent == null) {
+               _sUserAgent = string.Empty;
+            }
+
+            return _sUserAgent;
+         }
+      }
+
+      public string UserHostAddress {
+         get {
+            if (_sUserHostAddress == null && null != _WorkerRequest) {
+               _sUserHostAddress = _WorkerRequest.GetRemoteAddress();
+            }
+
+            if (_sUserHostAddress == null || _sUserHostAddress.Length == 0) {
+               _sUserHostAddress = "127.0.0.1";
+            }
+
+            return _sUserHostAddress;
+         }
+      }
+		
+      public string UserHostName {
+         get {
+            if (_sUserHostName == null && null != _WorkerRequest) {
+               _sUserHostName = _WorkerRequest.GetRemoteName();
+            }
+
+            if (_sUserHostName == null || _sUserHostName.Length == 0) {
+               _sUserHostName = UserHostAddress;
+            }
+
+            return _sUserHostName;
+         }
+      }
+		
+      public string [] UserLanguages {
+         get {
+            if (_arrUserLanguages == null && null != _WorkerRequest) {
+               _arrUserLanguages = HttpHelper.ParseMultiValueHeader(_WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderAcceptLanguage));
+            }
+
+            return _arrUserLanguages;
+         }
+      }
+
+      public byte [] BinaryRead(int count) {
+         int iSize = TotalBytes;
+         if (iSize == 0) {
+            throw new ArgumentException();
+         }
+
+         byte [] arrData = new byte[iSize];
+			
+         int iRetSize = InputStream.Read(arrData, 0, iSize);
+         if (iRetSize != iSize) {
+            byte [] tmpData = new byte[iRetSize];
+            if (iRetSize > 0) {
+               Array.Copy(arrData, 0, tmpData, 0, iRetSize);
+            }
+
+            arrData = tmpData;
+         }
+
+         return arrData;
+      }
+
+      public int [] MapImageCoordinates(string ImageFieldName) {
+         NameValueCollection oItems;
+
+         if (HttpMethod == "GET" || HttpMethod == "HEAD") {
+            oItems = QueryString;
+         } else if (HttpMethod == "POST") {
+            oItems = Form;
+         } else {
+            return null;
+         }
+
+         int [] arrRet = null;
+         try {
+            string sX = oItems.Get(ImageFieldName + ".x");
+            string sY = oItems.Get(ImageFieldName + ".y");
+
+            if (null != sX && null != sY) {
+               int [] arrTmp = new Int32[2];
+               arrRet[0] = Int32.Parse(sX);
+               arrRet[1] = Int32.Parse(sY);
+
+               arrRet = arrTmp;
+            }
+         }
+         catch (Exception) {
+         }
+
+         return arrRet;
+      }
+
+      public string MapPath(string VirtualPath) {
+         if (null == _sRequestRootVirtualDir) {
+            if (null == FilePath || FilePath.Length == 0) {
+               throw new ArgumentException("Filepath can't be empty");
+            }
+
+            if (FilePath[0] != '/') {
+               throw new ArgumentException("Filepath must be a root");
+            }
+
+            _sRequestRootVirtualDir = FilePath.Substring(0, FilePath.LastIndexOf('/'));
+            if (_sRequestRootVirtualDir.Length == 0) {
+               _sRequestRootVirtualDir = "/";
+            }
+         }
+
+         return MapPath(VirtualPath, _sRequestRootVirtualDir, true);
+      }
+
+      [MonoTODO("Build a path to send to MapPath in the workerrequest")]
+      public string MapPath(string virtualPath, string baseVirtualDir, bool allowCrossAppMapping) {
+         throw new NotImplementedException();
+      }
+
+      public void SaveAs(string filename, bool includeHeaders) {
+         FileStream oFile;
+         TextWriter oWriter;
+         HttpRequestStream oData;
+
+         oFile = new FileStream(filename, FileMode.CreateNew);
+         if (includeHeaders) {
+            oWriter = new StreamWriter(oFile);
+            oWriter.Write(HttpMethod + " " + Path);
+
+            if (QueryStringRaw != null && QueryStringRaw.Length > 0)
+               oWriter.Write("?" + QueryStringRaw);
+            if (_WorkerRequest != null) {
+               oWriter.Write(" " + _WorkerRequest.GetHttpVersion() + "\r\n");
+               oWriter.Write(GetAllHeaders(true));
+            } else {
+               oWriter.Write("\r\n");
+            }
+
+            oWriter.Write("\r\n");
+            oWriter.Flush();
+         }
+
+         oData = (HttpRequestStream) InputStream;
+
+         if (oData.DataLength > 0) {
+            oFile.Write(oData.Data, oData.DataOffset, oData.DataLength);
+         }
+
+         oFile.Flush();
+         oFile.Close();
+      }
+   }
+}

+ 142 - 0
mcs/class/System.Web/System.Web/HttpRequestStream.cs

@@ -0,0 +1,142 @@
+// 
+// System.Web.HttpRequestStream
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+using System.IO;
+
+namespace System.Web {
+   public class HttpRequestStream : Stream {
+      private byte []	_arrData;
+      private int			_iLength;
+      private int			_iOffset;
+      private int			_iPos;
+
+      internal HttpRequestStream(byte [] buffer, int offset, int length) {
+         _iPos = 0;
+         _iOffset = offset;
+         _iLength = length;
+
+         _arrData = buffer;
+      }
+		
+      private void Reset() {
+         _iPos = 0;
+         _iOffset = 0;
+         _iLength = 0;
+
+         _arrData = null;
+      }
+
+      public override void Flush() {
+      }
+
+      public override void Close() {
+         Reset();
+      }
+
+      public override int Read(byte [] buffer, int offset, int length) {
+         int iBytes = length;
+
+         if (_iPos + length > _arrData.Length) {
+            iBytes = (int) _arrData.Length - _iPos;
+         }
+
+         if (iBytes <= 0) {
+            return 0;
+         }
+
+         Buffer.BlockCopy(_arrData, _iPos, buffer, offset, iBytes);
+         _iPos += iBytes;
+
+         return iBytes;
+      }
+
+      public override long Seek(long offset, SeekOrigin origin) {
+         switch (origin) {
+            case SeekOrigin.Begin	:	if (offset > _arrData.Length) {
+                                          throw new ArgumentException();
+                                       }
+               _iPos = (int) offset;
+               break;
+											
+            case SeekOrigin.Current	:	if (((long) _iPos + offset > _arrData.Length) || (_iPos + (int) offset < 0)) {
+                                          throw new ArgumentException();
+                                       }
+               _iPos += Convert.ToInt32(offset);
+               break;
+
+            case SeekOrigin.End:		if (_arrData.Length - offset < 0) {
+                                       throw new ArgumentException();
+                                    }
+											
+               _iPos = Convert.ToInt32( _arrData.Length - offset);
+               break;
+         }
+
+         return (long) _iPos;										
+      }
+
+      public override void SetLength(long length) {
+         throw new NotSupportedException();
+      }
+
+      public override void Write(byte [] buffer, int offset, int length) {
+         throw new NotSupportedException();
+      }
+
+      public override bool CanRead {
+         get {
+            return true;
+         }
+      }
+
+      public override bool CanSeek {
+         get {
+            return true;
+         }
+      }
+
+      public override bool CanWrite {
+         get {
+            return false;
+         }
+      }
+
+      public byte [] Data {
+         get {
+            return _arrData;
+         }
+      }
+
+      public int DataLength {
+         get {
+            return _iLength;
+         }
+      }
+
+      public int DataOffset {
+         get {
+            return _iOffset;
+         }
+      }
+
+      public override long Length {
+         get {
+            return (long) _arrData.Length;
+         }
+      }
+
+      public override long Position {
+         get {
+            return (long) _iPos;
+         }
+
+         set {
+            Seek(value, SeekOrigin.Begin);
+         }
+      }
+   }
+}

+ 582 - 0
mcs/class/System.Web/System.Web/HttpResponse.cs

@@ -0,0 +1,582 @@
+// 
+// System.Web.HttpResponse
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+using System.Globalization;
+
+namespace System.Web {
+   public class HttpResponse {
+      // Chunked encoding static helpers
+      private static byte [] s_arrChunkSuffix = { 10, 13 };
+      private static byte [] s_arrChunkEnd = { 10 , 13 };
+      private static string s_sChunkedPrefix = "\r\n";
+
+      private ArrayList	_Headers;
+		
+      private bool _bClientDisconnected;
+      private bool _bSuppressHeaders;
+      private bool _bSuppressContent;
+      private bool _bChunked;
+      private bool _bEnded;
+      private bool _bBuffering;
+      private bool _bHeadersSent;
+      private bool _bFlushing;
+      private long _lContentLength;
+      private int _iStatusCode;
+
+      private string	_sContentType;
+      private string	_sCacheControl;
+      private string	_sTransferEncoding;
+      private string	_sCharset;
+      private string	_sStatusDescription;
+
+      private HttpCachePolicy _CachePolicy;
+
+      private Encoding _ContentEncoding;
+		
+      private HttpContext _Context;
+      private HttpWriter _Writer;
+      private TextWriter _TextWriter;
+
+      private HttpWorkerRequest _WorkerRequest;
+
+      public HttpResponse(HttpWorkerRequest WorkerRequest, HttpContext Context) {
+         _Context = Context;
+         _WorkerRequest = WorkerRequest;
+
+         _bBuffering = true;
+         _bFlushing = false;
+         _bHeadersSent = false;
+
+         _Headers = new ArrayList();
+
+         _sContentType = "text/html";
+
+         _iStatusCode = 200;
+         _sCharset = null;
+         _sCacheControl = null;
+
+         _lContentLength = 0;
+         _bSuppressContent = false;
+         _bSuppressHeaders = false;
+         _bClientDisconnected = false;
+
+         _bChunked = false;
+
+         _Writer = new HttpWriter(this);
+         _TextWriter = _Writer;
+      }
+
+      internal System.Text.Encoder ContentEncoder {
+         get {
+            return ContentEncoding.GetEncoder();
+         }
+      }
+
+      internal void FinalFlush() {
+         Flush(true);
+      }
+
+      [MonoTODO("We need to add cache headers also")]
+      private ArrayList GenerateHeaders() {
+         ArrayList oHeaders = new ArrayList(_Headers.ToArray());
+
+         // save culture info, we need us info here
+         CultureInfo oSavedInfo = System.Threading.Thread.CurrentThread.CurrentCulture;
+         System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo(0x0409);
+
+         oHeaders.Add(new HttpResponseHeader("Date", DateTime.Now.ToUniversalTime().ToString("ddd, d MMM yyyy HH:mm:ss") + " GMT"));
+
+         System.Threading.Thread.CurrentThread.CurrentCulture = oSavedInfo;
+
+         if (_lContentLength > 0) {
+            oHeaders.Add(new HttpResponseHeader(HttpWorkerRequest.HeaderContentLength, _lContentLength.ToString()));
+         }
+
+         if (_sContentType != null) {
+            if (_sContentType.IndexOf("charset=") == -1) {
+               if (Charset.Length == 0) {
+                  Charset = ContentEncoding.HeaderName;
+               }
+
+               // Time to build our string
+               if (Charset.Length > 0) {
+                  _sContentType += "; charset=" + Charset;
+               }
+            }
+
+            oHeaders.Add(new HttpResponseHeader(HttpWorkerRequest.HeaderContentType, _sContentType));
+         }
+
+         if (_sCacheControl != null) {
+            oHeaders.Add(new HttpResponseHeader(HttpWorkerRequest.HeaderPragma, _sCacheControl));
+         }
+
+         if (_sTransferEncoding != null) {
+            oHeaders.Add(new HttpResponseHeader(HttpWorkerRequest.HeaderTransferEncoding, _sTransferEncoding));
+         }
+
+         return oHeaders;
+      }
+
+      private void SendHeaders() {
+         _WorkerRequest.SendStatus(StatusCode, StatusDescription);
+			
+         ArrayList oHeaders = GenerateHeaders();
+         foreach (object oHeader in oHeaders) {
+            ((HttpResponseHeader) oHeader).SendContent(_WorkerRequest);
+         }
+			
+         _bHeadersSent = true;
+      }
+
+      public bool Buffer {
+         get {
+            return BufferOutput;
+         }
+			
+         set {
+            BufferOutput = value;
+         }
+      }
+
+      public bool BufferOutput {
+         get {
+            return _bBuffering;
+         }
+			
+         set {
+            if (_Writer != null) {
+               _Writer.Update();
+            }
+
+            _bBuffering = value;
+         }
+      }
+
+      public HttpCachePolicy Cache {
+         get {
+            if (null == _CachePolicy) {
+               _CachePolicy = new HttpCachePolicy();
+            }
+
+            return _CachePolicy;
+         }
+      }
+
+      [MonoTODO("Set status in the cache policy")]
+      public string CacheControl {
+         get {
+            return _sCacheControl;
+         }
+
+         set {
+            if (_bHeadersSent) {
+               throw new System.Web.HttpException("Headers has been sent to the client");
+            }
+
+            _sCacheControl = value;
+         }
+      }
+
+      public string Charset {
+         get {	
+            if (null == _sCharset) {
+               _sCharset = ContentEncoding.WebName;
+            }
+
+            return _sCharset;
+         }
+         set {
+            if (_bHeadersSent) {
+               throw new System.Web.HttpException("Headers has been sent to the client");
+            }
+
+            _sCharset = value;
+         }
+      }
+
+      public Encoding ContentEncoding {
+         get {
+            if (_ContentEncoding == null) {
+               _ContentEncoding = Encoding.UTF8;
+            }
+
+            return _ContentEncoding;
+         }
+
+         set {
+            if (value == null) {
+               throw new ArgumentException("Can't set a null as encoding");
+            }
+
+            _ContentEncoding = value;
+
+            if (_Writer != null) {
+               _Writer.Update();
+            }
+         }
+      }
+
+      public string ContentType {
+         get {
+            return _sContentType;
+         }
+
+         set {
+            if (_bHeadersSent) {
+               throw new System.Web.HttpException("Headers has been sent to the client");
+            }
+
+            _sContentType = value;
+         }
+      }
+
+      [MonoTODO("Set status in the cache policy")]
+      public HttpCookieCollection Cookies {
+         get {
+            throw new NotImplementedException();
+         }
+      }
+
+      [MonoTODO("Set expires in the cache policy")]
+      public int Expires {
+         get {
+            throw new NotImplementedException();
+         }
+
+         set {
+            throw new NotImplementedException();
+         }
+      }
+
+      [MonoTODO("Set expires in the cache policy")]
+      public int ExpiresAbsolut {
+         get {
+            throw new NotImplementedException();
+         }
+
+         set {
+            throw new NotImplementedException();
+         }
+      }
+      
+      public TextWriter Output {
+         get {
+            return _TextWriter;
+         }
+      }
+
+      public Stream OutputStream {
+         get {
+            if (_Writer == null) {
+               throw new System.Web.HttpException("a Output stream not available when running with custom text writer");
+            }
+
+            return _Writer.OutputStream;
+         }
+      }
+
+      public string StatusDescription {
+         get {
+            if (null == _sStatusDescription) {
+               _sStatusDescription = HttpWorkerRequest.GetStatusDescription(_iStatusCode);
+            } 
+               
+            return _sStatusDescription;
+         }
+
+         set {
+            if (_bHeadersSent) {
+               throw new System.Web.HttpException("Headers has been sent to the client");
+            }
+
+            _sStatusDescription = value;
+         }
+      }
+	
+      public int StatusCode {
+         get {
+            return _iStatusCode;
+         }
+         set {
+            if (_bHeadersSent) {
+               throw new System.Web.HttpException("Headers has been sent to the client");
+            }
+
+            _sStatusDescription = null;
+            _iStatusCode = value;
+         }
+      }
+
+      public bool SuppressContent {
+         get {
+            return _bSuppressContent;
+         }
+			
+         set {
+            if (_bHeadersSent) {
+               throw new System.Web.HttpException("Headers has been sent to the client");
+            }
+
+            _bSuppressContent = true;
+         }
+      }
+
+      public HttpRequest Request {
+         get {
+            return _Context.Request;
+         }
+      }
+
+      public void AppendHeader(int iIndex, string value) {
+         if (_bHeadersSent) {
+            throw new System.Web.HttpException("Headers has been sent to the client");
+         }
+         switch (iIndex) {
+            case HttpWorkerRequest.HeaderContentLength :	
+               _lContentLength = Int64.Parse(value);
+               break;
+            case HttpWorkerRequest.HeaderContentEncoding :	
+               _sContentType = value;
+               break;
+            case HttpWorkerRequest.HeaderTransferEncoding :	
+               _sTransferEncoding = value;
+               if (value.Equals("chunked")) {
+                  _bChunked = true;
+               } else {
+                  _bChunked = false;
+               }
+               break;
+
+            case HttpWorkerRequest.HeaderPragma	:	
+               _sCacheControl = value;
+               break;
+
+            default	:	
+               _Headers.Add(new HttpResponseHeader(iIndex, value));
+               break;
+         }
+      
+
+      }
+
+      public void AppendHeader(string name, string value) {
+         if (_bHeadersSent) {
+            throw new System.Web.HttpException("Headers has been sent to the client");
+         }
+	
+         switch (name.ToLower()) {
+            case "content-length"		:	_lContentLength = Int64.Parse(value);
+               break;
+            case "content-type"			:	_sContentType = value;
+               break;
+            case "transfer-encoding"	:	_sTransferEncoding = value;
+               if (value.Equals("chunked")) {
+                  _bChunked = true;
+               } else {
+                  _bChunked = false;
+               }
+
+               break;
+            case "pragma"				:	_sCacheControl = value;
+               break;
+
+            default						:	_Headers.Add(new HttpResponseHeader(name, value));
+               break;
+         }
+      }
+	
+      public void BinaryWrite(byte [] buffer) {
+         OutputStream.Write(buffer, 0, buffer.Length);
+      }
+
+      public void Clear() {
+         if (_Writer != null) {
+            _Writer.Clear();
+         }
+      }
+
+      public void ClearContent() {
+         Clear();
+      }
+
+      public void ClearHeaders() {
+         if (_bHeadersSent) {
+            throw new System.Web.HttpException("Headers has been sent to the client");
+         }
+
+         _sContentType = "text/html";
+
+         _iStatusCode = 200;
+         _sCharset = null;
+         _Headers = new ArrayList();
+         _sCacheControl = null;
+         _sTransferEncoding = null;
+
+         _lContentLength = 0;
+         _bSuppressContent = false;
+         _bSuppressHeaders = false;
+         _bClientDisconnected = false;
+      }
+
+      public void Close() {
+         _bClientDisconnected = false;
+
+         _WorkerRequest.CloseConnection();
+
+         _bClientDisconnected = true;
+      }
+
+      internal void Dispose() {
+         if (_Writer != null) {
+            _Writer.Dispose();
+            _Writer = null;
+         }
+      }
+
+      [MonoTODO("Handle callbacks into before done with session, needs to have a non ended flush here")]
+      internal void FlushAtEndOfRequest() 
+      {
+         Flush(true);
+      }
+
+      [MonoTODO("Check timeout and if we can cancel the thread...")]
+      public void End() {
+         if (!_bEnded) {
+            Flush();
+            _WorkerRequest.CloseConnection();
+
+            _bEnded = true;
+         }
+      }
+
+      public void Flush() {
+         Flush(false);
+      }
+
+      private void Flush(bool bFinish) {
+         if (_bFlushing) {
+            return;
+         }
+
+         _bFlushing = true;
+
+         if (_Writer != null) {
+            _Writer.FlushBuffers();
+         } else {
+            _TextWriter.Flush();
+         }
+
+         try {
+            if (!_bHeadersSent) {
+               if (!_bSuppressHeaders && !_bClientDisconnected) {
+                  if (_Writer != null && BufferOutput) {
+                     _lContentLength = _Writer.BufferSize;
+                  } 
+                  else {
+                     _lContentLength = 0;
+                  }
+		
+                  if (_lContentLength == 0 && _iStatusCode == 200 && _sTransferEncoding == null) {
+                     // Check we are going todo chunked encoding
+                     string sProto = _Context.Request.ServerVariables["SERVER_PROTOCOL"];
+                     if (sProto != null && sProto == "HTTP/1.1") {
+                        AppendHeader(HttpWorkerRequest.HeaderTransferEncoding, "chunked");
+                     }  
+                     else {
+                        // Just in case, the old browsers sends a HTTP/1.0 request with Connection: Keep-Alive
+                        AppendHeader(HttpWorkerRequest.HeaderConnection, "Close");
+                     }
+                  } 
+
+                  SendHeaders();
+               }					
+            }	
+            if ((!_bSuppressContent && Request.HttpMethod.Equals("HEAD")) || _Writer == null) {
+               _bSuppressContent = true;
+            }
+
+            if (!_bSuppressContent) {
+               _bClientDisconnected = false;
+               if (_bChunked) {
+                  Encoding oASCII = Encoding.ASCII;
+
+                  byte [] arrPrefix = oASCII.GetBytes(Convert.ToString(_Writer.BufferSize, 16) + s_sChunkedPrefix);
+                  _WorkerRequest.SendResponseFromMemory(arrPrefix, arrPrefix.Length);
+
+                  _Writer.SendContent(_WorkerRequest);
+
+                  _WorkerRequest.SendResponseFromMemory(s_arrChunkSuffix, s_arrChunkSuffix.Length);
+                  if (bFinish) {
+                     _WorkerRequest.SendResponseFromMemory(s_arrChunkEnd, s_arrChunkEnd.Length);
+                  }
+               } 
+               else {
+                  _Writer.SendContent(_WorkerRequest);
+               }
+
+               _WorkerRequest.FlushResponse(bFinish);	
+
+               if (!bFinish) {
+                  _Writer.Clear();
+               }
+            }
+         }
+         finally {
+            _bFlushing = false;
+         }
+      }
+
+      public void Pics(string value) {
+         AppendHeader("PICS-Label", value);
+      }
+
+
+      public void Redirect(string url) {
+         Redirect(url, true);
+      }
+
+      public void Redirect(string url, bool endResponse) {
+         if (_bHeadersSent) {
+            throw new System.Web.HttpException("Headers has been sent to the client");
+         }
+
+         Clear();
+
+         StatusCode = 302;
+         AppendHeader(HttpWorkerRequest.HeaderLocation, url);
+
+         // Text for browsers that can't handle location header
+         Write("<html><head><title>Object moved</title></head><body>\r\n");
+         Write("<h2>Object moved to <a href='" + url + "'>here</a></h2>\r\n");
+         Write("</body><html>\r\n");
+
+         if (endResponse) {
+            End();
+         }
+      }
+
+      public void Write(char ch) {
+         _TextWriter.Write(ch);
+      }
+
+      public void Write(object obj) {
+         _TextWriter.Write(obj);
+      }
+
+      public void Write(string str) {
+         _TextWriter.Write(str);
+      }
+
+      public void Write(char [] buffer, int index, int count) {
+         _TextWriter.Write(buffer, index, count);
+      }
+   }
+}

+ 53 - 0
mcs/class/System.Web/System.Web/HttpResponseHeader.cs

@@ -0,0 +1,53 @@
+// 
+// System.Web.HttpResponseHeader
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+
+namespace System.Web {
+   public class HttpResponseHeader {
+      private string _sHeader;
+      private string _sValue;
+      private int _iKnowHeaderId;
+
+      public HttpResponseHeader(int KnowHeaderId, string value) {
+         _iKnowHeaderId = KnowHeaderId;
+         _sValue = value;
+      }
+
+      public HttpResponseHeader(string header, string value) {
+         _sHeader = header;
+         _sValue = value;
+      }
+
+      public string Name {
+         get {
+            if (null == _sHeader) {
+               return HttpWorkerRequest.GetKnownResponseHeaderName(_iKnowHeaderId);
+            }
+
+            return _sHeader;
+         }
+      }
+
+      public string Value {
+         get {
+            return _sValue;
+         }
+      }
+
+      override public string ToString() {
+         return Name + ": " + Value;
+      }
+
+      internal void SendContent(HttpWorkerRequest WorkerRequest) {
+         if (null != _sHeader) {
+            WorkerRequest.SendUnknownResponseHeader(_sHeader, _sValue);
+         } else {
+            WorkerRequest.SendKnownResponseHeader(_iKnowHeaderId, _sValue);
+         }
+      }
+   }
+}

+ 87 - 0
mcs/class/System.Web/System.Web/HttpResponseStream.cs

@@ -0,0 +1,87 @@
+// 
+// System.Web.HttpResponseStream
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+using System.IO;
+
+namespace System.Web {
+   /// <summary>
+   /// Simple wrapper around HttpWriter to support the Stream interface
+   /// </summary>
+   public class HttpResponseStream : Stream {
+      private HttpWriter _Writer;
+	   
+      internal HttpResponseStream(HttpWriter Writer) {
+         _Writer = Writer;
+      }
+		
+      public override void Flush() {
+         _Writer.Flush();
+      }
+
+      public override void Close() {
+         _Writer.Close();
+      }
+
+      public override int Read(byte [] buffer, int offset, int length) {
+         throw new NotSupportedException();
+      }
+
+      public override long Seek(long offset, SeekOrigin origin) {
+         throw new NotSupportedException();
+      }
+
+      public override void SetLength(long length) {
+         throw new NotSupportedException();
+      }
+
+      public override void Write(byte [] buffer, int offset, int length) {
+         if (offset < 0) {
+            throw new ArgumentOutOfRangeException("offset");
+         }
+
+         if (length <= 0) {
+            throw new ArgumentOutOfRangeException("length");
+         }
+		   
+         _Writer.WriteBytes(buffer, offset, length);
+      }
+
+      public override bool CanRead {
+         get {
+            return false;
+         }
+      }
+
+      public override bool CanSeek {
+         get {
+            return false;
+         }
+      }
+
+      public override bool CanWrite {
+         get {
+            return true;
+         }
+      }
+
+      public override long Length {
+         get {
+            throw new NotSupportedException();
+         }
+      }
+
+      public override long Position {
+         get {
+            throw new NotSupportedException();
+         }
+
+         set {
+            throw new NotSupportedException();
+         }
+      }
+   }
+}

+ 48 - 0
mcs/class/System.Web/System.Web/HttpResponseStreamProxy.cs

@@ -0,0 +1,48 @@
+// 
+// System.Web.HttpResponseStreamProxy
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+using System.IO;
+
+namespace System.Web {
+   /// <summary>
+   /// Used to detect if there is a valid filter proxy.
+   /// </summary>
+   public class HttpResponseStreamProxy : HttpResponseStream {
+      bool _FilteringActive;
+	   
+      internal HttpResponseStreamProxy(HttpWriter Writer) : base(Writer) {
+         _FilteringActive = false;
+      }
+		
+      internal void CheckFilteringState() {
+         if (_FilteringActive) {
+            throw new HttpException("Invalid response filter state");
+         }
+      }
+		
+      internal bool Active {
+         get {
+            return _FilteringActive;
+         }
+         set {
+            _FilteringActive = value;
+         }
+      }
+		
+      public override void Flush() {
+      }
+
+      public override void Close() {
+      }
+		
+      public override void Write(byte [] buffer, int offset, int length) {
+         CheckFilteringState();
+         
+         Write(buffer, offset, length);
+      }
+   }
+}

+ 18 - 0
mcs/class/System.Web/System.Web/HttpSessionState.cs

@@ -0,0 +1,18 @@
+// 
+// System.Web.HttpSessionState
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+
+namespace System.Web {
+   [MonoTODO()]
+   public class HttpSessionState {
+      public HttpSessionState() {
+         //
+         // TODO: Add constructor logic here
+         //
+      }
+   }
+}

+ 179 - 0
mcs/class/System.Web/System.Web/HttpUtility.cs

@@ -0,0 +1,179 @@
+// 
+// System.Web.HttpUtility
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//   Wictor Wilén (decode/encode functions) ([email protected])
+//
+using System;
+using System.Text;
+using System.IO;
+
+namespace System.Web {
+   [MonoTODO()]
+   public class HttpUtility {
+      // private stuff
+      private const string _hex = "0123456789ABCDEF";
+      private const string _chars = "<>;:.?=&@*+%/\\";
+
+      public HttpUtility() {
+      }
+
+      public static void HtmlAttributeEncode(string s, TextWriter output) {
+         output.Write(HtmlAttributeEncode(s));
+      }
+
+      public static string HtmlAttributeEncode(string s) {
+         if (null == s) {
+            return s;
+         }
+
+         StringBuilder oStr = new StringBuilder(128);
+
+         for (int i = 0; i != s.Length; i++) {
+            if (s[i] == '&') {
+               oStr.Append("&amp;");
+            } else 
+            if (s[i] == '"') {
+               oStr.Append("&quot;");
+            } else {
+               oStr.Append(s[i]);
+            }
+         }
+
+         return oStr.ToString();
+      }
+
+      public static string UrlDecode(string str) {
+         return UrlDecode(str, Encoding.UTF8);
+      }
+
+      [MonoTODO("Use Encoding")]
+      public static string UrlDecode(string s, Encoding Enc) {
+         if (null == s) {
+            return null;
+         }
+
+         string dest = "";
+         long len = s.Length;
+         string tmp = "";
+
+
+         for(int i = 0; i < len; i++) {
+            if(s[i] == '%') {
+               tmp = s[i+1].ToString ();
+               tmp += s[i+2];
+               dest += char.Parse(tmp);
+            } 
+            else if( s[i] == '+') {
+               dest += " ";
+            }
+            else
+               dest += s[i];
+
+         }
+         return dest;
+      }
+
+      public static string UrlEncode(string str) {
+         return UrlDecode(str, Encoding.UTF8);
+      }
+
+      [MonoTODO("Use encoding")]
+      public static string UrlEncode(string s, Encoding Enc) {
+         if (null == s) {
+            return null;
+         }
+
+         string dest = "";
+         long len = s.Length;
+         int h1, h2;
+
+         for(int i = 0; i < len; i++) {
+            if(s[i] == ' ') // space character is replaced with '+'
+               dest += "+";
+            else if ( _chars.IndexOf(s[i]) >= 0 ) {
+               h1 = (int)s[i] % 16;
+               h2 = (int)s[i] / 16;
+               dest += "%";
+               dest += _hex[h1].ToString();
+               dest += _hex[h2].ToString();
+            }
+            else
+               dest += s[i].ToString();
+
+         }
+         return dest;
+      }
+   
+      /// <summary>
+      /// Decodes an HTML-encoded string and returns the decoded string.
+      /// </summary>
+      /// <param name="s">The HTML string to decode. </param>
+      /// <returns>The decoded text.</returns>
+      [MonoTODO()]
+      public static string HtmlDecode(string s) {
+         throw new System.NotImplementedException();
+      }
+
+      /// <summary>
+      /// Decodes an HTML-encoded string and sends the resulting output to a TextWriter output stream.
+      /// </summary>
+      /// <param name="s">The HTML string to decode</param>
+      /// <param name="output">The TextWriter output stream containing the decoded string. </param>
+      [MonoTODO()]
+      public static void HtmlDecode(string s, TextWriter output) {
+         throw new System.NotImplementedException();
+      }
+
+      /// <summary>
+      /// HTML-encodes a string and returns the encoded string.
+      /// </summary>
+      /// <param name="s">The text string to encode. </param>
+      /// <returns>The HTML-encoded text.</returns>
+      public static string HtmlEncode(string s) {
+         string dest = "";
+         long len = s.Length;
+         int v;
+
+
+
+         for(int i = 0; i < len; i++) {
+            switch(s[i]) {
+               case '>':
+                  dest += "&gt;";
+                  break;
+               case '<':
+                  dest += "&lt;";
+                  break;
+               case '"':
+                  dest += "&quot;";
+                  break;
+               case '&':
+                  dest += "&amp;";
+                  break;
+               default:
+                  if(s[i] >= 128) {
+                     dest += "&H";
+                     v = (int) s[i];
+                     dest += v.ToString() ;
+							
+                  }
+                  else
+                     dest += s[i];
+                  break;
+            }
+         }
+         return dest;
+      }
+
+      /// <summary>
+      /// HTML-encodes a string and sends the resulting output to a TextWriter output stream.
+      /// </summary>
+      /// <param name="s">The string to encode. </param>
+      /// <param name="output">The TextWriter output stream containing the encoded string. </param>
+      public static void HtmlEncode(	string s, TextWriter output) {
+         output.Write(HtmlEncode(s));
+      }
+   }
+}

+ 134 - 0
mcs/class/System.Web/System.Web/HttpValueCollection.cs

@@ -0,0 +1,134 @@
+// 
+// System.Web.HttpValueCollection
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+using System.Collections.Specialized;
+using System.Text;
+
+namespace System.Web {
+
+   [Serializable]
+   public class HttpValueCollection : NameValueCollection {
+      private bool	_bHeaders;
+
+      internal HttpValueCollection() {
+         _bHeaders = false;
+      }
+
+      internal HttpValueCollection(string sData) {
+         FillFromQueryString(sData, Encoding.UTF8);
+         IsReadOnly = true;
+      }
+
+      internal HttpValueCollection(string sData, bool ReadOnly, Encoding encoding) {
+         FillFromQueryString(sData, encoding);
+         IsReadOnly = ReadOnly;
+      }
+
+      // string = header1: value1\r\nheader2: value2
+      internal void FillFromHeaders(string sHeaders, Encoding encoding) {
+         _bHeaders = true;
+         char [] arrSplitValue = new char [] {':'};
+         string sKey, sValue;
+
+         sKey = "";
+         sValue = "";
+
+         string [] arrValues = sHeaders.Split(new char [] {'\r', '\n'});
+         foreach (string sLine in arrValues) {
+            string [] arrKeyValue = sLine.Split(arrSplitValue);
+            if (arrKeyValue.Length == 1 && arrKeyValue[0].Length == 0) {
+               // Empty \r or \n is ignored
+               continue;
+            }
+
+            if (arrKeyValue[0] != sKey && sKey.Length > 0) {
+               Add(System.Web.HttpUtility.UrlDecode(sKey, encoding), System.Web.HttpUtility.UrlDecode(sValue, encoding));
+            }
+
+            if (arrKeyValue.Length == 1) {
+               sValue += "\r\n" + arrKeyValue[0].Trim();
+               continue;
+            } 
+            else if (arrKeyValue.Length == 2) {
+               if (arrKeyValue[0].Length == 0) {
+                  sValue += arrKeyValue[1].Trim();
+                  continue;
+               }
+
+               sKey = arrKeyValue[0].Trim();
+               sValue = arrKeyValue[1].Trim();
+            } 
+         }
+			
+         if (sKey.Length > 0) {
+            Add(System.Web.HttpUtility.UrlDecode(sKey, encoding), System.Web.HttpUtility.UrlDecode(sValue, encoding));
+         }
+      }
+
+      internal void FillFromHeaders(string sData) {
+         FillFromHeaders(sData, Encoding.UTF8);
+      }
+
+      // String = test=aaa&kalle=nisse
+      internal void FillFromQueryString(string sData, Encoding encoding) {
+         _bHeaders = false;
+
+         char [] arrSplitValue = new char [] {'='};
+
+         string [] arrValues = sData.Split(new char [] {'&'});
+         foreach (string sValue in arrValues) {
+            string [] arrKeyValue = sValue.Split(arrSplitValue);
+            if (arrKeyValue.Length == 1) {
+               // Add key only
+               Add(System.Web.HttpUtility.UrlDecode(arrKeyValue[0].Trim(), encoding), string.Empty);
+            } 
+            else if (arrKeyValue.Length == 2) {
+               Add(System.Web.HttpUtility.UrlDecode(arrKeyValue[0].Trim(), encoding),System.Web.HttpUtility.UrlDecode(arrKeyValue[1].Trim(), encoding));
+            } 
+            else {
+               throw new InvalidOperationException("Data is malformed");
+            }
+         }		
+      }
+
+      internal void FillFromQueryString(string sData) {
+         FillFromQueryString(sData, Encoding.UTF8);
+      }
+
+      internal void MakeReadOnly() {
+         IsReadOnly = true;
+      }
+		
+      internal void MakeReadWrite() {
+         IsReadOnly = false;
+      }
+
+      internal void Merge(NameValueCollection oData) {
+         foreach (string sKey in oData) {
+            Add(sKey, oData[sKey]);
+         }
+      }
+
+      internal void Reset() {
+         Clear();
+      }
+
+      [MonoTODO("string ToString(bool UrlEncode)")]
+      internal string ToString(bool UrlEncode) {
+         if (_bHeaders) {
+         }
+
+         // TODO: Should return a correctly formated string (different depending on header flag)
+         throw new NotImplementedException();
+      }
+
+      new public string ToString() {
+         return ToString(false);
+      }
+   }
+
+}

+ 0 - 17
mcs/class/System.Web/System.Web/HttpWorkerRequest.EndOfSendNotification.cs

@@ -1,17 +0,0 @@
-//
-// System.Web.HttpWorkerRequest.EndOfSendNotification.cs
-//
-// Author:
-//   Bob Smith <[email protected]>
-//
-// (C) Bob Smith
-//
-
-namespace System.Web
-{
-	public class HttpWorkerRequest {
-        	public delegate void EndOfSendNotification(
-                                HttpWorkerRequest wr,
-                                object extraData);
-	}
-}

+ 230 - 0
mcs/class/System.Web/System.Web/HttpWriter.cs

@@ -0,0 +1,230 @@
+// 
+// System.Web.HttpWriter
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+using System.IO;
+using System.Text;
+
+namespace System.Web {
+   public class HttpWriter : TextWriter {
+      private HttpResponse	_Response;
+		
+      private HttpResponseStream _ResponseStream;
+		
+      private MemoryStream	_OutputStream;
+      private StreamWriter	_OutputHelper;
+      private Encoder		_Encoder;
+      private Encoding		_Encoding;	
+
+      private Stream       _OutputFilter;
+      private HttpResponseStreamProxy  _OutputProxy;
+
+      internal HttpWriter(HttpResponse Response) {
+         _Response = Response;
+
+         _OutputStream = new MemoryStream(32768);
+         _OutputHelper = new StreamWriter(_OutputStream, Encoding.Unicode);
+         _ResponseStream = new HttpResponseStream(this);
+
+         Update();
+      }  
+
+      internal void Dispose() {
+         _OutputHelper.Close();
+         _OutputStream.Close();
+			
+         _OutputFilter.Close();
+      }
+		
+      internal Stream GetActiveFilter() {
+         if (null == _OutputFilter) {
+            if (null == _OutputProxy) {
+               // Create a filter proxy to allow us to know if we have a valid filter
+               _OutputProxy = new HttpResponseStreamProxy(this);
+            }
+            		      
+            return _OutputProxy;
+         }
+		   
+         return _OutputFilter;
+      }
+		
+      internal void ActivateFilter(Stream OutputFilter) {
+         if (null == _OutputProxy) {
+            throw new HttpException("Invalid filter usage");
+         }
+		   
+         _OutputFilter = OutputFilter;
+      }
+		
+      internal void FilterData(bool CloseStream) {
+         // Check if we have any filter at all
+         if (null == _OutputFilter) {
+            return;
+         }
+		   
+         FlushBuffers();
+		     
+         // Save our current data
+         byte [] arrData = _OutputStream.ToArray();
+		   
+         // Remove our internal data
+         Clear();   	     
+         
+         // If we have a filter then we have a proxy
+         _OutputProxy.Active = true;
+         
+         try {
+            // Call the filter (it does a callback into our HttpWriter again)
+            _OutputFilter.Write(arrData, 0, arrData.Length);
+		      
+            if (CloseStream) {
+               _OutputFilter.Close();
+            }
+         }
+         finally {
+            _OutputProxy.Active = false;
+         }
+      }
+
+      internal void Clear() {
+         _OutputHelper.Close();
+         _OutputStream.Close();
+								
+         // Quick way of doing cleanup
+         _OutputStream = new MemoryStream(32768);
+         _OutputHelper = new StreamWriter(_OutputStream, Encoding.Unicode);
+      }
+
+      internal byte [] ToArray() {
+         if (_OutputStream.Length == 0) {
+            return null;
+         }
+
+         // TODO: Optimize
+         byte [] arrStream = _OutputStream.ToArray();
+         byte [] arrData = new byte [arrStream.Length - 2];
+
+         Buffer.BlockCopy(arrStream, 2, arrData, 0, arrStream.Length - 2);
+			
+         byte [] arrContent = _Encoding.GetBytes(Encoding.Unicode.GetString(arrData));
+
+         return arrContent;
+      }
+
+      internal void SendContent(HttpWorkerRequest Handler) {
+         FlushBuffers();
+
+         if (_OutputStream.Length > 0) {
+            byte [] arrContent = ToArray();
+            Handler.SendResponseFromMemory(arrContent, arrContent.Length);
+         }
+      }
+
+      internal void Update() {
+         _Encoder = _Response.ContentEncoder;
+         _Encoding = _Response.ContentEncoding;
+      }
+
+      internal long BufferSize {
+         get {
+            FlushBuffers();
+
+            if (_OutputStream.Length == 0) {
+               return 0;
+            }
+
+            return ToArray().Length;
+         }
+      }
+
+      internal void FlushBuffers() {
+         _OutputHelper.Flush();
+         _OutputStream.Flush();
+      }
+
+      public override Encoding Encoding {
+         get {
+            return _Encoding;
+         }
+      }
+
+      public Stream OutputStream {
+         get {
+            return _ResponseStream;
+         }
+      }
+
+      public override void Close() {
+         FlushBuffers();
+
+         _Response.Flush();
+         _Response.Close();
+      }
+
+      public override void Flush() {
+         FlushBuffers();
+
+         _Response.Flush();
+      }
+
+      public override void Write(char ch) {
+         _OutputHelper.Write(ch);
+         if (!_Response.BufferOutput) {
+            FlushBuffers();
+            _Response.Flush();
+         }
+      }
+
+      public override void Write(object obj) {
+         _OutputHelper.Write(obj.ToString());
+         if (!_Response.BufferOutput) {
+            FlushBuffers();
+            _Response.Flush();
+         }
+      }
+
+      public override void Write(string s) {
+         _OutputHelper.Write(s);
+         if (!_Response.BufferOutput) {
+            FlushBuffers();
+            _Response.Flush();
+         }
+      }
+
+      public override void Write(char[] buffer, int index, int count) {
+         _OutputHelper.Write(buffer, index, count);
+         if (!_Response.BufferOutput) {
+            FlushBuffers();
+            _Response.Flush();
+         }
+      }
+
+      public void WriteBytes(byte[] buffer, int index, int count) {
+         _OutputStream.Write(buffer, index, count);
+         if (!_Response.BufferOutput) {
+            FlushBuffers();
+            _Response.Flush();
+         }
+      }
+		
+      override public void WriteLine() {
+         _OutputHelper.Write("\n\r");
+         if (!_Response.BufferOutput) {
+            FlushBuffers();
+            _Response.Flush();
+         }
+      }
+
+      public void WriteString(string s, int index, int count) {
+         _OutputHelper.Write(s.Substring(index, count));
+         if (!_Response.BufferOutput) {
+            FlushBuffers();
+            _Response.Flush();
+         }
+      }
+   }
+}

+ 15 - 0
mcs/class/System.Web/System.Web/TraceContext.cs

@@ -0,0 +1,15 @@
+// 
+// System.Web.TraceContext
+//
+// Author:
+//   Patrik Torstensson ([email protected])
+//
+using System;
+
+namespace System.Web {
+   [MonoTODO()]
+   public class TraceContext {
+      public TraceContext(HttpContext Context) {
+      }
+   }
+}