Making simple web app work with Grasshopper from svn.
[mono.git] / mcs / class / System.Web / System.Web / HttpRequest.cs
index c9ae49eea9962dddcdbd1af42fdf9ff8df022d02..97293adafa80fc41663276f04c28e4ab81afecb2 100644 (file)
 using System;
 using System.Collections;
 using System.Collections.Specialized;
+using System.Globalization;
 using System.IO;
 using System.Text;
 using System.Web.Configuration;
 using System.Web.Util;
 
+#if TARGET_J2EE
+using vmw.common;
+#endif
+
 namespace System.Web {
        [MonoTODO("Review security in all path access function")]
        public sealed class HttpRequest {
@@ -92,6 +97,10 @@ namespace System.Web {
                bool validateCookies;
                bool validateForm;
                bool validateQueryString;
+
+               bool checkedCookies;
+               bool checkedForm;
+               bool checkedQueryString;
 #endif
 
                public HttpRequest(string Filename, string Url, string Querystring) {
@@ -117,11 +126,36 @@ namespace System.Web {
                        _iTotalBytes = -1;
                }
 
-               static private string MakeServerVariableFromHeader(string header) {
-                       return "HTTP_" + header.ToUpper().Replace("-", "_");
+               internal void AddHeaderVariables (ServerVariablesCollection coll)
+               {
+                       if (null == _WorkerRequest)
+                               return;
+
+                       string hname;
+                       string hvalue;
+
+                       // Add all known headers
+                       for (int i = 0; i < HttpWorkerRequest.RequestHeaderMaximum; i++) {
+                               hvalue = _WorkerRequest.GetKnownRequestHeader (i);
+                               if (null != hvalue && hvalue.Length > 0) {
+                                       hname = HttpWorkerRequest.GetKnownRequestHeaderName (i);
+                                       if (null != hname && hname.Length > 0)
+                                               coll.Add ("HTTP_" + hname.ToUpper ().Replace ('-', '_'), hvalue);
+                               }
+                       }
+
+                       // Get all other headers
+                       string [][] unknown = _WorkerRequest.GetUnknownRequestHeaders ();
+                       if (null != unknown) {
+                               for (int i = 0; i < unknown.Length; i++) {
+                                       hname = unknown [i][0];
+                                       hvalue = unknown [i][1];
+                                       coll.Add ("HTTP_" + hname.ToUpper ().Replace ('-', '_'), hvalue);
+                               }
+                       }
                }
 
-               internal string GetAllHeaders(bool Raw) {
+               internal string GetAllHeaders(bool raw) {
                        StringBuilder oData;
 
                        if (null == _WorkerRequest) {
@@ -134,13 +168,18 @@ namespace System.Web {
                        string sHeaderName;
                        int iCount = 0;
 
-                       // Add all know headers
-                       for (; iCount != 40; iCount++) {
+                       // Add all known headers
+                       for (; iCount != HttpWorkerRequest.RequestHeaderMaximum; iCount++) {
                                sHeaderValue = _WorkerRequest.GetKnownRequestHeader(iCount);
                                if (null != sHeaderValue && sHeaderValue.Length > 0) {
-                                       sHeaderName = _WorkerRequest.GetKnownRequestHeader(iCount);
+                                       sHeaderName = HttpWorkerRequest.GetKnownRequestHeaderName(iCount);
                                        if (null != sHeaderName && sHeaderName.Length > 0) {
-                                               oData.Append(sHeaderName);
+                                               if (raw) {
+                                                       oData.Append(sHeaderName);
+                                               } else {
+                                                       oData.Append ("HTTP_");
+                                                       oData.Append (sHeaderName.ToUpper ().Replace ('-', '_'));
+                                               }
                                                oData.Append(": ");
                                                oData.Append(sHeaderValue);
                                                oData.Append("\r\n");
@@ -152,7 +191,13 @@ namespace System.Web {
                        string [][] arrUnknownHeaders = _WorkerRequest.GetUnknownRequestHeaders();
                        if (null != arrUnknownHeaders) {
                                for (iCount = 0; iCount != arrUnknownHeaders.Length; iCount++) {
-                                       oData.Append(arrUnknownHeaders[iCount][0]);
+                                       string hname = arrUnknownHeaders[iCount][0];
+                                       if (raw) {
+                                               oData.Append (hname);
+                                       } else {
+                                               oData.Append ("HTTP_");
+                                               oData.Append (hname.ToUpper ().Replace ('-', '_'));
+                                       }
                                        oData.Append(": ");
                                        oData.Append(arrUnknownHeaders[iCount][1]);
                                        oData.Append("\r\n");
@@ -176,30 +221,31 @@ namespace System.Web {
 
                private void ParseFormData ()
                {
-                       string contentType = ContentType;
-                       if (0 == String.Compare (contentType, "application/x-www-form-urlencoded", true)) {
+                       string content_type = ContentType;
+                       if (content_type == null)
+                               return;
+
+                       content_type = content_type.ToLower (CultureInfo.InvariantCulture);
+                       if (content_type == "application/x-www-form-urlencoded") {
                                byte [] arrData = GetRawContent ();
                                Encoding enc = ContentEncoding;
                                string data = enc.GetString (arrData);
                                _oFormData = new HttpValueCollection (data, true, enc);
                                return;
                        }
-                       if (!ContentType.StartsWith ("multipart/form-data")) {
-                               if (contentType.Length > 0)
-                                       Console.WriteLine ("Content-Type -> {0} not supported", contentType);
-                               _oFormData = new HttpValueCollection ();
-                               return;
-                       }
-                       
-                       MultipartContentElement [] parts = GetMultipartFormData ();
+
                        _oFormData = new HttpValueCollection ();
-                       if (parts == null) return;
-                               
-                       foreach (MultipartContentElement p in parts) {
-                               if (!p.IsFormItem) continue;
-                               _oFormData.Add (p.Name, p.GetString (ContentEncoding));
+                       if (StrUtils.StartsWith (content_type, "multipart/form-data")) {
+                               MultipartContentElement [] parts = GetMultipartFormData ();
+                               if (parts == null)
+                                       return;
+                               Encoding content_encoding = ContentEncoding;
+                               foreach (MultipartContentElement p in parts) {
+                                       if (p.IsFormItem) {
+                                               _oFormData.Add (p.Name, p.GetString (content_encoding));
+                                       }
+                               }
                        }
-
                }
 
                [MonoTODO("void Dispose")]
@@ -228,37 +274,38 @@ namespace System.Web {
                        int length = ContentLength;
                        HttpRuntimeConfig cfg = (HttpRuntimeConfig) _oContext.GetConfig ("system.web/httpRuntime");
                        int maxRequestLength = cfg.MaxRequestLength * 1024;
-                       if (ContentLength > maxRequestLength)
+                       if (length > maxRequestLength) {
                                throw new HttpException (400, "Maximum request length exceeded.");
+                       }
                                
                        if (_WorkerRequest.IsEntireEntityBodyIsPreloaded () || length <= _arrRawContent.Length)
                                return _arrRawContent;
 
-                       byte [] arrBuffer = new byte [Math.Min (16384, length)];
-                       MemoryStream ms = new MemoryStream (arrBuffer.Length);
-                       ms.Write (_arrRawContent, 0, _arrRawContent.Length);
+                       byte [] result = new byte [length];
+                       int offset = _arrRawContent.Length;
+                       Buffer.BlockCopy (_arrRawContent, 0, result, 0, offset);
+
                        int read = 0;
+                       byte [] arrBuffer = new byte [Math.Min (16384, length)];
                        int bufLength = arrBuffer.Length;
-                       for (int loaded = _arrRawContent.Length; loaded < length; loaded += read) {
-                               if (length - loaded < bufLength)
-                                       bufLength = length - loaded;
+                       for (; offset < length; offset += read) {
+                               if (length - offset < bufLength)
+                                       bufLength = length - offset;
 
                                read = _WorkerRequest.ReadEntityBody (arrBuffer, bufLength);
                                if (read == 0 ||read == -1 )
                                        break;
 
-                               if (ContentLength > maxRequestLength || ms.Length + read > maxRequestLength)
+                               if (length > maxRequestLength || offset + read > maxRequestLength)
                                        throw new HttpException (400, "Maximum request length exceeded.");
 
-                               ms.Write (arrBuffer, 0, read);
+                               Buffer.BlockCopy (arrBuffer, 0, result, offset, read);
                        }
 
-                       byte [] msBuffer = ms.GetBuffer ();
-                       if (msBuffer.Length == length)
-                               _arrRawContent = msBuffer;
-                       else
-                               _arrRawContent = ms.ToArray ();
+                       if (offset < length)
+                               throw new HttpException (400, "Data length is shorter than Content-Length.");
 
+                       _arrRawContent = result;
                        if (userFilter != null) {
                                requestFilter.Set (_arrRawContent, 0, _arrRawContent.Length);
                                int userLength = Convert.ToInt32 (userFilter.Length - userFilter.Position);
@@ -499,12 +546,13 @@ namespace System.Web {
                                        cookies = new HttpCookieCollection (null, false);
                                        if (_WorkerRequest != null)
                                                GetCookies ();
+                               }
 #if NET_1_1
-                                       if (validateCookies)
-                                               ValidateCookieCollection (cookies);
-#endif
+                               if (validateCookies && !checkedCookies) {
+                                       ValidateCookieCollection (cookies);
+                                       checkedCookies = true;
                                }
-
+#endif
                                return cookies;
                        }
                }
@@ -548,7 +596,8 @@ namespace System.Web {
                
                void FillPostedFiles ()
                {
-                       if (!ContentType.StartsWith ("multipart/form-data")) return;
+                       if (!StrUtils.StartsWith (ContentType, "multipart/form-data"))
+                               return;
                        
                        MultipartContentElement [] parts = GetMultipartFormData ();
                        if (parts == null) return;
@@ -593,11 +642,13 @@ namespace System.Web {
                        get {
                                if (_oFormData == null) {
                                        ParseFormData ();
+                               }
 #if NET_1_1
-                                       if (validateForm)
-                                               ValidateNameValueCollection ("Form", _oFormData);
-#endif
+                               if (validateForm && !checkedForm) {
+                                       ValidateNameValueCollection ("Form", _oFormData);
+                                       checkedForm = true;
                                }
+#endif
 
                                return _oFormData;
                        }
@@ -722,9 +773,11 @@ namespace System.Web {
                                        _oParams.Merge(QueryString);
                                        _oParams.Merge(Form);
                                        _oParams.Merge(ServerVariables);
-                                       string [] cookies = Cookies.AllKeys;
-                                       foreach (string k in cookies)
-                                               _oParams.Add (k, Cookies [k].ToString ());
+                                       int count = Cookies.Count;
+                                       for (int i = 0; i< count; i++) {
+                                               HttpCookie cookie = Cookies [i];
+                                               _oParams.Add (cookie.Name, cookie.Value);
+                                       }
                                        _oParams.MakeReadOnly();
                                }
 
@@ -793,12 +846,13 @@ namespace System.Web {
                                                _oQueryString = new HttpValueCollection(QueryStringRaw, true,
                                                                                        Encoding.ASCII);
                                        }
+                               }
 #if NET_1_1
-                                       if (validateQueryString)
-                                               ValidateNameValueCollection ("QueryString", _oQueryString);
-#endif
+                               if (validateQueryString && !checkedQueryString) {
+                                       ValidateNameValueCollection ("QueryString", _oQueryString);
+                                       checkedQueryString = true;
                                }
-
+#endif
                                return _oQueryString;
                        }
                }
@@ -1009,25 +1063,20 @@ namespace System.Web {
                         }
                 }
                 
-               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);
-                               }
+               public byte [] BinaryRead (int count)
+               {
+                       if (count < 0 || count > TotalBytes)
+                               throw new ArgumentOutOfRangeException ("count");
 
-                               arrData = tmpData;
+                       byte [] data = new byte [count];
+                       int nread = InputStream.Read (data, 0, count);
+                       if (nread != count) {
+                               byte [] tmp = new byte [nread];
+                               Buffer.BlockCopy (data, 0, tmp, 0, nread);
+                               data = tmp;
                        }
 
-                       return arrData;
+                       return data;
                }
 
                public int [] MapImageCoordinates(string ImageFieldName) {
@@ -1070,6 +1119,15 @@ namespace System.Web {
                        if (_WorkerRequest == null)
                                throw new HttpException ("No HttpWorkerRequest!!!");
 
+#if TARGET_J2EE
+                       if (baseVirtualDir.Equals(BaseVirtualDir))
+                       {
+                               string val =  System.Web.J2EE.PageMapper.GetFromMapPathCache(virtualPath);
+                               if (val != null)
+                                       return val;
+                       }
+#endif
+
                        if (virtualPath == null || virtualPath.Length == 0)
                                virtualPath = ".";
                        else
@@ -1077,7 +1135,10 @@ namespace System.Web {
 
                        if (virtualPath.IndexOf (':') != -1)
                                throw new ArgumentException ("Invalid path -> " + virtualPath);
-
+#if TARGET_J2EE
+                       if (virtualPath.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL))
+                               return  virtualPath;
+#endif
                        if (System.IO.Path.DirectorySeparatorChar != '/')
                                virtualPath = virtualPath.Replace (System.IO.Path.DirectorySeparatorChar, '/');
 
@@ -1092,7 +1153,7 @@ namespace System.Web {
                        }
 
                        if (!allowCrossAppMapping) {
-                               if (!virtualPath.ToLower ().StartsWith (RootVirtualDir.ToLower ()))
+                               if (!StrUtils.StartsWith (virtualPath, RootVirtualDir, true))
                                        throw new HttpException ("Mapping across applications not allowed.");
 
                                if (RootVirtualDir.Length > 1 && virtualPath.Length > 1 && virtualPath [0] != '/')
@@ -1147,6 +1208,8 @@ namespace System.Web {
                internal void SetCurrentExePath (string filePath)
                {
                        currentExePath = filePath;
+                       _sPath = filePath;
+                       _sFilePath = filePath;
                        _sRequestRootVirtualDir = null;
                        baseVirtualDir = null;
                        _sPathTranslated = null;