2 // System.Web.HttpWorkerRequest
5 // Patrik Torstensson (Patrik.Torstensson@labs2.com)
6 // (constants from Bob Smith (bob@thestuff.net))
7 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
9 // (c) Patrik Torstensson
10 // (c) 2002 Ximian, Inc. (http://www.ximian.com)
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:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
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.
34 using System.Collections;
35 using System.Globalization;
36 using System.Runtime.InteropServices;
41 public abstract class HttpWorkerRequest : IHttpMapPath
43 public delegate void EndOfSendNotification (HttpWorkerRequest wr, object extraData);
45 public const int HeaderAccept = 20;
46 public const int HeaderAcceptCharset = 21;
47 public const int HeaderAcceptEncoding = 22;
48 public const int HeaderAcceptLanguage = 23;
49 public const int HeaderAcceptRanges = 20;
50 public const int HeaderAge = 21;
51 public const int HeaderAllow = 10;
52 public const int HeaderAuthorization = 24;
53 public const int HeaderCacheControl = 0;
54 public const int HeaderConnection = 1;
55 public const int HeaderContentEncoding = 13;
56 public const int HeaderContentLanguage = 14;
57 public const int HeaderContentLength = 11;
58 public const int HeaderContentLocation = 15;
59 public const int HeaderContentMd5 = 16;
60 public const int HeaderContentRange = 17;
61 public const int HeaderContentType = 12;
62 public const int HeaderCookie = 25;
63 public const int HeaderDate = 2;
64 public const int HeaderEtag = 22;
65 public const int HeaderExpect = 26;
66 public const int HeaderExpires = 18;
67 public const int HeaderFrom = 27;
68 public const int HeaderHost = 28;
69 public const int HeaderIfMatch = 29;
70 public const int HeaderIfModifiedSince = 30;
71 public const int HeaderIfNoneMatch = 31;
72 public const int HeaderIfRange = 32;
73 public const int HeaderIfUnmodifiedSince = 33;
74 public const int HeaderKeepAlive = 3;
75 public const int HeaderLastModified = 19;
76 public const int HeaderLocation = 23;
77 public const int HeaderMaxForwards = 34;
78 public const int HeaderPragma = 4;
79 public const int HeaderProxyAuthenticate = 24;
80 public const int HeaderProxyAuthorization = 35;
81 public const int HeaderRange = 37;
82 public const int HeaderReferer = 36;
83 public const int HeaderRetryAfter = 25;
84 public const int HeaderServer = 26;
85 public const int HeaderSetCookie = 27;
86 public const int HeaderTe = 38;
87 public const int HeaderTrailer = 5;
88 public const int HeaderTransferEncoding = 6;
89 public const int HeaderUpgrade = 7;
90 public const int HeaderUserAgent = 39;
91 public const int HeaderVary = 28;
92 public const int HeaderVia = 8;
93 public const int HeaderWarning = 9;
94 public const int HeaderWwwAuthenticate = 29;
95 public const int ReasonCachePolicy = 2;
96 public const int ReasonCacheSecurity = 3;
97 public const int ReasonClientDisconnect = 4;
98 public const int ReasonDefault = 0;
99 public const int ReasonFileHandleCacheMiss = 1;
100 public const int ReasonResponseCacheMiss = 0;
101 public const int RequestHeaderMaximum = 40;
102 public const int ResponseHeaderMaximum = 30;
104 static string [][] s_HttpStatusDescriptions;
105 static string [] s_HttpRequestHeaderNames;
106 static string [] s_HttpResponseHeaderNames;
108 static Hashtable s_HttpResponseHeadersTable;
109 static Hashtable s_HttpRequestHeaderTable;
111 static HttpWorkerRequest ()
115 s_HttpStatusDescriptions = new string [6][];
117 sSubCodes = new String [3];
118 sSubCodes [0] = "Continue";
119 sSubCodes [1] = "Switching Protocols";
120 sSubCodes [2] = "Processing";
121 s_HttpStatusDescriptions [1] = sSubCodes;
123 sSubCodes = new String [8];
124 sSubCodes [0] = "OK";
125 sSubCodes [1] = "Created";
126 sSubCodes [2] = "Accepted";
127 sSubCodes [3] = "Non-Authoritative Information";
128 sSubCodes [4] = "No Content";
129 sSubCodes [5] = "Reset Content";
130 sSubCodes [6] = "Partial Content";
131 sSubCodes [7] = "Multi-Status";
132 s_HttpStatusDescriptions [2] = sSubCodes;
134 sSubCodes = new String [8];
135 sSubCodes [0] = "Multiple Choices";
136 sSubCodes [1] = "Moved Permanently";
137 sSubCodes [2] = "Found";
138 sSubCodes [3] = "See Other";
139 sSubCodes [4] = "Not Modified";
140 sSubCodes [5] = "Use Proxy";
141 sSubCodes [6] = String.Empty;
142 sSubCodes [7] = "Temporary Redirect";
143 s_HttpStatusDescriptions [3] = sSubCodes;
145 sSubCodes = new String [24];
146 sSubCodes [0] = "Bad Request";
147 sSubCodes [1] = "Unauthorized";
148 sSubCodes [2] = "Payment Required";
149 sSubCodes [3] = "Forbidden";
150 sSubCodes [4] = "Not Found";
151 sSubCodes [5] = "Method Not Allowed";
152 sSubCodes [6] = "Not Acceptable";
153 sSubCodes [7] = "Proxy Authentication Required";
154 sSubCodes [8] = "Request Timeout";
155 sSubCodes [9] = "Conflict";
156 sSubCodes [10] = "Gone";
157 sSubCodes [11] = "Length Required";
158 sSubCodes [12] = "Precondition Failed";
159 sSubCodes [13] = "Request Entity Too Large";
160 sSubCodes [14] = "Request-Uri Too Long";
161 sSubCodes [15] = "Unsupported Media Type";
162 sSubCodes [16] = "Requested Range Not Satisfiable";
163 sSubCodes [17] = "Expectation Failed";
164 sSubCodes [18] = String.Empty;
165 sSubCodes [19] = String.Empty;
166 sSubCodes [20] = String.Empty;
167 sSubCodes [21] = "Unprocessable Entity";
168 sSubCodes [22] = "Locked";
169 sSubCodes [23] = "Failed Dependency";
170 s_HttpStatusDescriptions [4] = sSubCodes;
172 sSubCodes = new String [8];
173 sSubCodes [0] = "Internal Server Error";
174 sSubCodes [1] = "Not Implemented";
175 sSubCodes [2] = "Bad Gateway";
176 sSubCodes [3] = "Service Unavailable";
177 sSubCodes [4] = "Gateway Timeout";
178 sSubCodes [5] = "Http Version Not Supported";
179 sSubCodes [6] = String.Empty;
180 sSubCodes [7] = "Insufficient Storage";
181 s_HttpStatusDescriptions [5] = sSubCodes;
186 public HttpWorkerRequest ()
190 static private void InitLookupTables ()
192 // Performance arrays
193 s_HttpRequestHeaderNames = new string [40];
194 s_HttpResponseHeaderNames = new string [30];
196 // Lookup tables (name -> id)
197 CaseInsensitiveHashCodeProvider hprovider;
198 hprovider = new CaseInsensitiveHashCodeProvider (CultureInfo.InvariantCulture);
199 CaseInsensitiveComparer hcomparer;
200 hcomparer = new CaseInsensitiveComparer (CultureInfo.InvariantCulture);
201 s_HttpRequestHeaderTable = new Hashtable (hprovider, hcomparer);
202 s_HttpResponseHeadersTable = new Hashtable (hprovider, hcomparer);
204 AddHeader (true, true, 0, "Cache-Control");
205 AddHeader (true, true, 1, "Connection");
206 AddHeader (true, true, 2, "Date");
207 AddHeader (true, true, 3, "Keep-Alive");
208 AddHeader (true, true, 4, "Pragma");
209 AddHeader (true, true, 5, "Trailer");
210 AddHeader (true, true, 6, "Transfer-Encoding");
211 AddHeader (true, true, 7, "Upgrade");
212 AddHeader (true, true, 8, "Via");
213 AddHeader (true, true, 9, "Warning");
214 AddHeader (true, true, 10, "Allow");
215 AddHeader (true, true, 11, "Content-Length");
216 AddHeader (true, true, 12, "Content-Type");
217 AddHeader (true, true, 13, "Content-Encoding");
218 AddHeader (true, true, 14, "Content-Language");
219 AddHeader (true, true, 15, "Content-Location");
220 AddHeader (true, true, 16, "Content-MD5");
221 AddHeader (true, true, 17, "Content-Range");
222 AddHeader (true, true, 18, "Expires");
223 AddHeader (true, true, 19, "Last-Modified");
224 AddHeader (true, false, 20, "Accept");
225 AddHeader (true, false, 21, "Accept-Charset");
226 AddHeader (true, false, 22, "Accept-Encoding");
227 AddHeader (true, false, 23, "Accept-Language");
228 AddHeader (true, false, 24, "Authorization");
229 AddHeader (true, false, 25, "Cookie");
230 AddHeader (true, false, 26, "Expect");
231 AddHeader (true, false, 27, "From");
232 AddHeader (true, false, 28, "Host");
233 AddHeader (true, false, 29, "If-Match");
234 AddHeader (true, false, 30, "If-Modified-Since");
235 AddHeader (true, false, 31, "If-None-Match");
236 AddHeader (true, false, 32, "If-Range");
237 AddHeader (true, false, 33, "If-Unmodified-Since");
238 AddHeader (true, false, 34, "Max-Forwards");
239 AddHeader (true, false, 35, "Proxy-Authorization");
240 AddHeader (true, false, 36, "Referer");
241 AddHeader (true, false, 37, "Range");
242 AddHeader (true, false, 38, "TE");
243 AddHeader (true, false, 39, "User-Agent");
244 AddHeader (false, true, 20, "Accept-Ranges");
245 AddHeader (false, true, 21, "Age");
246 AddHeader (false, true, 22, "ETag");
247 AddHeader (false, true, 23, "Location");
248 AddHeader (false, true, 24, "Proxy-Authenticate");
249 AddHeader (false, true, 25, "Retry-After");
250 AddHeader (false, true, 26, "Server");
251 AddHeader (false, true, 27, "Set-Cookie");
252 AddHeader (false, true, 28, "Vary");
253 AddHeader (false, true, 29, "WWW-Authenticate");
256 static private void AddHeader(bool bRequest, bool bResponse, int iID, string sHeader)
259 s_HttpResponseHeaderNames [iID] = sHeader;
260 s_HttpResponseHeadersTable.Add (sHeader, iID);
264 s_HttpRequestHeaderNames [iID] = sHeader;
265 s_HttpRequestHeaderTable.Add (sHeader, iID);
269 public virtual void CloseConnection ()
273 public abstract void EndOfRequest ();
274 public abstract void FlushResponse (bool finalFlush);
276 public virtual string GetAppPath ()
281 public virtual string GetAppPathTranslated ()
286 public virtual string GetAppPoolID ()
291 public virtual long GetBytesRead ()
296 public virtual byte[] GetClientCertificate ()
301 public virtual byte[] GetClientCertificateBinaryIssuer ()
306 public virtual int GetClientCertificateEncoding ()
311 public virtual byte[] GetClientCertificatePublicKey ()
316 public virtual DateTime GetClientCertificateValidFrom ()
321 public virtual DateTime GetClientCertificateValidUntil ()
326 public virtual long GetConnectionID ()
331 public virtual string GetFilePath ()
336 public virtual string GetFilePathTranslated ()
341 public abstract string GetHttpVerbName ();
342 public abstract string GetHttpVersion ();
344 public virtual string GetKnownRequestHeader (int index)
349 public static int GetKnownRequestHeaderIndex (string header)
352 index = s_HttpRequestHeaderTable [header];
354 return (Int32) index;
359 public static string GetKnownRequestHeaderName (int index)
361 return s_HttpRequestHeaderNames [index];
364 public static int GetKnownResponseHeaderIndex (string header)
368 index = s_HttpResponseHeadersTable [header];
370 return (Int32) index;
375 public static string GetKnownResponseHeaderName(int index)
377 return s_HttpResponseHeaderNames [index];
380 public abstract string GetLocalAddress ();
381 public abstract int GetLocalPort ();
383 public virtual string GetPathInfo ()
388 public virtual byte [] GetPreloadedEntityBody ()
393 public virtual string GetProtocol ()
395 return (IsSecure ()) ? "https" : "http";
398 public abstract string GetQueryString ();
400 public virtual byte[] GetQueryStringRawBytes ()
405 public abstract string GetRawUrl ();
406 public abstract string GetRemoteAddress ();
408 public virtual string GetRemoteName ()
410 return GetRemoteAddress();
413 public abstract int GetRemotePort ();
415 public virtual int GetRequestReason ()
420 public virtual string GetServerName ()
422 return GetLocalAddress();
425 public virtual string GetServerVariable (string name)
430 public static string GetStatusDescription (int code)
432 if (code>= 100 && code < 600) {
433 int iMajor = code / 100;
434 int iMinor = code % 100;
435 if (iMinor < (int) s_HttpStatusDescriptions [iMajor].Length)
436 return s_HttpStatusDescriptions [iMajor][iMinor];
442 public virtual string GetUnknownRequestHeader (string name)
447 [CLSCompliant(false)]
448 public virtual string [][] GetUnknownRequestHeaders ()
453 public abstract string GetUriPath ();
455 public virtual long GetUrlContextID ()
460 public virtual IntPtr GetUserToken ()
462 throw new NotSupportedException ();
465 public virtual IntPtr GetVirtualPathToken ()
467 throw new NotSupportedException ();
470 public bool HasEntityBody ()
472 string sContentLength = GetKnownRequestHeader (HeaderContentLength);
473 if (null != sContentLength && sContentLength != "0")
476 if (null != GetKnownRequestHeader (HeaderTransferEncoding))
479 if (null != GetPreloadedEntityBody () || IsEntireEntityBodyIsPreloaded ())
485 public virtual bool HeadersSent ()
490 public virtual bool IsClientConnected ()
495 public virtual bool IsEntireEntityBodyIsPreloaded ()
500 public virtual bool IsSecure ()
505 public virtual string MapPath (string virtualPath)
510 public virtual int ReadEntityBody (byte[] buffer, int size)
515 public virtual void SendCalculatedContentLength (int contentLength)
519 public abstract void SendKnownResponseHeader (int index, string value);
520 public abstract void SendResponseFromFile (IntPtr handle, long offset, long length);
521 public abstract void SendResponseFromFile (string filename, long offset, long length);
522 public abstract void SendResponseFromMemory (byte [] data, int length);
524 public virtual void SendResponseFromMemory (IntPtr data, int length)
529 byte [] dataBytes = new byte [length];
530 Marshal.Copy (data, dataBytes, 0, length);
531 SendResponseFromMemory (dataBytes, length);
534 public abstract void SendStatus (int statusCode, string statusDescription);
535 public abstract void SendUnknownResponseHeader (string name, string value);
537 public virtual void SetEndOfSendNotification (EndOfSendNotification callback, object extraData)
541 public virtual string MachineConfigPath
548 public virtual string MachineInstallDirectory