convert .invoke requests to PathInfo, remove ToUpper usage
[mono.git] / mcs / class / System.Web / System.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
39 namespace System.Web.Hosting {
40         [MonoTODO("Implement security demands on the path usage functions (and review)")]
41         [ComVisible (false)]
42         internal sealed class ServletWorkerRequest : HttpWorkerRequest {
43                 readonly HttpServlet _HttpServlet;
44                 readonly HttpServletRequest _HttpServletRequest;
45                 readonly HttpServletResponse _HttpServletResponse;
46
47                 readonly string _requestUri;
48                 readonly string _pathInfo;
49
50                 static readonly StringDictionary _srvVarsToHeaderMap;
51
52                 private string [][] unknownHeaders;
53                 string _rawUrl;
54
55                 private HttpWorkerRequest.EndOfSendNotification _endOfSendCallback;
56                 private object _endOfSendArgs;
57
58                 enum KnownServerVariable {
59                         AUTH_TYPE,
60                         CONTENT_LENGTH,
61                         CONTENT_TYPE,
62                         QUERY_STRING,
63                         REMOTE_ADDR,
64                         REMOTE_HOST,
65                         REMOTE_USER,
66                         REQUEST_METHOD,
67                         REQUEST_URI,
68                         SCRIPT_NAME,
69                         SERVER_NAME,
70                         SERVER_PORT,
71                         SERVER_PROTOCOL,
72                         SERVER_SOFTWARE,
73                         PATH_INFO
74                 };
75
76                 static readonly string[] KnownServerVariableNames = Enum.GetNames(typeof(KnownServerVariable));
77
78                 static ServletWorkerRequest() {
79                         _srvVarsToHeaderMap = new StringDictionary();
80                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT", "Accept");
81                         _srvVarsToHeaderMap.Add("HTTP_REFERER", "Referer");
82                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT_LANGUAGE", "Accept-Language");
83                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT_ENCODING", "Accept-Encoding");
84                         _srvVarsToHeaderMap.Add("HTTP_CONNECTION", "Connection");
85                         _srvVarsToHeaderMap.Add("HTTP_HOST", "Host");
86                         _srvVarsToHeaderMap.Add("HTTP_USER_AGENT", "User-Agent");
87                         _srvVarsToHeaderMap.Add("HTTP_SOAPACTION", "SOAPAction");
88                 }
89
90                 public ServletWorkerRequest (HttpServlet servlet, HttpServletRequest req, HttpServletResponse resp) {
91                         _HttpServlet = servlet;
92                         _HttpServletRequest = req;
93                         _HttpServletResponse = resp;
94
95                         string requestUri = req.getRequestURI();
96                         const int dotInvokeLength = 7; //".invoke".Length
97                         if (requestUri.Length > dotInvokeLength &&
98                                 String.CompareOrdinal(".invoke", 0, requestUri, 
99                                 requestUri.Length - dotInvokeLength, dotInvokeLength) == 0) {
100                                 
101                                 _requestUri = requestUri.Substring(0, requestUri.Length - dotInvokeLength);
102
103                                 int paramNameStart = requestUri.LastIndexOf('/');
104                                 _pathInfo = requestUri.Substring(paramNameStart,
105                                         requestUri.Length - paramNameStart - dotInvokeLength);
106                         }
107                 }
108
109                 public HttpServlet Servlet {
110                         get {
111                                 return _HttpServlet;
112                         }
113                 }
114                 
115                 public HttpServletRequest ServletRequest {
116                         get{
117                                 return _HttpServletRequest;
118                         }
119                 }
120
121                 public HttpServletResponse ServletResponse {
122                         get{
123                                 return _HttpServletResponse;
124                         }
125                 }
126                 
127                 [MonoTODO("Implement security")]
128                 public override string MachineInstallDirectory {
129                         get {
130                                 return ICalls.GetMachineInstallDirectory ();
131                         }
132                 }
133
134                 public override string MachineConfigPath {
135                         get { return ICalls.GetMachineConfigPath (); }
136                 }
137
138                 public override void EndOfRequest () {
139                         if (_endOfSendCallback != null)
140                                 _endOfSendCallback(this, _endOfSendArgs);
141                 }
142
143                 public override void FlushResponse (bool finalFlush) {
144                         ServletOutputStream servletOutputStream = _HttpServletResponse.getOutputStream();
145                         servletOutputStream.flush();
146                         if (finalFlush)
147                                 servletOutputStream.close();
148                 }
149
150                 public override string GetAppPath () {
151                         return _HttpServletRequest.getContextPath();
152                 }
153
154                 public override string GetAppPathTranslated () {
155                         return J2EEUtils.GetApplicationRealPath(_HttpServlet.getServletConfig());;
156                 }
157
158                 public override string GetFilePath () {
159                         string uri = GetUriPath();
160                         string pathInfo = GetPathInfo();
161                         if (pathInfo != null && pathInfo.Length > 0)
162                                 uri = uri.Substring(0, uri.Length - pathInfo.Length);
163
164                         return uri;
165                 }
166
167                 public override string GetFilePathTranslated () {
168                         string page = GetFilePath ();
169
170                         if (Path.DirectorySeparatorChar != '/')
171                                 page = page.Replace ('/', Path.DirectorySeparatorChar);
172
173                         if (page [0] == Path.DirectorySeparatorChar)
174                                 page = page.Substring (1);
175                         
176                         return Path.Combine (GetAppPathTranslated (), page);
177                 }
178
179                 public override string GetHttpVerbName () {
180                         return _HttpServletRequest.getMethod();
181                 }
182
183                 public override string GetHttpVersion () {
184                         return _HttpServletRequest.getProtocol();
185                 }
186
187                 public override string GetLocalAddress () {
188                         return _HttpServletRequest.getLocalAddr();
189                 }
190
191                 public override int GetLocalPort () {
192                         return _HttpServletRequest.getLocalPort();
193                 }
194
195                 public override string GetPathInfo () {
196                         return _pathInfo != null ? _pathInfo : _HttpServletRequest.getPathInfo();
197                 }
198
199                 public override string GetQueryString () {
200                         return _HttpServletRequest.getQueryString();
201                 }
202
203                 public override string GetRawUrl () {
204                         if (_rawUrl == null) {
205                                 StringBuilder builder = new StringBuilder();
206                                 builder.Append(GetProtocol());
207                                 builder.Append("://");
208                                 builder.Append(GetServerName());
209                                 int port = _HttpServletRequest.getServerPort();
210                                 if (port != 80) {
211                                         builder.Append(':');
212                                         builder.Append(port);
213                                 }
214                                 builder.Append(GetUriPath());
215                                 string pathInfo = GetPathInfo();
216                                 if (pathInfo != null)
217                                         builder.Append(pathInfo);
218                                 string query = GetQueryString();
219                                 if (query != null && query.Length > 0) {
220                                         builder.Append('?');
221                                         builder.Append(query);
222                                 }
223
224                                 _rawUrl = builder.ToString();
225                         }
226
227                         return _rawUrl;
228                 }
229
230                 public override string GetRemoteAddress() {
231                         return _HttpServletRequest.getRemoteAddr();
232                 }
233
234                 public override string GetRemoteName() {
235                         return _HttpServletRequest.getRemoteHost();
236                 }
237
238
239                 public override int GetRemotePort() {
240                         try {
241                                 return _HttpServletRequest.getRemotePort();
242                         }
243                         catch(Exception e) { //should catch also java.lang.Throwable
244                                 //if servlet API is 2.3 and below - there is no
245                                 //method getRemotePort in ServletRequest interface...
246                                 //should be described as limitation.
247                                 return 0;
248                         }
249                 }
250
251                 public override string GetServerVariable(string name) {
252                         // FIXME: We need to make a proper mapping between the standard server
253                         // variables and java equivalent. probably we have to have a configuration file 
254                         // which associates between the two. Pay a special attention on GetUnknownRequestHeader/s
255                         // while implementing. Ensure that system web "common" code correctly calls each method.
256
257                         string headerName = _srvVarsToHeaderMap[name];
258
259                         if (headerName != null)
260                                 return _HttpServletRequest.getHeader( headerName );
261
262                         for (int i = 0, max = KnownServerVariableNames.Length; i < max; i++)
263                                 if (string.Compare(name, KnownServerVariableNames[i],
264                                         true, CultureInfo.InvariantCulture) == 0)
265                                         return GetKnownServerVariable((KnownServerVariable)i);
266
267                         return _HttpServletRequest.getHeader( name );
268                 }
269
270                 string GetKnownServerVariable(KnownServerVariable index) {
271                         switch (index) {
272                                 case KnownServerVariable.AUTH_TYPE : return _HttpServletRequest.getAuthType();
273                                 case KnownServerVariable.CONTENT_LENGTH : return Convert.ToString(_HttpServletRequest.getContentLength());
274                                 case KnownServerVariable.CONTENT_TYPE : return _HttpServletRequest.getContentType();
275                                 case KnownServerVariable.QUERY_STRING : return GetQueryString();
276                                 case KnownServerVariable.REMOTE_ADDR : return GetRemoteAddress();
277                                 case KnownServerVariable.REMOTE_HOST : return GetRemoteName();
278                                 case KnownServerVariable.REMOTE_USER : return _HttpServletRequest.getRemoteUser();
279                                 case KnownServerVariable.REQUEST_METHOD : return GetHttpVerbName ();
280                                 case KnownServerVariable.REQUEST_URI : return GetUriPath();
281                                 case KnownServerVariable.SCRIPT_NAME : return GetFilePath ();
282                                 case KnownServerVariable.SERVER_NAME : return GetServerName();
283                                 case KnownServerVariable.SERVER_PORT : return Convert.ToString(_HttpServletRequest.getServerPort());
284                                 case KnownServerVariable.SERVER_PROTOCOL : return GetHttpVersion ();
285                                 case KnownServerVariable.SERVER_SOFTWARE : return Servlet.getServletContext().getServerInfo();
286                                 case KnownServerVariable.PATH_INFO : return GetPathInfo();
287                                 default: throw new IndexOutOfRangeException("index");
288                         }
289                 }
290
291                 public override string GetUriPath() {
292                         return _requestUri != null ? _requestUri : _HttpServletRequest.getRequestURI();
293                 }
294
295                 public override IntPtr GetUserToken() {
296                         return IntPtr.Zero;
297                 }
298
299                 public override string MapPath (string path) {
300                         string appVirtualPath = GetAppPath();
301                         if (path.StartsWith(appVirtualPath)) {
302                                 path = path.Remove(0,appVirtualPath.Length);
303                                 if (path.StartsWith("/"))
304                                         path = path.Remove(0,1);
305                         }
306                         //string realPath = Servlet.getServletContext().getRealPath(path);
307                         //                      if (Path.IsPathRooted(path))
308                         //                              return path;
309                         //                      if (!path.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL)&& 
310                         //                              !path.StartsWith("/") && !path.StartsWith("\\")&& !Path.IsPathRooted(path))            
311                         //                              return IAppDomainConfig.WAR_ROOT_SYMBOL + "/" + path;
312                         //                      else if (!path.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL)&& !Path.IsPathRooted(path))
313                         //                              return IAppDomainConfig.WAR_ROOT_SYMBOL + path;
314                         //                      else 
315                         //                              return path;
316
317                         if (path.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL)) {
318                                 return path;
319                         }
320
321                         string retVal =  IAppDomainConfig.WAR_ROOT_SYMBOL;
322
323                         if (!path.StartsWith("/") && !path.StartsWith("\\"))
324                                 retVal += "/";
325
326                         retVal += path;
327
328                         return retVal;
329                 }
330
331                 public override void SendResponseFromFile (IntPtr handle, long offset, long length) {
332                         throw new NotSupportedException();
333                 }
334
335                 public override void SendResponseFromFile (string filename, long offset, long length) {
336                         using (FileStream fs = File.OpenRead (filename)) {
337                                 byte [] buffer = new byte [4 * 1024];
338
339                                 if (offset != 0)
340                                         fs.Position = offset;
341
342                                 long remain = length;
343                                 int n;
344                                 while (remain > 0 && (n = fs.Read (buffer, 0, (int) Math.Min (remain, buffer.Length))) != 0){
345                                         remain -= n;
346                                         SendResponseFromMemory(buffer, n);
347                                 }
348                         }
349                 }
350
351                 public override void SendResponseFromMemory (byte [] data, int length) {
352                         sbyte [] sdata = vmw.common.TypeUtils.ToSByteArray(data);
353                         _HttpServletResponse.getOutputStream().write(sdata, 0 , length);
354                 }
355
356                 public override void SendStatus(int statusCode, string statusDescription) {
357                         // setStatus(int, string) is deprecated
358                         _HttpServletResponse.setStatus(statusCode/*, statusDescription*/);
359                 }
360
361                 public override void SendUnknownResponseHeader(string name, string value) {
362                         if (HeadersSent ())
363                                 return;
364
365                         _HttpServletResponse.addHeader(name, value);
366                 }
367
368                 public override bool HeadersSent () {
369                         return _HttpServletResponse.isCommitted();
370                 }
371
372                 public override void SendCalculatedContentLength (int contentLength) {
373                         _HttpServletResponse.setContentLength(contentLength);
374                 }
375
376                 public override void SendKnownResponseHeader (int index, string value) {
377                         SendUnknownResponseHeader (GetKnownResponseHeaderName (index), value);
378                 }
379
380                 public override string GetKnownRequestHeader (int index) {      
381                         return GetUnknownRequestHeader(GetKnownRequestHeaderName (index));
382                 }
383
384                 public override string GetUnknownRequestHeader (string name) {
385                         return _HttpServletRequest.getHeader(name);
386                 }
387
388                 public override string [][] GetUnknownRequestHeaders () {
389                         if (unknownHeaders == null) {
390                                 ArrayList pairs = new ArrayList ();
391                                 for (java.util.Enumeration he = _HttpServletRequest.getHeaderNames(); he.hasMoreElements() ;) {
392                                         string key = (string) he.nextElement();
393                                         int index = HttpWorkerRequest.GetKnownRequestHeaderIndex (key);
394                                         if (index != -1)
395                                                 continue;
396                                         pairs.Add (new string [] {key, _HttpServletRequest.getHeader(key)});
397                                 }
398                                 
399                                 if (pairs.Count != 0) {
400                                         unknownHeaders = new string [pairs.Count][];
401                                         for (int i = 0; i < pairs.Count; i++)
402                                                 unknownHeaders [i] = (string []) pairs [i];
403                                 }
404                         }
405                         if (unknownHeaders == null) unknownHeaders = new string [0][];
406
407                         return unknownHeaders;
408                 }
409
410                 public override int ReadEntityBody (byte [] buffer, int size) {
411                         if (buffer == null || size == 0)
412                                 return 0;
413                         sbyte [] sbuffer = vmw.common.TypeUtils.ToSByteArray(buffer);
414                         int r = _HttpServletRequest.getInputStream().read(sbuffer, 0, size);    
415                         return (r==-1)?0:r;
416                 }
417
418                 public override void SetEndOfSendNotification(System.Web.HttpWorkerRequest.EndOfSendNotification callback, object extraData) {
419                         _endOfSendCallback = callback;
420                         _endOfSendArgs = extraData;
421                 }
422
423                 public override string GetProtocol() {
424                         return _HttpServletRequest.getScheme();
425                 }
426
427                 public override string GetServerName() {
428                         return _HttpServletRequest.getServerName();
429                 }
430
431                 public override bool IsSecure() {
432                         return _HttpServletRequest.isSecure();
433                 }
434         }
435 }
436