New test.
[mono.git] / mcs / class / System.Web / System.Web / HttpWorkerRequest.cs
1 //
2 // System.Web.HttoWorkerRequest.cs 
3 //
4 // Author:
5 //      Miguel de Icaza (miguel@novell.com)
6 //
7
8 //
9 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Collections;
32 using System.Runtime.InteropServices;
33 using System.Security.Permissions;
34 using System.Web.UI;
35 using System.Collections.Specialized;
36
37 namespace System.Web {
38
39         // CAS
40         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
41         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
42         // attributes
43         [ComVisible (false)]
44         public abstract class HttpWorkerRequest {
45
46                 public delegate void EndOfSendNotification (HttpWorkerRequest wr, object extraData);
47
48                 public const int HeaderCacheControl = 0;
49                 public const int HeaderConnection = 1;
50                 public const int HeaderDate = 2;
51                 public const int HeaderKeepAlive = 3;
52                 public const int HeaderPragma = 4;
53                 public const int HeaderTrailer = 5;
54                 public const int HeaderTransferEncoding = 6;
55                 public const int HeaderUpgrade = 7;
56                 public const int HeaderVia = 8;
57                 public const int HeaderWarning = 9;
58                 public const int HeaderAllow = 10;
59                 public const int HeaderContentLength = 11;
60                 public const int HeaderContentType = 12;
61                 public const int HeaderContentEncoding = 13;
62                 public const int HeaderContentLanguage = 14;
63                 public const int HeaderContentLocation = 15;
64                 public const int HeaderContentMd5 = 16;
65                 public const int HeaderContentRange = 17;
66                 public const int HeaderExpires = 18;
67                 public const int HeaderLastModified = 19;
68                 public const int HeaderAccept = 20;
69                 public const int HeaderAcceptCharset = 21;
70                 public const int HeaderAcceptEncoding = 22;
71                 public const int HeaderAcceptLanguage = 23;
72                 public const int HeaderAuthorization = 24;
73                 public const int HeaderCookie = 25;
74                 public const int HeaderExpect = 26;
75                 public const int HeaderFrom = 27;
76                 public const int HeaderHost = 28;
77                 public const int HeaderIfMatch = 29;
78                 public const int HeaderIfModifiedSince = 30;
79                 public const int HeaderIfNoneMatch = 31;
80                 public const int HeaderIfRange = 32;
81                 public const int HeaderIfUnmodifiedSince = 33;
82                 public const int HeaderMaxForwards = 34;
83                 public const int HeaderProxyAuthorization = 35;
84                 public const int HeaderReferer = 36;
85                 public const int HeaderRange = 37;
86                 public const int HeaderTe = 38;
87                 public const int HeaderUserAgent = 39;
88                 public const int RequestHeaderMaximum = 40;
89
90                 public const int HeaderAcceptRanges = 20;
91                 public const int HeaderAge = 21;
92                 public const int HeaderEtag = 22;
93                 public const int HeaderLocation = 23;
94                 public const int HeaderProxyAuthenticate = 24;
95                 public const int HeaderRetryAfter = 25;
96                 public const int HeaderServer = 26;
97                 public const int HeaderSetCookie = 27;
98                 public const int HeaderVary = 28;
99                 public const int HeaderWwwAuthenticate = 29;
100                 public const int ResponseHeaderMaximum = 30;
101
102                 public const int ReasonResponseCacheMiss = 0;
103                 public const int ReasonFileHandleCacheMiss = 1;
104                 public const int ReasonCachePolicy = 2;
105                 public const int ReasonCacheSecurity = 3;
106                 public const int ReasonClientDisconnect = 4;
107                 public const int ReasonDefault = 0;
108
109                 static readonly Hashtable RequestHeaderIndexer;
110                 static readonly Hashtable ResponseHeaderIndexer;
111
112                 static HttpWorkerRequest() {
113                         RequestHeaderIndexer = CollectionsUtil.CreateCaseInsensitiveHashtable(RequestHeaderMaximum);
114                         for (int i = 0; i < RequestHeaderMaximum; i++)
115                                 RequestHeaderIndexer[GetKnownRequestHeaderName(i)] = i;
116
117                         ResponseHeaderIndexer = CollectionsUtil.CreateCaseInsensitiveHashtable(ResponseHeaderMaximum);
118                         for (int i = 0; i < ResponseHeaderMaximum; i++)
119                                 ResponseHeaderIndexer[GetKnownResponseHeaderName(i)] = i;
120                 }
121
122                 public virtual string MachineConfigPath {
123                         get {
124                                 return null;
125                         }
126                 }
127
128                 public virtual string MachineInstallDirectory {
129                         get {
130                                 return null;
131                         }
132                 }
133
134 #if NET_2_0
135                 public virtual Guid RequestTraceIdentifier {
136                         get { return Guid.Empty; }
137                 }
138
139                 public virtual string RootWebConfigPath {
140                         get { return null; }
141                 }
142 #endif
143
144                 public virtual void CloseConnection ()
145                 {
146                 }
147
148                 public virtual string GetAppPath ()
149                 {
150                         return null;
151                 }
152
153                 public virtual string GetAppPathTranslated ()
154                 {
155                         return null;
156                 }
157
158                 public virtual string GetAppPoolID ()
159                 {
160                         return null;
161                 }
162                 
163                 public virtual long GetBytesRead ()
164                 {
165                         return 0;
166                 }
167
168                 public virtual string GetFilePath ()
169                 {
170                         return null;
171                 }
172
173                 public virtual string GetFilePathTranslated ()
174                 {
175                         return null;
176                 }
177
178                 public virtual string GetKnownRequestHeader (int index)
179                 {
180                         return null;
181                 }
182
183                 public virtual string GetPathInfo ()
184                 {
185                         return "";
186                 }
187
188                 public virtual byte [] GetPreloadedEntityBody ()
189                 {
190                         return null;
191                 }
192 #if NET_2_0
193                 public virtual int GetPreloadedEntityBody (byte[] buffer, int offset)
194                 {
195                         return 0;
196                 }
197
198                 public virtual int GetPreloadedEntityBodyLength ()
199                 {
200                         return 0;
201                 }
202 #endif
203                 public virtual string GetProtocol ()
204                 {
205                         if (IsSecure ())
206                                 return "https";
207                         else
208                                 return "http";
209                 }
210                 
211                 public virtual byte [] GetQueryStringRawBytes ()
212                 {
213                         return null;
214                 }
215
216                 public virtual string GetRemoteName ()
217                 {
218                         return GetRemoteAddress ();
219                 }
220                 
221                 public virtual int GetRequestReason ()
222                 {
223                         return 0;
224                 }
225
226                 public virtual string GetServerName ()
227                 {
228                         return GetLocalAddress ();
229                 }
230
231                 public virtual string GetServerVariable (string name)
232                 {
233                         return null;
234                 }
235 #if NET_2_0
236                 public virtual int GetTotalEntityBodyLength ()
237                 {
238                         return 0;
239                 }
240 #endif
241                 public virtual string GetUnknownRequestHeader (string name)
242                 {
243                         return null;
244                 }
245
246                 [CLSCompliant (false)]
247                 public virtual string [][] GetUnknownRequestHeaders ()
248                 {
249                         return null;
250                 }
251
252                 public virtual IntPtr GetUserToken ()
253                 {
254                         return IntPtr.Zero;
255                 }
256
257                 public bool HasEntityBody ()
258                 {
259                         // TODO this is not virtual.
260                         
261                         return false;
262                 }
263
264                 public virtual bool HeadersSent ()
265                 {
266                         return true;
267                 }
268
269                 public virtual bool IsClientConnected ()
270                 {
271                         return true;
272                 }
273
274                 public virtual bool IsEntireEntityBodyIsPreloaded ()
275                 {
276                         return false;
277                 }
278
279                 public virtual bool IsSecure ()
280                 {
281                         return false;
282                 }
283
284                 public virtual string MapPath (string virtualPath)
285                 {
286                         return null;
287                 }
288
289                 public virtual int ReadEntityBody (byte [] buffer, int size)
290                 {
291                         return 0;
292                 }
293 #if NET_2_0
294                 public virtual int ReadEntityBody (byte [] buffer, int offset, int size)
295                 {
296                         return 0;
297                 }
298 #endif
299                 public virtual void SendCalculatedContentLength (int contentLength)
300                 {
301                         throw new NotImplementedException ();
302                 }
303
304 #if TARGET_JVM
305                 public virtual void SendResponseFromMemory (IntPtr data, int length)
306                 {
307                         throw new NotImplementedException("SendResponseFromMemory: unsafe buffers (IntPtr) are not supported");
308                 }
309 #else
310                 public virtual void SendResponseFromMemory (IntPtr data, int length)
311                 {
312                         if (data != IntPtr.Zero) {
313                                 byte [] copy = new byte [length];
314                                 Marshal.Copy (data, copy, 0, length);
315                                 SendResponseFromMemory (copy, length);
316                         }
317                 }
318 #endif
319
320                 public virtual void SetEndOfSendNotification (HttpWorkerRequest.EndOfSendNotification callback, object extraData)
321                 {
322                 }
323
324 #region Abstract methods
325                 public abstract void EndOfRequest ();
326                 public abstract void FlushResponse (bool finalFlush);
327                 public abstract string GetHttpVerbName ();
328                 public abstract string GetHttpVersion ();
329                 public abstract string GetLocalAddress ();
330                 public abstract int GetLocalPort ();
331                 public abstract string GetQueryString ();
332                 public abstract string GetRawUrl ();
333                 public abstract string GetRemoteAddress ();
334                 public abstract int GetRemotePort ();
335                 public abstract string GetUriPath ();
336                 public abstract void SendKnownResponseHeader (int index, string value);
337                 public abstract void SendResponseFromFile (IntPtr handle, long offset, long length);
338                 public abstract void SendResponseFromFile (string filename, long offset, long length);
339                 public abstract void SendResponseFromMemory (byte [] data, int length);
340                 public abstract void SendStatus (int statusCode, string statusDescription);
341                 public abstract void SendUnknownResponseHeader (string name, string value);
342 #endregion
343                 
344 #region Static methods
345                 
346                 public static int GetKnownRequestHeaderIndex (string header)
347                 {
348                         switch (header){
349                         case "Cache-Control": return HeaderCacheControl;
350                         case "Connection": return HeaderConnection;
351                         case "Date": return HeaderDate;
352                         case "Keep-Alive": return HeaderKeepAlive;
353                         case "Pragma": return HeaderPragma;
354                         case "Trailer": return HeaderTrailer;
355                         case "Transfer-Encoding": return HeaderTransferEncoding;
356                         case "Upgrade": return HeaderUpgrade;
357                         case "Via": return HeaderVia;
358                         case "Warning": return HeaderWarning;
359                         case "Allow": return HeaderAllow;
360                         case "Content-Length": return HeaderContentLength;
361                         case "Content-Type": return HeaderContentType;
362                         case "Content-Encoding": return HeaderContentEncoding;
363                         case "Content-Language": return HeaderContentLanguage;
364                         case "Content-Location": return HeaderContentLocation;
365                         case "Content-MD5": return HeaderContentMd5;
366                         case "Content-Range": return HeaderContentRange;
367                         case "Expires": return HeaderExpires;
368                         case "Last-Modified": return HeaderLastModified;
369                         case "Accept": return HeaderAccept;
370                         case "Accept-Charset": return HeaderAcceptCharset;
371                         case "Accept-Encoding": return HeaderAcceptEncoding;
372                         case "Accept-Language": return HeaderAcceptLanguage;
373                         case "Authorization": return HeaderAuthorization;
374                         case "Cookie": return HeaderCookie;
375                         case "Expect": return HeaderExpect;
376                         case "From": return HeaderFrom;
377                         case "Host": return HeaderHost;
378                         case "If-Match": return HeaderIfMatch;
379                         case "If-Modified-Since": return HeaderIfModifiedSince;
380                         case "If-None-Match": return HeaderIfNoneMatch;
381                         case "If-Range": return HeaderIfRange;
382                         case "If-Unmodified-Since": return HeaderIfUnmodifiedSince;
383                         case "Max-Forwards": return HeaderMaxForwards;
384                         case "Proxy-Authorization": return HeaderProxyAuthorization;
385                         case "Referer": return HeaderReferer;
386                         case "Range": return HeaderRange;
387                         case "TE": return HeaderTe;
388                         case "User-Agent": return HeaderUserAgent;
389                         }
390
391                         object index = RequestHeaderIndexer[header];
392                         if (index != null)
393                                 return (int)index;
394
395                         return -1;
396                 }
397
398                 public static string GetKnownRequestHeaderName (int index)
399                 {
400                         switch (index){
401                         case HeaderCacheControl: return "Cache-Control";
402                         case HeaderConnection: return "Connection";
403                         case HeaderDate: return "Date";
404                         case HeaderKeepAlive: return "Keep-Alive";
405                         case HeaderPragma: return "Pragma";
406                         case HeaderTrailer: return "Trailer";
407                         case HeaderTransferEncoding: return "Transfer-Encoding";
408                         case HeaderUpgrade: return "Upgrade";
409                         case HeaderVia: return "Via";
410                         case HeaderWarning: return "Warning";
411                         case HeaderAllow: return "Allow";
412                         case HeaderContentLength: return "Content-Length";
413                         case HeaderContentType: return "Content-Type";
414                         case HeaderContentEncoding: return "Content-Encoding";
415                         case HeaderContentLanguage: return "Content-Language";
416                         case HeaderContentLocation: return "Content-Location";
417                         case HeaderContentMd5: return "Content-MD5";
418                         case HeaderContentRange: return "Content-Range";
419                         case HeaderExpires: return "Expires";
420                         case HeaderLastModified: return "Last-Modified";
421                         case HeaderAccept: return "Accept";
422                         case HeaderAcceptCharset: return "Accept-Charset";
423                         case HeaderAcceptEncoding: return "Accept-Encoding";
424                         case HeaderAcceptLanguage: return "Accept-Language";
425                         case HeaderAuthorization: return "Authorization";
426                         case HeaderCookie: return "Cookie";
427                         case HeaderExpect: return "Expect";
428                         case HeaderFrom: return "From";
429                         case HeaderHost: return "Host";
430                         case HeaderIfMatch: return "If-Match";
431                         case HeaderIfModifiedSince: return "If-Modified-Since";
432                         case HeaderIfNoneMatch: return "If-None-Match";
433                         case HeaderIfRange: return "If-Range";
434                         case HeaderIfUnmodifiedSince: return "If-Unmodified-Since";
435                         case HeaderMaxForwards: return "Max-Forwards";
436                         case HeaderProxyAuthorization: return "Proxy-Authorization";
437                         case HeaderReferer: return "Referer";
438                         case HeaderRange: return "Range";
439                         case HeaderTe: return "TE";
440                         case HeaderUserAgent: return "User-Agent";
441                         }
442                         throw new IndexOutOfRangeException ("index");
443                                 
444                 }
445
446                 public static int GetKnownResponseHeaderIndex (string header)
447                 {
448                         switch (header){
449                         case "Cache-Control": return HeaderCacheControl;
450                         case "Connection": return HeaderConnection;
451                         case "Date": return HeaderDate;
452                         case "Keep-Alive": return HeaderKeepAlive;
453                         case "Pragma": return HeaderPragma;
454                         case "Trailer": return HeaderTrailer;
455                         case "Transfer-Encoding": return HeaderTransferEncoding;
456                         case "Upgrade": return HeaderUpgrade;
457                         case "Via": return HeaderVia;
458                         case "Warning": return HeaderWarning;
459                         case "Allow": return HeaderAllow;
460                         case "Content-Length": return HeaderContentLength;
461                         case "Content-Type": return HeaderContentType;
462                         case "Content-Encoding": return HeaderContentEncoding;
463                         case "Content-Language": return HeaderContentLanguage;
464                         case "Content-Location": return HeaderContentLocation;
465                         case "Content-MD5": return HeaderContentMd5;
466                         case "Content-Range": return HeaderContentRange;
467                         case "Expires": return HeaderExpires;
468                         case "Last-Modified": return HeaderLastModified;
469                         case "Accept-Ranges": return HeaderAcceptRanges;
470                         case "Age": return HeaderAge;
471                         case "ETag": return HeaderEtag;
472                         case "Location": return HeaderLocation;
473                         case "Proxy-Authenticate":return HeaderProxyAuthenticate;
474                         case "Retry-After": return HeaderRetryAfter;
475                         case "Server": return HeaderServer;
476                         case "Set-Cookie": return HeaderSetCookie;
477                         case "Vary": return HeaderVary;
478                         case "WWW-Authenticate": return HeaderWwwAuthenticate;
479                         }
480
481                         object index = ResponseHeaderIndexer[header];
482                         if (index != null)
483                                 return (int)index;
484
485                         return -1;
486                 }
487
488                 public static string GetKnownResponseHeaderName (int index)
489                 {
490                         switch (index){
491                         case HeaderCacheControl: return "Cache-Control";
492                         case HeaderConnection: return "Connection";
493                         case HeaderDate: return "Date";
494                         case HeaderKeepAlive: return "Keep-Alive";
495                         case HeaderPragma: return "Pragma";
496                         case HeaderTrailer: return "Trailer";
497                         case HeaderTransferEncoding: return "Transfer-Encoding";
498                         case HeaderUpgrade: return "Upgrade";
499                         case HeaderVia: return "Via";
500                         case HeaderWarning: return "Warning";
501                         case HeaderAllow: return "Allow";
502                         case HeaderContentLength: return "Content-Length";
503                         case HeaderContentType: return "Content-Type";
504                         case HeaderContentEncoding: return "Content-Encoding";
505                         case HeaderContentLanguage: return "Content-Language";
506                         case HeaderContentLocation: return "Content-Location";
507                         case HeaderContentMd5: return "Content-MD5";
508                         case HeaderContentRange: return "Content-Range";
509                         case HeaderExpires: return "Expires";
510                         case HeaderLastModified: return "Last-Modified";
511                         case HeaderAcceptRanges: return "Accept-Ranges";
512                         case HeaderAge: return "Age";
513                         case HeaderEtag: return "ETag";
514                         case HeaderLocation: return "Location";
515                         case HeaderProxyAuthenticate: return "Proxy-Authenticate";
516                         case HeaderRetryAfter: return "Retry-After";
517                         case HeaderServer: return "Server";
518                         case HeaderSetCookie: return "Set-Cookie";
519                         case HeaderVary: return "Vary";
520                         case HeaderWwwAuthenticate: return "WWW-Authenticate";
521                         }
522
523                         throw new IndexOutOfRangeException ("index");
524                 }
525                 
526                 public static string GetStatusDescription (int code)
527                 {
528                         switch (code){
529                         case 100: return "Continue";
530                         case 101: return "Switching Protocols";
531                         case 102: return "Processing";
532                         case 200: return "OK";
533                         case 201: return "Created";
534                         case 202: return "Accepted";
535                         case 203: return "Non-Authoritative Information";
536                         case 204: return "No Content";
537                         case 205: return "Reset Content";
538                         case 206: return "Partial Content";
539                         case 207: return "Multi-Status";
540                         case 300: return "Multiple Choices";
541                         case 301: return "Moved Permanently";
542                         case 302: return "Found";
543                         case 303: return "See Other";
544                         case 304: return "Not Modified";
545                         case 305: return "Use Proxy";
546                         case 307: return "Temporary Redirect";
547                         case 400: return "Bad Request";
548                         case 401: return "Unauthorized";
549                         case 402: return "Payment Required";
550                         case 403: return "Forbidden";
551                         case 404: return "Not Found";
552                         case 405: return "Method Not Allowed";
553                         case 406: return "Not Acceptable";
554                         case 407: return "Proxy Authentication Required";
555                         case 408: return "Request Timeout";
556                         case 409: return "Conflict";
557                         case 410: return "Gone";
558                         case 411: return "Length Required";
559                         case 412: return "Precondition Failed";
560                         case 413: return "Request Entity Too Large";
561                         case 414: return "Request-Uri Too Long";
562                         case 415: return "Unsupported Media Type";
563                         case 416: return "Requested Range Not Satisfiable";
564                         case 417: return "Expectation Failed";
565                         case 422: return "Unprocessable Entity";
566                         case 423: return "Locked";
567                         case 424: return "Failed Dependency";
568                         case 500: return "Internal Server Error";
569                         case 501: return "Not Implemented";
570                         case 502: return "Bad Gateway";
571                         case 503: return "Service Unavailable";
572                         case 504: return "Gateway Timeout";
573                         case 505: return "Http Version Not Supported";
574                         case 507: return "Insufficient Storage";
575                         }
576                         return "";
577                 }
578 #endregion
579
580 #region Internals
581                 //
582                 // These are exposed on the public API, but are for internal consumption
583                 //
584                 public virtual byte [] GetClientCertificate ()
585                 {
586                         return new byte [0];
587                 }
588                 
589                 public virtual byte [] GetClientCertificateBinaryIssuer ()
590                 {
591                         return new byte [0];
592                 }
593                 
594                 public virtual int GetClientCertificateEncoding  ()
595                 {
596                         return 0;
597                 }
598                 
599                 public virtual byte [] GetClientCertificatePublicKey ()
600                 {
601                         return new byte [0];
602                 }
603
604                 public virtual DateTime GetClientCertificateValidFrom ()
605                 {
606                         return DateTime.Now;
607                 }
608
609                 public virtual DateTime GetClientCertificateValidUntil ()
610                 {
611                         return DateTime.Now;
612                 }
613
614                 public virtual long GetConnectionID ()
615                 {
616                         return 0;
617                 }
618
619                 public virtual long GetUrlContextID ()
620                 {
621                         return 0;
622                 }
623
624                 public virtual IntPtr GetVirtualPathToken ()
625                 {
626                         return IntPtr.Zero;
627                 }
628 #endregion
629                 
630         }
631 }