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