merged Sys.Web.Services 2.0 support in my branch:
[mono.git] / mcs / class / Mainsoft.Web / Mainsoft.Web.Hosting / ServletWorkerRequest.jvm.cs
1 //
2 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
3 //
4
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 //
25 using System;
26 using System.IO;
27 using System.Text;
28 using System.Runtime.InteropServices;
29 using System.Web.Util;
30 using vmw.common;
31 using System.Web.J2EE;
32 using System.Collections;
33 using System.Web;
34 using javax.servlet;
35 using javax.servlet.http;
36 using System.Collections.Specialized;
37 using System.Globalization;
38 using System.Web.Hosting;
39
40 namespace Mainsoft.Web.Hosting {
41         [MonoTODO("Implement security demands on the path usage functions (and review)")]
42         [ComVisible (false)]
43         internal sealed class ServletWorkerRequest : HttpWorkerRequest {
44                 readonly HttpServlet _HttpServlet;
45                 readonly HttpServletRequest _HttpServletRequest;
46                 readonly HttpServletResponse _HttpServletResponse;
47
48                 readonly string _requestUri;
49                 readonly string _pathInfo;
50
51                 static readonly StringDictionary _srvVarsToHeaderMap;
52
53                 private string [][] unknownHeaders;
54                 string _rawUrl;
55
56                 private HttpWorkerRequest.EndOfSendNotification _endOfSendCallback;
57                 private object _endOfSendArgs;
58
59                 enum KnownServerVariable {
60                         AUTH_TYPE,
61                         CONTENT_LENGTH,
62                         CONTENT_TYPE,
63                         QUERY_STRING,
64                         REMOTE_ADDR,
65                         REMOTE_HOST,
66                         REMOTE_USER,
67                         REQUEST_METHOD,
68                         REQUEST_URI,
69                         SCRIPT_NAME,
70                         SERVER_NAME,
71                         SERVER_PORT,
72                         SERVER_PROTOCOL,
73                         SERVER_SOFTWARE,
74                         PATH_INFO
75                 };
76
77                 static readonly Hashtable KnownServerVariableMap;
78
79                 static ServletWorkerRequest() {
80                         _srvVarsToHeaderMap = new StringDictionary();
81                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT", "Accept");
82                         _srvVarsToHeaderMap.Add("HTTP_REFERER", "Referer");
83                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT_LANGUAGE", "Accept-Language");
84                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT_ENCODING", "Accept-Encoding");
85                         _srvVarsToHeaderMap.Add("HTTP_CONNECTION", "Connection");
86                         _srvVarsToHeaderMap.Add("HTTP_HOST", "Host");
87                         _srvVarsToHeaderMap.Add("HTTP_USER_AGENT", "User-Agent");
88                         _srvVarsToHeaderMap.Add("HTTP_SOAPACTION", "SOAPAction");
89
90                         string[] knownServerVariableNames = Enum.GetNames(typeof(KnownServerVariable));
91                         KnownServerVariableMap = CollectionsUtil.CreateCaseInsensitiveHashtable(knownServerVariableNames.Length);
92                         for (int i = 0; i < knownServerVariableNames.Length; i++)
93                                 KnownServerVariableMap[knownServerVariableNames[i]] = (KnownServerVariable)i;
94                 }
95
96                 public ServletWorkerRequest (HttpServlet servlet, HttpServletRequest req, HttpServletResponse resp) {
97                         _HttpServlet = servlet;
98                         _HttpServletRequest = req;
99                         _HttpServletResponse = resp;
100
101                         string contextPath = req.getContextPath();
102                         string requestURI = req.getRequestURI();
103                         if (String.CompareOrdinal(requestURI, contextPath) == 0 ||
104                                 (((requestURI.Length - contextPath.Length) == 1) &&
105                                         requestURI[contextPath.Length] == '/' &&
106                                         String.CompareOrdinal(requestURI, 0, contextPath, 0, contextPath.Length) == 0 ))
107                                 requestURI = contextPath + req.getServletPath();        
108
109                         _requestUri = Uri.UnescapeDataString(requestURI);
110                         const int dotInvokeLength = 7; //".invoke".Length
111                         if (_requestUri.Length > dotInvokeLength &&
112                                 String.CompareOrdinal(".invoke", 0, _requestUri, 
113                                 _requestUri.Length - dotInvokeLength, dotInvokeLength) == 0) {
114
115                                 _requestUri = _requestUri.Substring(0, _requestUri.Length - dotInvokeLength);
116                                 
117                                 int paramNameStart = _requestUri.LastIndexOf('/');
118                                 _pathInfo = _requestUri.Substring(paramNameStart, _requestUri.Length - paramNameStart);
119                         }
120                 }
121
122                 public HttpServlet Servlet {
123                         get {
124                                 return _HttpServlet;
125                         }
126                 }
127                 
128                 public HttpServletRequest ServletRequest {
129                         get{
130                                 return _HttpServletRequest;
131                         }
132                 }
133
134                 public HttpServletResponse ServletResponse {
135                         get{
136                                 return _HttpServletResponse;
137                         }
138                 }
139                 
140                 [MonoTODO("Implement security")]
141                 public override string MachineInstallDirectory {
142                         get {
143                                 return ".";
144                         }
145                 }
146
147                 public override string MachineConfigPath {
148                         get { return "."; }
149                 }
150
151                 public override void EndOfRequest () {
152                         if (_endOfSendCallback != null)
153                                 _endOfSendCallback(this, _endOfSendArgs);
154                 }
155
156                 public override void FlushResponse (bool finalFlush) {
157                         ServletOutputStream servletOutputStream = _HttpServletResponse.getOutputStream();
158                         servletOutputStream.flush();
159                         if (finalFlush)
160                                 servletOutputStream.close();
161                 }
162
163                 public override string GetAppPath () {
164                         return _HttpServletRequest.getContextPath();
165                 }
166                 public override string GetAppPathTranslated () {
167                         return J2EEUtils.GetApplicationRealPath(_HttpServlet.getServletConfig());;
168                 }
169
170                 public override string GetFilePath () {
171                         string uri = GetUriPath();
172                         string pathInfo = GetPathInfo();
173                         if (pathInfo != null && pathInfo.Length > 0)
174                                 uri = uri.Substring(0, uri.Length - pathInfo.Length);
175
176                         return uri;
177                 }
178
179                 public override string GetFilePathTranslated () {
180                         string page = GetFilePath ();
181
182                         if (Path.DirectorySeparatorChar != '/')
183                                 page = page.Replace ('/', Path.DirectorySeparatorChar);
184
185                         if (page [0] == Path.DirectorySeparatorChar)
186                                 page = page.Substring (1);
187                         
188                         return Path.Combine (GetAppPathTranslated (), page);
189                 }
190
191                 public override string GetHttpVerbName () {
192                         return _HttpServletRequest.getMethod();
193                 }
194
195                 public override string GetHttpVersion () {
196                         return _HttpServletRequest.getProtocol();
197                 }
198
199                 public override string GetLocalAddress () {
200                         return _HttpServletRequest.getLocalAddr();
201                 }
202
203                 public override int GetLocalPort () {
204                         return _HttpServletRequest.getLocalPort();
205                 }
206
207                 public override string GetPathInfo () {
208                         string pathInfo = _pathInfo != null ? _pathInfo : _HttpServletRequest.getPathInfo();
209                         return pathInfo != null ? pathInfo : String.Empty;
210                 }
211
212                 public override string GetQueryString () {
213                         return _HttpServletRequest.getQueryString();
214                 }
215
216                 public override string GetRawUrl () {
217                         if (_rawUrl == null) {
218                                 StringBuilder builder = new StringBuilder();
219                                 builder.Append(GetUriPath());
220                                 string pathInfo = GetPathInfo();
221                                 string query = GetQueryString();
222                                 if (query != null && query.Length > 0) {
223                                         builder.Append('?');
224                                         builder.Append(query);
225                                 }
226
227                                 _rawUrl = builder.ToString();
228                         }
229
230                         return _rawUrl;
231                 }
232
233                 public override string GetRemoteAddress() {
234                         return _HttpServletRequest.getRemoteAddr();
235                 }
236
237                 public override string GetRemoteName() {
238                         return _HttpServletRequest.getRemoteHost();
239                 }
240
241
242                 public override int GetRemotePort() {
243                         try {
244                                 return _HttpServletRequest.getRemotePort();
245                         }
246                         catch(Exception e) { //should catch also java.lang.Throwable
247                                 //if servlet API is 2.3 and below - there is no
248                                 //method getRemotePort in ServletRequest interface...
249                                 //should be described as limitation.
250                                 return 0;
251                         }
252                 }
253
254                 public override string GetServerVariable(string name) {
255                         // FIXME: We need to make a proper mapping between the standard server
256                         // variables and java equivalent. probably we have to have a configuration file 
257                         // which associates between the two. Pay a special attention on GetUnknownRequestHeader/s
258                         // while implementing. Ensure that system web "common" code correctly calls each method.
259
260                         string headerName = _srvVarsToHeaderMap[name];
261
262                         if (headerName != null)
263                                 return _HttpServletRequest.getHeader( headerName );
264
265                         object knownVariable = KnownServerVariableMap[name];
266                         if (knownVariable != null)
267                                 return GetKnownServerVariable((KnownServerVariable)knownVariable);
268
269                         return _HttpServletRequest.getHeader( name );
270                 }
271
272                 string GetKnownServerVariable(KnownServerVariable index) {
273                         switch (index) {
274                                 case KnownServerVariable.AUTH_TYPE : return _HttpServletRequest.getAuthType();
275                                 case KnownServerVariable.CONTENT_LENGTH : return Convert.ToString(_HttpServletRequest.getContentLength());
276                                 case KnownServerVariable.CONTENT_TYPE : return _HttpServletRequest.getContentType();
277                                 case KnownServerVariable.QUERY_STRING : return GetQueryString();
278                                 case KnownServerVariable.REMOTE_ADDR : return GetRemoteAddress();
279                                 case KnownServerVariable.REMOTE_HOST : return GetRemoteName();
280                                 case KnownServerVariable.REMOTE_USER : return _HttpServletRequest.getRemoteUser();
281                                 case KnownServerVariable.REQUEST_METHOD : return GetHttpVerbName ();
282                                 case KnownServerVariable.REQUEST_URI : return GetUriPath();
283                                 case KnownServerVariable.SCRIPT_NAME : return GetFilePath ();
284                                 case KnownServerVariable.SERVER_NAME : return GetServerName();
285                                 case KnownServerVariable.SERVER_PORT : return Convert.ToString(_HttpServletRequest.getServerPort());
286                                 case KnownServerVariable.SERVER_PROTOCOL : return GetHttpVersion ();
287                                 case KnownServerVariable.SERVER_SOFTWARE : return Servlet.getServletContext().getServerInfo();
288                                 case KnownServerVariable.PATH_INFO : return GetPathInfo();
289                                 default: throw new IndexOutOfRangeException("index");
290                         }
291                 }
292
293                 public override string GetUriPath() {
294                         return _requestUri;
295                 }
296
297                 public override IntPtr GetUserToken() {
298                         return IntPtr.Zero;
299                 }
300
301                 public override string MapPath (string path) {
302                         string appVirtualPath = GetAppPath();
303                         if (path.StartsWith(appVirtualPath)) {
304                                 path = path.Remove(0,appVirtualPath.Length);
305                                 if (path.StartsWith("/"))
306                                         path = path.Remove(0,1);
307                         }
308                         //string realPath = Servlet.getServletContext().getRealPath(path);
309                         //                      if (Path.IsPathRooted(path))
310                         //                              return path;
311                         //                      if (!path.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL)&& 
312                         //                              !path.StartsWith("/") && !path.StartsWith("\\")&& !Path.IsPathRooted(path))            
313                         //                              return IAppDomainConfig.WAR_ROOT_SYMBOL + "/" + path;
314                         //                      else if (!path.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL)&& !Path.IsPathRooted(path))
315                         //                              return IAppDomainConfig.WAR_ROOT_SYMBOL + path;
316                         //                      else 
317                         //                              return path;
318
319                         if (path.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL)) {
320                                 return path;
321                         }
322
323                         string retVal =  IAppDomainConfig.WAR_ROOT_SYMBOL;
324
325                         if (!path.StartsWith("/") && !path.StartsWith("\\"))
326                                 retVal += "/";
327
328                         retVal += path;
329
330                         return retVal;
331                 }
332
333                 public override void SendResponseFromFile (IntPtr handle, long offset, long length) {
334                         throw new NotSupportedException();
335                 }
336
337                 public override void SendResponseFromFile (string filename, long offset, long length) {
338                         using (FileStream fs = File.OpenRead (filename)) {
339                                 byte [] buffer = new byte [4 * 1024];
340
341                                 if (offset != 0)
342                                         fs.Position = offset;
343
344                                 long remain = length;
345                                 int n;
346                                 while (remain > 0 && (n = fs.Read (buffer, 0, (int) Math.Min (remain, buffer.Length))) != 0){
347                                         remain -= n;
348                                         SendResponseFromMemory(buffer, n);
349                                 }
350                         }
351                 }
352
353                 public override void SendResponseFromMemory (byte [] data, int length) {
354                         sbyte [] sdata = vmw.common.TypeUtils.ToSByteArray(data);
355                         _HttpServletResponse.getOutputStream().write(sdata, 0 , length);
356                 }
357
358                 public override void SendStatus(int statusCode, string statusDescription) {
359                         // setStatus(int, string) is deprecated
360                         _HttpServletResponse.setStatus(statusCode/*, statusDescription*/);
361                 }
362
363                 public override void SendUnknownResponseHeader(string name, string value) {
364                         if (HeadersSent ())
365                                 return;
366
367                         _HttpServletResponse.addHeader(name, value);
368                 }
369
370                 public override bool HeadersSent () {
371                         return _HttpServletResponse.isCommitted();
372                 }
373
374                 public override void SendCalculatedContentLength (int contentLength) {
375                         _HttpServletResponse.setContentLength(contentLength);
376                 }
377
378                 public override void SendKnownResponseHeader (int index, string value) {
379                         SendUnknownResponseHeader (GetKnownResponseHeaderName (index), value);
380                 }
381
382                 public override string GetKnownRequestHeader (int index) {      
383                         return GetUnknownRequestHeader(GetKnownRequestHeaderName (index));
384                 }
385
386                 public override string GetUnknownRequestHeader (string name) {
387                         return _HttpServletRequest.getHeader(name);
388                 }
389
390                 public override string [][] GetUnknownRequestHeaders () {
391                         if (unknownHeaders == null) {
392                                 ArrayList pairs = new ArrayList ();
393                                 for (java.util.Enumeration he = _HttpServletRequest.getHeaderNames(); he.hasMoreElements() ;) {
394                                         string key = (string) he.nextElement();
395                                         int index = HttpWorkerRequest.GetKnownRequestHeaderIndex (key);
396                                         if (index != -1)
397                                                 continue;
398                                         pairs.Add (new string [] {key, _HttpServletRequest.getHeader(key)});
399                                 }
400                                 
401                                 if (pairs.Count != 0) {
402                                         unknownHeaders = new string [pairs.Count][];
403                                         for (int i = 0; i < pairs.Count; i++)
404                                                 unknownHeaders [i] = (string []) pairs [i];
405                                 }
406                         }
407                         if (unknownHeaders == null) unknownHeaders = new string [0][];
408
409                         return unknownHeaders;
410                 }
411
412                 public override int ReadEntityBody (byte [] buffer, int size) {
413                         if (buffer == null || size == 0)
414                                 return 0;
415                         sbyte [] sbuffer = vmw.common.TypeUtils.ToSByteArray(buffer);
416                         int r = _HttpServletRequest.getInputStream().read(sbuffer, 0, size);    
417                         return (r==-1)?0:r;
418                 }
419
420                 public override void SetEndOfSendNotification(System.Web.HttpWorkerRequest.EndOfSendNotification callback, object extraData) {
421                         _endOfSendCallback = callback;
422                         _endOfSendArgs = extraData;
423                 }
424
425                 public override string GetProtocol() {
426                         return _HttpServletRequest.getScheme();
427                 }
428
429                 public override string GetServerName() {
430                         return _HttpServletRequest.getServerName();
431                 }
432
433                 public override bool IsSecure() {
434                         return _HttpServletRequest.isSecure();
435                 }
436         }
437 }
438