Making simple web app work with Grasshopper from svn.
[mono.git] / mcs / class / System.Web / System.Web / HttpRequest.cs
1 //
2 // System.Web.HttpRequest
3 //
4 // Authors:
5 //      Patrik Torstensson (Patrik.Torstensson@labs2.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (c) 2001, 2002 Patrick Torstensson
9 // (c) 2002,2003 Ximian, Inc. (http://www.ximian.com)
10 // (c) 2004 Novell, Inc. (http://www.novell.com)
11 //
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33 using System;
34 using System.Collections;
35 using System.Collections.Specialized;
36 using System.Globalization;
37 using System.IO;
38 using System.Text;
39 using System.Web.Configuration;
40 using System.Web.Util;
41
42 #if TARGET_J2EE
43 using vmw.common;
44 #endif
45
46 namespace System.Web {
47         [MonoTODO("Review security in all path access function")]
48         public sealed class HttpRequest {
49                 private string []       _arrAcceptTypes;
50                 private string []       _arrUserLanguages;
51
52                 private byte [] _arrRawContent;
53                 private int     _iContentLength;
54
55                 private string  _sContentType;
56                 private string  _sHttpMethod;
57                 private string  _sRawUrl;
58                 private string  _sUserAgent;
59                 private string  _sUserHostAddress;
60                 private string  _sUserHostName;
61                 private string  _sPath;
62                 private string  _sPathInfo;
63                 private string _sFilePath;
64                 private string baseVirtualDir;
65                 private string _sPathTranslated;
66                 private string _sQueryStringRaw;
67                 private string _sRequestType;
68                 private string _sRequestRootVirtualDir;
69
70                 private Encoding _oContentEncoding;
71
72                 private Uri _oUriReferrer;
73                 private Uri _oUrl;
74
75                 private int     _iTotalBytes;
76
77                 private HttpContext     _oContext;
78
79                 private HttpWorkerRequest _WorkerRequest;
80                 private HttpRequestStream       _oInputStream;
81                 private HttpClientCertificate _ClientCert;
82
83                 private HttpValueCollection _oServerVariables;
84                 private HttpValueCollection _oHeaders;
85                 private HttpValueCollection _oQueryString;
86                 private HttpValueCollection _oFormData;
87                 private HttpValueCollection _oParams;
88
89                 private HttpBrowserCapabilities _browser;
90
91                 private HttpCookieCollection cookies;
92                 Stream userFilter;
93                 HttpRequestStream requestFilter;
94                 string clientTarget;
95                 string currentExePath;
96 #if NET_1_1
97                 bool validateCookies;
98                 bool validateForm;
99                 bool validateQueryString;
100
101                 bool checkedCookies;
102                 bool checkedForm;
103                 bool checkedQueryString;
104 #endif
105
106                 public HttpRequest(string Filename, string Url, string Querystring) {
107                         _iContentLength = -1;
108                         _iTotalBytes = -1;
109
110                         _WorkerRequest = null;
111                         _sPathTranslated = Filename;
112                         _sRequestType = "GET";
113
114                         _oUrl = new Uri(Url);
115                         _sPath = _oUrl.AbsolutePath;
116
117                         _sQueryStringRaw = Querystring;
118                         _oQueryString = new HttpValueCollection(Querystring, true, Encoding.ASCII);
119                 }
120
121                 internal HttpRequest(HttpWorkerRequest WorkRequest, HttpContext Context) {
122                         _WorkerRequest = WorkRequest;
123                         _oContext = Context;
124
125                         _iContentLength = -1;
126                         _iTotalBytes = -1;
127                 }
128
129                 internal void AddHeaderVariables (ServerVariablesCollection coll)
130                 {
131                         if (null == _WorkerRequest)
132                                 return;
133
134                         string hname;
135                         string hvalue;
136
137                         // Add all known headers
138                         for (int i = 0; i < HttpWorkerRequest.RequestHeaderMaximum; i++) {
139                                 hvalue = _WorkerRequest.GetKnownRequestHeader (i);
140                                 if (null != hvalue && hvalue.Length > 0) {
141                                         hname = HttpWorkerRequest.GetKnownRequestHeaderName (i);
142                                         if (null != hname && hname.Length > 0)
143                                                 coll.Add ("HTTP_" + hname.ToUpper ().Replace ('-', '_'), hvalue);
144                                 }
145                         }
146
147                         // Get all other headers
148                         string [][] unknown = _WorkerRequest.GetUnknownRequestHeaders ();
149                         if (null != unknown) {
150                                 for (int i = 0; i < unknown.Length; i++) {
151                                         hname = unknown [i][0];
152                                         hvalue = unknown [i][1];
153                                         coll.Add ("HTTP_" + hname.ToUpper ().Replace ('-', '_'), hvalue);
154                                 }
155                         }
156                 }
157
158                 internal string GetAllHeaders(bool raw) {
159                         StringBuilder oData;
160
161                         if (null == _WorkerRequest) {
162                                 return null;
163                         }
164
165                         oData = new StringBuilder(512);
166
167                         string sHeaderValue;
168                         string sHeaderName;
169                         int iCount = 0;
170
171                         // Add all known headers
172                         for (; iCount != HttpWorkerRequest.RequestHeaderMaximum; iCount++) {
173                                 sHeaderValue = _WorkerRequest.GetKnownRequestHeader(iCount);
174                                 if (null != sHeaderValue && sHeaderValue.Length > 0) {
175                                         sHeaderName = HttpWorkerRequest.GetKnownRequestHeaderName(iCount);
176                                         if (null != sHeaderName && sHeaderName.Length > 0) {
177                                                 if (raw) {
178                                                         oData.Append(sHeaderName);
179                                                 } else {
180                                                         oData.Append ("HTTP_");
181                                                         oData.Append (sHeaderName.ToUpper ().Replace ('-', '_'));
182                                                 }
183                                                 oData.Append(": ");
184                                                 oData.Append(sHeaderValue);
185                                                 oData.Append("\r\n");
186                                         }
187                                 }
188                         }
189
190                         // Get all other headers
191                         string [][] arrUnknownHeaders = _WorkerRequest.GetUnknownRequestHeaders();
192                         if (null != arrUnknownHeaders) {
193                                 for (iCount = 0; iCount != arrUnknownHeaders.Length; iCount++) {
194                                         string hname = arrUnknownHeaders[iCount][0];
195                                         if (raw) {
196                                                 oData.Append (hname);
197                                         } else {
198                                                 oData.Append ("HTTP_");
199                                                 oData.Append (hname.ToUpper ().Replace ('-', '_'));
200                                         }
201                                         oData.Append(": ");
202                                         oData.Append(arrUnknownHeaders[iCount][1]);
203                                         oData.Append("\r\n");
204                                 }
205                         }
206
207                         return oData.ToString();
208                 }
209       
210                 [MonoTODO("We need to handly 'dynamic' variables like AUTH_USER, that can be changed during runtime... special collection")]
211                 private void ParseServerVariables() {
212                         if (null == _WorkerRequest) {
213                                 return;
214                         }
215
216                         if (_oServerVariables == null){ 
217                                 _oServerVariables = new ServerVariablesCollection (this);            
218                                 _oServerVariables.MakeReadOnly ();
219                         }
220                 }
221
222                 private void ParseFormData ()
223                 {
224                         string content_type = ContentType;
225                         if (content_type == null)
226                                 return;
227
228                         content_type = content_type.ToLower (CultureInfo.InvariantCulture);
229                         if (content_type == "application/x-www-form-urlencoded") {
230                                 byte [] arrData = GetRawContent ();
231                                 Encoding enc = ContentEncoding;
232                                 string data = enc.GetString (arrData);
233                                 _oFormData = new HttpValueCollection (data, true, enc);
234                                 return;
235                         }
236
237                         _oFormData = new HttpValueCollection ();
238                         if (StrUtils.StartsWith (content_type, "multipart/form-data")) {
239                                 MultipartContentElement [] parts = GetMultipartFormData ();
240                                 if (parts == null)
241                                         return;
242                                 Encoding content_encoding = ContentEncoding;
243                                 foreach (MultipartContentElement p in parts) {
244                                         if (p.IsFormItem) {
245                                                 _oFormData.Add (p.Name, p.GetString (content_encoding));
246                                         }
247                                 }
248                         }
249                 }
250
251                 [MonoTODO("void Dispose")]
252                 internal void Dispose() {                       
253                 }
254
255                 private byte [] GetRawContent ()
256                 {
257                         if (_arrRawContent != null)
258                                 return _arrRawContent;
259
260                         if (null == _WorkerRequest) {
261                                 if (QueryStringRaw == null)
262                                         return null;
263                                 char [] q = QueryStringRaw.ToCharArray ();
264                                 _arrRawContent = new byte [q.Length];
265                                 for (int i = 0; i < q.Length; i++)
266                                         _arrRawContent [i] = (byte) q [i];
267                                 return _arrRawContent;
268                         }
269
270                         _arrRawContent = _WorkerRequest.GetPreloadedEntityBody ();
271                         if (_arrRawContent == null)
272                                 _arrRawContent = new byte [0];
273
274                         int length = ContentLength;
275                         HttpRuntimeConfig cfg = (HttpRuntimeConfig) _oContext.GetConfig ("system.web/httpRuntime");
276                         int maxRequestLength = cfg.MaxRequestLength * 1024;
277                         if (length > maxRequestLength) {
278                                 throw new HttpException (400, "Maximum request length exceeded.");
279                         }
280                                 
281                         if (_WorkerRequest.IsEntireEntityBodyIsPreloaded () || length <= _arrRawContent.Length)
282                                 return _arrRawContent;
283
284                         byte [] result = new byte [length];
285                         int offset = _arrRawContent.Length;
286                         Buffer.BlockCopy (_arrRawContent, 0, result, 0, offset);
287
288                         int read = 0;
289                         byte [] arrBuffer = new byte [Math.Min (16384, length)];
290                         int bufLength = arrBuffer.Length;
291                         for (; offset < length; offset += read) {
292                                 if (length - offset < bufLength)
293                                         bufLength = length - offset;
294
295                                 read = _WorkerRequest.ReadEntityBody (arrBuffer, bufLength);
296                                 if (read == 0 ||read == -1 )
297                                         break;
298
299                                 if (length > maxRequestLength || offset + read > maxRequestLength)
300                                         throw new HttpException (400, "Maximum request length exceeded.");
301
302                                 Buffer.BlockCopy (arrBuffer, 0, result, offset, read);
303                         }
304
305                         if (offset < length)
306                                 throw new HttpException (400, "Data length is shorter than Content-Length.");
307
308                         _arrRawContent = result;
309                         if (userFilter != null) {
310                                 requestFilter.Set (_arrRawContent, 0, _arrRawContent.Length);
311                                 int userLength = Convert.ToInt32 (userFilter.Length - userFilter.Position);
312                                 byte [] filtered = new byte [userLength];
313                                 userFilter.Read (filtered, 0, userLength);
314                                 _arrRawContent = filtered;
315                         }
316
317                         return _arrRawContent;
318                 }
319                 
320                 internal HttpContext Context {
321                         get { return _oContext; }
322                 }
323
324                 internal HttpWorkerRequest WorkerRequest {
325                         get { return _WorkerRequest; }
326                 }
327
328                 public string [] AcceptTypes {
329                         get {
330                                 if (null == _arrAcceptTypes && null != _WorkerRequest) {
331                                         _arrAcceptTypes = HttpHelper.ParseMultiValueHeader(_WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderAccept));
332                                 } 
333
334                                 return _arrAcceptTypes;
335                                 
336                         }
337                 }
338
339                 public string ApplicationPath {
340                         get {
341                                 if (null != _WorkerRequest) {
342                                         return _WorkerRequest.GetAppPath();
343                                 }
344
345                                 return null;
346                         }
347                 }
348
349                 public HttpBrowserCapabilities Browser {
350                         get {
351                                 if (_browser == null) {
352                                         _browser = (HttpBrowserCapabilities)
353                                                     HttpCapabilitiesBase.GetConfigCapabilities (null, this);
354                                 }
355
356                                 return _browser;
357                         }
358
359                         set { _browser = value; }
360                 }
361
362                 public HttpClientCertificate ClientCertificate {
363                         get {
364                                 if (null == _ClientCert) {
365                                         _ClientCert = new HttpClientCertificate(_oContext);
366                                 }
367
368                                 return _ClientCert;
369                         }
370                 }
371
372                 private string GetValueFromHeader (string header, string attr)
373                 {
374                         int where = header.IndexOf (attr + '=');
375                         if (where == -1)
376                                 return null;
377
378                         where += attr.Length + 1;
379                         int max = header.Length;
380                         if (where >= max)
381                                 return String.Empty;
382
383                         char ending = header [where];
384                         if (ending != '"')
385                                 ending = ' ';
386
387                         int end = header.Substring (where + 1).IndexOf (ending);
388                         if (end == -1)
389                                 return (ending == '"') ? null : header.Substring (where);
390
391                         return header.Substring (where, end);
392                 }
393                 
394                 public Encoding ContentEncoding
395                 {
396                         get {
397                                 if (_oContentEncoding == null) {
398                                         if (_WorkerRequest != null && 
399                                             (!_WorkerRequest.HasEntityBody () || ContentType != String.Empty)) {
400                                                 _oContentEncoding = WebEncoding.RequestEncoding;
401                                         } else  {
402                                                 string charset;
403                                                 charset = GetValueFromHeader (_sContentType, "charset");
404                                                 try {
405                                                         _oContentEncoding = Encoding.GetEncoding (charset);
406                                                 } catch {
407                                                         _oContentEncoding = WebEncoding.RequestEncoding;
408                                                 }
409                                         }
410                                 }
411
412                                 return _oContentEncoding;
413                         }
414
415                         set {
416                                 _oContentEncoding = value;
417                         }
418                 }
419
420                 public int ContentLength {
421                         get {
422                                 if (_iContentLength == -1 && null != _WorkerRequest) {
423                                         string sLength = _WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength);
424                                         if (sLength != null) {
425                                                 try {
426                                                         _iContentLength = Int32.Parse(sLength);
427                                                 }
428                                                 catch(Exception) {
429                                                 }
430                                         } 
431                                 }
432
433                                 if (_iContentLength < 0) {
434                                         _iContentLength = 0;
435                                 }
436
437                                 return _iContentLength;
438                         }
439                 }
440
441                 public string ContentType {
442                         get {
443                                 if (null == _sContentType) {
444                                         if (null != _WorkerRequest) {
445                                                 _sContentType = _WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentType);
446                                         }
447
448                                         if (null == _sContentType) {
449                                                 _sContentType = string.Empty;
450                                         }
451                                 }
452
453                                 return _sContentType;
454                         }
455 #if NET_1_1
456                         set { _sContentType = value; }
457 #endif
458                 }
459
460                 static private string GetCookieValue (string str, int length, ref int i)
461                 {
462                         if (i >= length)
463                                 return null;
464
465                         int k = i;
466                         while (k < length && Char.IsWhiteSpace (str [k]))
467                                 k++;
468
469                         int begin = k;
470                         while (k < length && str [k] != ';')
471                                 k++;
472
473                         i = k;
474                         return str.Substring (begin, i - begin).Trim ();
475                 }
476
477                 static private string GetCookieName (string str, int length, ref int i)
478                 {
479                         if (i >= length)
480                                 return null;
481
482                         int k = i;
483                         while (k < length && Char.IsWhiteSpace (str [k]))
484                                 k++;
485
486                         int begin = k;
487                         while (k < length && str [k] != ';' &&  str [k] != '=')
488                                 k++;
489
490                         i = k + 1;
491                         return str.Substring (begin, k - begin).Trim ();
492                 }
493
494                 private void GetCookies ()
495                 {
496                         string header = _WorkerRequest.GetKnownRequestHeader (HttpWorkerRequest.HeaderCookie);
497                         if (header == null || header.Length == 0)
498                                 return;
499
500                         /* RFC 2109
501                          *      cookie          =       "Cookie:" cookie-version
502                          *                                 1*((";" | ",") cookie-value)
503                          *      cookie-value    =       NAME "=" VALUE [";" path] [";" domain]
504                          *      cookie-version  =       "$Version" "=" value
505                          *      NAME            =       attr
506                          *      VALUE           =       value
507                          *      path            =       "$Path" "=" value
508                          *      domain          =       "$Domain" "=" value
509                          *
510                          *      MS ignores $Version! 
511                          *      ',' as a separator produces errors.
512                          */
513
514                         string [] name_values = header.Trim ().Split (';');
515                         int length = name_values.Length;
516                         HttpCookie cookie = null;
517                         int pos;
518                         for (int i = 0; i < length; i++) {
519                                 pos = 0;
520                                 string name_value = name_values [i].Trim ();
521                                 string name = GetCookieName (name_value, name_value.Length, ref pos);
522                                 string value = GetCookieValue (name_value, name_value.Length, ref pos);
523                                 if (cookie != null) {
524                                         if (name == "$Path") {
525                                                 cookie.Path = value;
526                                                 continue;
527                                         } else if (name == "$Domain") {
528                                                 cookie.Domain = value;
529                                                 continue;
530                                         } else {
531                                                 cookies.Add (cookie);
532                                                 cookie = null;
533                                         }
534                                 }
535                                 cookie = new HttpCookie (name, value);
536                         }
537
538                         if (cookie != null)
539                                 cookies.Add (cookie);
540                 }
541
542                 public HttpCookieCollection Cookies
543                 {
544                         get {
545                                 if (cookies == null) {
546                                         cookies = new HttpCookieCollection (null, false);
547                                         if (_WorkerRequest != null)
548                                                 GetCookies ();
549                                 }
550 #if NET_1_1
551                                 if (validateCookies && !checkedCookies) {
552                                         ValidateCookieCollection (cookies);
553                                         checkedCookies = true;
554                                 }
555 #endif
556                                 return cookies;
557                         }
558                 }
559
560                 public string CurrentExecutionFilePath {
561                         get {
562                                 if (currentExePath != null)
563                                         return currentExePath;
564
565                                 return FilePath;
566                         }
567                 }
568
569                 public string FilePath {
570                         get {
571                                 if (null == _sFilePath && null != _WorkerRequest) {
572                                         _sFilePath = _WorkerRequest.GetFilePath();
573                                         try {
574                                                 _sFilePath = UrlUtils.Reduce (_sFilePath);
575                                         } catch (Exception) {
576                                                 throw new HttpException (403, "Forbidden");
577                                         }
578                                 }
579
580                                 return _sFilePath;
581                         }
582                 }
583
584                 HttpFileCollection files;
585                 public HttpFileCollection Files {
586                         get {
587                                 if (files != null)
588                                         return files;
589                                 
590                                 files = new HttpFileCollection ();
591                                 FillPostedFiles ();
592                                 return files;
593                                 
594                         }
595                 }
596                 
597                 void FillPostedFiles ()
598                 {
599                         if (!StrUtils.StartsWith (ContentType, "multipart/form-data"))
600                                 return;
601                         
602                         MultipartContentElement [] parts = GetMultipartFormData ();
603                         if (parts == null) return;
604                                 
605                         foreach (MultipartContentElement p in parts) {
606                                 if (!p.IsFile) continue;
607                                 files.AddFile (p.Name, p.GetFile ());
608                         }
609                 }
610                 
611                 MultipartContentElement [] multipartContent;
612                 MultipartContentElement [] GetMultipartFormData ()
613                 {
614                         if (multipartContent != null) return multipartContent;
615                         
616                         byte [] raw = GetRawContent ();
617                         byte [] boundary = Encoding.ASCII.GetBytes (("--" + GetValueFromHeader (ContentType, "boundary")));
618                         return multipartContent = HttpMultipartContentParser.Parse (raw, boundary, ContentEncoding);
619                 }
620
621                 public Stream Filter {
622                         get {
623                                 if (userFilter != null)
624                                         return userFilter;
625
626                                 if (requestFilter == null)
627                                         requestFilter = new HttpRequestStream ();
628
629                                 // This is an empty stream. It will not contain data until GetRawContent
630                                 return requestFilter;
631                         }
632
633                         set {
634                                 if (requestFilter == null)
635                                         throw new HttpException ("Invalid request filter.");
636
637                                 userFilter = value;
638                         }
639                 }
640
641                 public NameValueCollection Form {
642                         get {
643                                 if (_oFormData == null) {
644                                         ParseFormData ();
645                                 }
646 #if NET_1_1
647                                 if (validateForm && !checkedForm) {
648                                         ValidateNameValueCollection ("Form", _oFormData);
649                                         checkedForm = true;
650                                 }
651 #endif
652
653                                 return _oFormData;
654                         }
655                 }
656
657                 public NameValueCollection Headers {
658                         get {
659                                 if (_oHeaders == null) {
660                                         _oHeaders = new HttpValueCollection();
661
662                                         if (null != _WorkerRequest) {
663                                                 string sHeaderValue;
664                                                 string sHeaderName;
665                                                 int iCount = 0;
666
667                                                 // Add all know headers
668                                                 for (; iCount != 40; iCount++) {
669                                                         sHeaderValue = _WorkerRequest.GetKnownRequestHeader(iCount);
670                                                         if (null != sHeaderValue && sHeaderValue.Length > 0) {
671                                                                 sHeaderName = HttpWorkerRequest.GetKnownRequestHeaderName(iCount);
672                                                                 if (null != sHeaderName && sHeaderName.Length > 0) {
673                                                                         _oHeaders.Add(sHeaderName, sHeaderValue);
674                                                                 }
675                                                         }
676                                                 }
677
678                                                 // Get all other headers
679                                                 string [][] arrUnknownHeaders = _WorkerRequest.GetUnknownRequestHeaders();
680                                                 if (null != arrUnknownHeaders) {
681                                                         for (iCount = 0; iCount != arrUnknownHeaders.Length; iCount++) {
682                                                                 _oHeaders.Add(arrUnknownHeaders[iCount][0], arrUnknownHeaders[iCount][1]);
683                                                         }
684                                                 }
685                                         }
686
687                                         // Make headers read-only
688                                         _oHeaders.MakeReadOnly();
689                                 }
690
691                                 return (NameValueCollection) _oHeaders;
692                         }
693                 }
694
695                 public string HttpMethod {
696                         get {
697                                 if (null == _sHttpMethod) {
698                                         if (null != _WorkerRequest) {
699                                                 _sHttpMethod = _WorkerRequest.GetHttpVerbName().ToUpper();
700                                         }
701                
702                                         if (_sHttpMethod == null) {
703                                                 if (RequestType != null)
704                                                         _sHttpMethod = RequestType;
705                                                 else
706                                                         _sHttpMethod = "GET";
707                                         }
708                                 }
709
710                                 return _sHttpMethod;
711                         }
712                 }
713
714                 public Stream InputStream {
715                         get {
716                                 if (_oInputStream == null) {
717                                         byte [] arrInputData = GetRawContent ();
718
719                                         if (null != arrInputData) {
720                                                 _oInputStream = new HttpRequestStream(arrInputData, 0, arrInputData.Length);
721                                         } else {
722                                                 _oInputStream = new HttpRequestStream(null, 0, 0);
723                                         }
724                                 }
725
726                                 return _oInputStream;
727                         } 
728                 }
729
730                 public bool IsAuthenticated {
731                         get {
732                                 if (_oContext != null && _oContext.User != null && _oContext.User.Identity != null) {
733                                         return _oContext.User.Identity.IsAuthenticated;
734                                 }
735
736                                 return false;
737                         }
738                 }
739
740                 public bool IsSecureConnection {
741                         get {
742                                 if (null != _WorkerRequest) {
743                                         return _WorkerRequest.IsSecure();
744                                 }
745
746                                 return false;
747                         }
748                 }
749
750                 public string this [string sKey] {
751                         get {
752                                 string result = QueryString [sKey];
753                                 if (result != null)
754                                         return result;
755
756                                 result = Form [sKey];
757                                 if (result != null)
758                                         return result;
759
760                                 HttpCookie cookie = Cookies [sKey];
761                                 if (cookie != null)
762                                         return cookie.Value;
763
764                                 return ServerVariables [sKey];
765                         }
766                 }
767
768                 public NameValueCollection Params {
769                         get {
770                                 if (_oParams == null) {
771                                         _oParams = new HttpValueCollection();
772                                         
773                                         _oParams.Merge(QueryString);
774                                         _oParams.Merge(Form);
775                                         _oParams.Merge(ServerVariables);
776                                         int count = Cookies.Count;
777                                         for (int i = 0; i< count; i++) {
778                                                 HttpCookie cookie = Cookies [i];
779                                                 _oParams.Add (cookie.Name, cookie.Value);
780                                         }
781                                         _oParams.MakeReadOnly();
782                                 }
783
784                                 return (NameValueCollection) _oParams;
785                         }
786                 }
787                 
788                 public string Path {
789                         get {
790                                 if (_sPath == null) {
791                                         if (null != _WorkerRequest) {
792                                                 _sPath = _WorkerRequest.GetUriPath();
793                                         }
794
795                                         if (_sPath == null) {
796                                                 _sPath = string.Empty;
797                                         }
798                                 }
799
800                                 return _sPath;
801                         }
802                 }
803                 
804                 public string PathInfo {
805                         get {
806                                 if (_sPathInfo == null) {
807                                         if (null != _WorkerRequest) {
808                                                 _sPathInfo = _WorkerRequest.GetPathInfo();
809                                         }
810
811                                         if (_sPathInfo == null) {
812                                                 _sPathInfo = string.Empty;
813                                         }
814                                 }
815                                 
816                                 return _sPathInfo;
817                         }
818                 }
819
820                 public string PhysicalApplicationPath {
821                         get {
822                                 if (null != _WorkerRequest) {
823                                         return _WorkerRequest.GetAppPathTranslated();
824                                 }
825
826                                 return null;
827                         }
828                 }
829
830                 public string PhysicalPath {
831                         get {
832                                 if (_sPathTranslated == null && _WorkerRequest != null)
833                                         _sPathTranslated = _WorkerRequest.MapPath (CurrentExecutionFilePath);
834
835                                 return _sPathTranslated;
836                         }
837                 }
838
839                 public NameValueCollection QueryString {
840                         get {
841                                 if (_oQueryString == null) {
842                                         try {
843                                                 _oQueryString = new HttpValueCollection(QueryStringRaw, true,
844                                                                                         ContentEncoding);
845                                         } catch {
846                                                 _oQueryString = new HttpValueCollection(QueryStringRaw, true,
847                                                                                         Encoding.ASCII);
848                                         }
849                                 }
850 #if NET_1_1
851                                 if (validateQueryString && !checkedQueryString) {
852                                         ValidateNameValueCollection ("QueryString", _oQueryString);
853                                         checkedQueryString = true;
854                                 }
855 #endif
856                                 return _oQueryString;
857                         }
858                 }
859
860                 // Used to parse the querystring
861                 internal string QueryStringRaw {
862                         get {
863                                 if (_sQueryStringRaw == null && null != _WorkerRequest) {
864                                         byte [] arrQuerystringBytes = _WorkerRequest.GetQueryStringRawBytes();
865                                         if (null != arrQuerystringBytes && arrQuerystringBytes.Length > 0) {
866                                                 _sQueryStringRaw = ContentEncoding.GetString(arrQuerystringBytes);
867                                         } else {
868                                                 _sQueryStringRaw = _WorkerRequest.GetQueryString();   
869                                         }
870                                 }
871
872                                 if (_sQueryStringRaw == null) {
873                                         _sQueryStringRaw = string.Empty;
874                                 }
875
876                                 return _sQueryStringRaw;
877                         }
878                         
879                         set {
880                                 _sQueryStringRaw = value;
881                                 _oQueryString = null;
882                                 _arrRawContent = null;
883                                 _sRawUrl = null;
884                         }
885                 }
886
887                 public string RawUrl {
888                         get {
889                                 if (null == _sRawUrl) {
890                                         if (null != _WorkerRequest) {
891                                                 _sRawUrl = _WorkerRequest.GetRawUrl();
892                                         } else {
893                                                 _sRawUrl = Path;
894                                                 if (QueryStringRaw != null && QueryStringRaw.Length > 0) {
895                                                         _sRawUrl = _sRawUrl + "?" + QueryStringRaw;
896                                                 }
897                                         }
898                                 }
899
900                                 return _sRawUrl;
901                         }
902                 }
903
904                 public string RequestType {
905                         get {
906                                 if (null == _sRequestType) {
907                                         return HttpMethod;
908                                 }
909          
910                                 return _sRequestType;
911                         }
912
913                         set {
914                                 _sRequestType = value;
915                         }
916                 }
917                 
918       
919                 public NameValueCollection ServerVariables {
920                         get {
921                                 ParseServerVariables();
922
923                                 return (NameValueCollection) _oServerVariables;
924                         }
925                 }      
926
927                 public int TotalBytes {
928                         get {
929                                 if (_iTotalBytes == -1) {
930                                         if (null != InputStream) {
931                                                 _iTotalBytes = (int) InputStream.Length;
932                                         } else {
933                                                 _iTotalBytes = 0;
934                                         }
935                                 }
936
937                                 return _iTotalBytes;
938                         }
939                 }
940
941                 public Uri Url {
942                         get {
943                                 if (_oUrl != null || _WorkerRequest == null)
944                                         return _oUrl;
945
946                                 string qs = QueryStringRaw;
947                                 if (qs == null)
948                                         qs = "";
949                                 else
950                                         qs = "?" + qs;
951
952                                 UriBuilder ub = new UriBuilder (_WorkerRequest.GetProtocol (),
953                                                                 _WorkerRequest.GetServerName (),
954                                                                 _WorkerRequest.GetLocalPort (),
955                                                                 Path,
956                                                                 qs);
957
958                                 _oUrl = ub.Uri;
959                                 return _oUrl;
960                         }
961                 }
962
963                 public Uri UrlReferrer {
964                         get {
965                                 if (null == _oUriReferrer && null != _WorkerRequest) {
966                                         string sReferrer = _WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderReferer);
967                                         if (null != sReferrer && sReferrer.Length > 0) {
968                                                 try {
969                                                         if (sReferrer.IndexOf("://") >= 0) {
970                                                                 _oUriReferrer = new Uri(sReferrer);
971                                                         } else {
972                                                                 _oUriReferrer = new Uri(this.Url, sReferrer);
973                                                         }
974                                                 }
975                                                 catch (Exception) {
976                                                 }
977                                         }
978                                 }
979
980                                 return _oUriReferrer;
981                         }
982                 }
983
984                 public string UserAgent {
985                         get {
986                                 if (_sUserAgent == null && _WorkerRequest != null) {
987                                         _sUserAgent = _WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderUserAgent);
988                                 }
989
990                                 if (_sUserAgent == null) {
991                                         _sUserAgent = string.Empty;
992                                 }
993
994                                 return _sUserAgent;
995                         }
996                 }
997
998                 public string UserHostAddress {
999                         get {
1000                                 if (_sUserHostAddress == null && null != _WorkerRequest) {
1001                                         _sUserHostAddress = _WorkerRequest.GetRemoteAddress();
1002                                 }
1003
1004                                 if (_sUserHostAddress == null || _sUserHostAddress.Length == 0) {
1005                                         _sUserHostAddress = "127.0.0.1";
1006                                 }
1007
1008                                 return _sUserHostAddress;
1009                         }
1010                 }
1011                 
1012                 public string UserHostName {
1013                         get {
1014                                 if (_sUserHostName == null && null != _WorkerRequest) {
1015                                         _sUserHostName = _WorkerRequest.GetRemoteName();
1016                                 }
1017
1018                                 if (_sUserHostName == null || _sUserHostName.Length == 0) {
1019                                         _sUserHostName = UserHostAddress;
1020                                 }
1021
1022                                 return _sUserHostName;
1023                         }
1024                 }
1025                 
1026                 public string [] UserLanguages {
1027                         get {
1028                                 if (_arrUserLanguages == null && null != _WorkerRequest) {
1029                                         _arrUserLanguages = HttpHelper.ParseMultiValueHeader(_WorkerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderAcceptLanguage));
1030                                 }
1031
1032                                 return _arrUserLanguages;
1033                         }
1034                 }
1035
1036                 internal string RootVirtualDir {
1037                         get {
1038                                 if (_sRequestRootVirtualDir == null) {
1039                                         _sRequestRootVirtualDir = FilePath;
1040                                         int pos = _sRequestRootVirtualDir.LastIndexOf ('/');
1041                                         if (pos == -1 || pos == 0)
1042                                                 _sRequestRootVirtualDir = "/";
1043                                         else
1044                                                 _sRequestRootVirtualDir = _sRequestRootVirtualDir.Substring (0, pos);
1045                                 }
1046
1047                                 return _sRequestRootVirtualDir;
1048                         }
1049                 }
1050                 
1051                 internal string BaseVirtualDir {
1052                         get {
1053                                 if (baseVirtualDir == null)
1054                                         baseVirtualDir = UrlUtils.GetDirectory (FilePath);
1055
1056                                 return baseVirtualDir;
1057                         }
1058                 }
1059
1060                 internal bool IsLocal {
1061                         get {
1062                                 return _WorkerRequest.GetLocalAddress () == "127.0.0.1";
1063                         }
1064                 }
1065                 
1066                 public byte [] BinaryRead (int count)
1067                 {
1068                         if (count < 0 || count > TotalBytes)
1069                                 throw new ArgumentOutOfRangeException ("count");
1070
1071                         byte [] data = new byte [count];
1072                         int nread = InputStream.Read (data, 0, count);
1073                         if (nread != count) {
1074                                 byte [] tmp = new byte [nread];
1075                                 Buffer.BlockCopy (data, 0, tmp, 0, nread);
1076                                 data = tmp;
1077                         }
1078
1079                         return data;
1080                 }
1081
1082                 public int [] MapImageCoordinates(string ImageFieldName) {
1083                         NameValueCollection oItems;
1084
1085                         if (HttpMethod == "GET" || HttpMethod == "HEAD") {
1086                                 oItems = QueryString;
1087                         } else if (HttpMethod == "POST") {
1088                                 oItems = Form;
1089                         } else {
1090                                 return null;
1091                         }
1092
1093                         int [] arrRet = null;
1094                         try {
1095                                 string sX = oItems.Get(ImageFieldName + ".x");
1096                                 string sY = oItems.Get(ImageFieldName + ".y");
1097
1098                                 if (null != sX && null != sY) {
1099                                         int [] arrTmp = new Int32[2];
1100                                         arrRet[0] = Int32.Parse(sX);
1101                                         arrRet[1] = Int32.Parse(sY);
1102
1103                                         arrRet = arrTmp;
1104                                 }
1105                         }
1106                         catch (Exception) {
1107                         }
1108
1109                         return arrRet;
1110                 }
1111
1112                 public string MapPath (string VirtualPath)
1113                 {
1114                         return MapPath (VirtualPath, BaseVirtualDir, true);
1115                 }
1116
1117                 public string MapPath (string virtualPath, string baseVirtualDir, bool allowCrossAppMapping)
1118                 {
1119                         if (_WorkerRequest == null)
1120                                 throw new HttpException ("No HttpWorkerRequest!!!");
1121
1122 #if TARGET_J2EE
1123                         if (baseVirtualDir.Equals(BaseVirtualDir))
1124                         {
1125                                 string val =  System.Web.J2EE.PageMapper.GetFromMapPathCache(virtualPath);
1126                                 if (val != null)
1127                                         return val;
1128                         }
1129 #endif
1130
1131                         if (virtualPath == null || virtualPath.Length == 0)
1132                                 virtualPath = ".";
1133                         else
1134                                 virtualPath = virtualPath.Trim ();
1135
1136                         if (virtualPath.IndexOf (':') != -1)
1137                                 throw new ArgumentException ("Invalid path -> " + virtualPath);
1138 #if TARGET_J2EE
1139                         if (virtualPath.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL))
1140                                 return  virtualPath;
1141 #endif
1142                         if (System.IO.Path.DirectorySeparatorChar != '/')
1143                                 virtualPath = virtualPath.Replace (System.IO.Path.DirectorySeparatorChar, '/');
1144
1145                         if (UrlUtils.IsRooted (virtualPath)) {
1146                                 virtualPath = UrlUtils.Reduce (virtualPath);
1147                         } else {
1148                                 if (baseVirtualDir == null) {
1149                                         virtualPath = UrlUtils.Combine (RootVirtualDir, virtualPath);
1150                                 } else {
1151                                         virtualPath = UrlUtils.Combine (baseVirtualDir, virtualPath);
1152                                 }
1153                         }
1154
1155                         if (!allowCrossAppMapping) {
1156                                 if (!StrUtils.StartsWith (virtualPath, RootVirtualDir, true))
1157                                         throw new HttpException ("Mapping across applications not allowed.");
1158
1159                                 if (RootVirtualDir.Length > 1 && virtualPath.Length > 1 && virtualPath [0] != '/')
1160                                         throw new HttpException ("Mapping across applications not allowed.");
1161                         }
1162                         
1163                         return _WorkerRequest.MapPath (virtualPath);
1164                 }
1165
1166                 public void SaveAs(string filename, bool includeHeaders) {
1167                         FileStream oFile;
1168                         TextWriter oWriter;
1169                         HttpRequestStream oData;
1170
1171                         oFile = new FileStream(filename, FileMode.CreateNew);
1172                         if (includeHeaders) {
1173                                 oWriter = new StreamWriter(oFile);
1174                                 oWriter.Write(HttpMethod + " " + Path);
1175
1176                                 if (QueryStringRaw != null && QueryStringRaw.Length > 0)
1177                                         oWriter.Write("?" + QueryStringRaw);
1178                                 if (_WorkerRequest != null) {
1179                                         oWriter.Write(" " + _WorkerRequest.GetHttpVersion() + "\r\n");
1180                                         oWriter.Write(GetAllHeaders(true));
1181                                 } else {
1182                                         oWriter.Write("\r\n");
1183                                 }
1184
1185                                 oWriter.Write("\r\n");
1186                                 oWriter.Flush();
1187                         }
1188
1189                         oData = (HttpRequestStream) InputStream;
1190
1191                         if (oData.DataLength > 0) {
1192                                 oFile.Write(oData.Data, oData.DataOffset, oData.DataLength);
1193                         }
1194
1195                         oFile.Flush();
1196                         oFile.Close();
1197                 }
1198
1199 #if NET_1_1
1200                 public void ValidateInput ()
1201                 {
1202                         validateCookies = true;
1203                         validateQueryString = true;
1204                         validateForm = true;
1205                 }
1206 #endif
1207                 
1208                 internal void SetCurrentExePath (string filePath)
1209                 {
1210                         currentExePath = filePath;
1211                         _sPath = filePath;
1212                         _sFilePath = filePath;
1213                         _sRequestRootVirtualDir = null;
1214                         baseVirtualDir = null;
1215                         _sPathTranslated = null;
1216                 }
1217
1218                 internal void SetPathInfo (string pathInfo)
1219                 {
1220                         _sPathInfo = pathInfo;
1221                 }
1222
1223                 internal void SetForm (HttpValueCollection form)
1224                 {
1225                         _oFormData = form;
1226                 }
1227
1228                 internal void SetHeader (string name, string value)
1229                 {
1230                         HttpValueCollection headers = (HttpValueCollection) Headers;
1231                         headers.MakeReadWrite ();
1232                         headers [name] = value;
1233                         headers.MakeReadOnly ();
1234                 }
1235
1236                 internal string ClientTarget {
1237                         get { return clientTarget; }
1238                         set {
1239                                 if (value != clientTarget) {
1240                                         clientTarget = value;
1241                                         _browser = null;
1242                                 }
1243                         }
1244                 }
1245
1246 #if NET_1_1
1247                 static void ValidateNameValueCollection (string name, NameValueCollection coll)
1248                 {
1249                         if (coll == null)
1250                                 return;
1251
1252                         foreach (string key in coll.Keys) {
1253                                 string val = coll [key];
1254                                 if (CheckString (val))
1255                                         ThrowValidationException (name, key, val);
1256                         }
1257                 }
1258
1259                 static void ValidateCookieCollection (HttpCookieCollection cookies)
1260                 {
1261                         if (cookies == null)
1262                                 return;
1263
1264                         int size = cookies.Count;
1265                         HttpCookie cookie;
1266                         for (int i = 0 ; i < size ; i++) {
1267                                 cookie = cookies[i];
1268                                 if (CheckString (cookie.Value))
1269                                         ThrowValidationException ("Cookies", cookie.Name, cookie.Value);
1270                         }
1271                 }
1272
1273                 static void ThrowValidationException (string name, string key, string value)
1274                 {
1275                         string v = "\"" + value + "\"";
1276                         if (v.Length > 20)
1277                                 v = v.Substring (0, 16) + "...\"";
1278
1279                         string msg = String.Format ("A potentially dangerous Request.{0} value was " +
1280                                                     "detected from the client ({1}={2}).", name, key, v);
1281
1282                         throw new HttpRequestValidationException (msg);
1283                 }
1284
1285                 static bool CheckString (string val)
1286                 {
1287                         if (val == null)
1288                                 return false;
1289
1290                         //TODO: More checks
1291                         foreach (char c in val) {
1292                                 if (c == '<' || c == '>' || c == '\xff1c' || c == '\xff1e')
1293                                         return true;
1294                         }
1295
1296                         return false;
1297                 }
1298 #endif
1299         }
1300 }
1301