format view state hidden field.
[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 System.Web.J2EE;
31 using System.Collections;
32 using System.Web;
33 using javax.servlet;
34 using javax.servlet.http;
35 using System.Collections.Specialized;
36 using System.Globalization;
37 using System.Web.Hosting;
38 using vmw.common;
39 using InputStream=java.io.InputStream;
40 using java.security;
41
42 namespace Mainsoft.Web.Hosting {
43         [MonoTODO("Implement security demands on the path usage functions (and review)")]
44         [ComVisible (false)]
45         public abstract class BaseWorkerRequest : HttpWorkerRequest, IHttpExtendedWorkerRequest, IServiceProvider
46         {
47                 OutputStreamWrapper _OutputStream;
48
49                 readonly string _contextPath;
50                 readonly string _requestUri;
51                 readonly string _pathInfo;
52
53                 static readonly StringDictionary _srvVarsToHeaderMap;
54
55                 private string [][] unknownHeaders;
56                 string _rawUrl;
57
58                 private HttpWorkerRequest.EndOfSendNotification _endOfSendCallback;
59                 private object _endOfSendArgs;
60
61                 enum KnownServerVariable {
62                         AUTH_TYPE,
63                         CONTENT_LENGTH,
64                         CONTENT_TYPE,
65                         QUERY_STRING,
66                         REMOTE_ADDR,
67                         REMOTE_HOST,
68                         REMOTE_USER,
69                         REQUEST_METHOD,
70                         REQUEST_URI,
71                         SCRIPT_NAME,
72                         SERVER_NAME,
73                         SERVER_PORT,
74                         SERVER_PROTOCOL,
75                         SERVER_SOFTWARE,
76                         PATH_INFO
77                 };
78
79                 static readonly Hashtable KnownServerVariableMap;
80
81                 static BaseWorkerRequest() {
82                         _srvVarsToHeaderMap = new StringDictionary();
83                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT", "Accept");
84                         _srvVarsToHeaderMap.Add("HTTP_REFERER", "Referer");
85                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT_LANGUAGE", "Accept-Language");
86                         _srvVarsToHeaderMap.Add("HTTP_ACCEPT_ENCODING", "Accept-Encoding");
87                         _srvVarsToHeaderMap.Add("HTTP_CONNECTION", "Connection");
88                         _srvVarsToHeaderMap.Add("HTTP_HOST", "Host");
89                         _srvVarsToHeaderMap.Add("HTTP_USER_AGENT", "User-Agent");
90                         _srvVarsToHeaderMap.Add("HTTP_SOAPACTION", "SOAPAction");
91
92                         string[] knownServerVariableNames = Enum.GetNames(typeof(KnownServerVariable));
93                         KnownServerVariableMap = CollectionsUtil.CreateCaseInsensitiveHashtable(knownServerVariableNames.Length);
94                         for (int i = 0; i < knownServerVariableNames.Length; i++)
95                                 KnownServerVariableMap[knownServerVariableNames[i]] = (KnownServerVariable)i;
96                 }
97
98                 public BaseWorkerRequest (string contextPath, string servletPath, string requestURI) {
99
100
101                         _contextPath = contextPath;
102
103                         //string contextPath = req.getContextPath();
104                         //string servletPath = req.getServletPath ();
105                         //string requestURI = req.getRequestURI ();
106                         // servletPath - Returns the part of this request's URL that calls the servlet.
107                         //              so it contains default page.
108                         // requestURI - Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request.
109                         //              so it contains what the user passed.
110                         //
111                         // the one containing more information wins.
112                         if (contextPath.Length + servletPath.Length > requestURI.Length)
113                                 requestURI = contextPath + servletPath;
114                         else { 
115                                 int contextPos = requestURI.IndexOf(contextPath, StringComparison.Ordinal);
116                                 if (contextPos > 0)
117                                         requestURI = requestURI.Substring (contextPos);
118                         }
119
120                         _requestUri = Uri.UnescapeDataString(requestURI);
121                         const int dotInvokeLength = 7; //".invoke".Length
122                         if (_requestUri.Length > dotInvokeLength &&
123                                 String.CompareOrdinal(".invoke", 0, _requestUri, 
124                                 _requestUri.Length - dotInvokeLength, dotInvokeLength) == 0) {
125
126                                 _requestUri = _requestUri.Substring(0, _requestUri.Length - dotInvokeLength);
127                                 
128                                 int paramNameStart = _requestUri.LastIndexOf('/');
129                                 _pathInfo = _requestUri.Substring(paramNameStart, _requestUri.Length - paramNameStart);
130                         }
131
132                         const int aspnetconfigLength = 12; //"aspnetconfig".Length
133                         int endingSlash = _requestUri [_requestUri.Length - 1] == '/' ? 1 : 0;
134                         if (_requestUri.Length > aspnetconfigLength &&
135                                 String.CompareOrdinal ("aspnetconfig", 0, _requestUri,
136                                 _requestUri.Length - aspnetconfigLength - endingSlash, aspnetconfigLength) == 0) {
137
138                                 if (endingSlash == 0)
139                                         _requestUri += "/";
140                                 _requestUri += "Default.aspx";
141                         }
142                 }
143
144                 static readonly Type typeOfWriter = typeof (java.io.Writer);
145                 public virtual object GetService (Type serviceType)
146                 {
147                         if (serviceType == typeOfWriter)
148                                 return CreateOutputStream (false);
149                         return null;
150                 }
151                 
152                 [MonoTODO("Implement security")]
153                 public override string MachineInstallDirectory {
154                         get {
155                                 return ".";
156                         }
157                 }
158
159                 public override string MachineConfigPath {
160                         get { return "."; }
161                 }
162
163                 public override void EndOfRequest () {
164                         if (_endOfSendCallback != null)
165                                 _endOfSendCallback(this, _endOfSendArgs);
166                         _OutputStream = null;
167                 }
168
169                 public override void FlushResponse (bool finalFlush) {
170                         //kostat
171                         //IPortletActionResponse resp =_HttpServletResponse as IPortletActionResponse;
172                         //if (_OutputStream == null || resp != null && resp.isRedirected())
173                         //      return;
174                         if (_OutputStream == null)
175                                 return;
176
177                         _OutputStream.flush();
178                         if (finalFlush)
179                                 _OutputStream.close();
180                 }
181
182                 public override string GetAppPath () {
183                         return _contextPath;
184                 }
185
186                 public override string GetFilePath () {
187                         string uri = GetUriPath();
188                         string pathInfo = GetPathInfo();
189                         if (pathInfo != null && pathInfo.Length > 0)
190                                 uri = uri.Substring (0, uri.Length - pathInfo.Length);
191
192                         return uri;
193                 }
194
195                 public override string GetFilePathTranslated () {
196                         string page = GetFilePath ();
197
198                         if (Path.DirectorySeparatorChar != '/')
199                                 page = page.Replace ('/', Path.DirectorySeparatorChar);
200
201                         if (page [0] == Path.DirectorySeparatorChar)
202                                 page = page.Substring (1);
203                         
204                         return Path.Combine (GetAppPathTranslated (), page);
205                 }
206
207                 public override string GetPathInfo () {
208                         return _pathInfo;
209                 }               
210
211                 public override string GetRawUrl () {
212                         if (_rawUrl == null) {
213                                 StringBuilder builder = new StringBuilder();
214                                 builder.Append(GetUriPath());
215                                 string pathInfo = GetPathInfo();
216                                 string query = GetQueryString();
217                                 if (query != null && query.Length > 0) {
218                                         builder.Append('?');
219                                         builder.Append(query);
220                                 }
221
222                                 _rawUrl = builder.ToString();
223                         }
224
225                         return _rawUrl;
226                 }
227
228                 public override string GetServerVariable(string name) {
229                         // FIXME: We need to make a proper mapping between the standard server
230                         // variables and java equivalent. probably we have to have a configuration file 
231                         // which associates between the two. Pay a special attention on GetUnknownRequestHeader/s
232                         // while implementing. Ensure that system web "common" code correctly calls each method.
233
234                         string headerName = _srvVarsToHeaderMap[name];
235
236                         if (headerName != null)
237                                 return getHeader( headerName );
238
239                         object knownVariable = KnownServerVariableMap[name];
240                         if (knownVariable != null)
241                                 return GetKnownServerVariable((KnownServerVariable)knownVariable);
242
243                         return getHeader( name );
244                 }
245
246                 public abstract string GetAuthType ();
247                 protected abstract int getContentLength ();
248                 protected abstract string getContentType ();
249                 public abstract string GetRemoteUser ();
250                 protected abstract string getHeader (string name);
251                 protected abstract java.util.Enumeration getHeaderNames ();
252                 protected abstract InputStream getInputStream ();
253                 public abstract ServletContext GetContext ();
254                 protected abstract OutputStreamWrapper CreateOutputStream (bool binary);
255
256                 public abstract HttpSession GetSession (bool create);
257                 public abstract bool IsRequestedSessionIdValid ();
258                 public abstract string GetRequestedSessionId ();
259                 public abstract bool IsUserInRole (string name);
260                 public abstract Principal GetUserPrincipal ();
261
262                 string GetKnownServerVariable(KnownServerVariable index) {
263                         switch (index) {
264                                 case KnownServerVariable.AUTH_TYPE : return GetAuthType();
265                                 case KnownServerVariable.CONTENT_LENGTH : return Convert.ToString(getContentLength());
266                                 case KnownServerVariable.CONTENT_TYPE : return getContentType();
267                                 case KnownServerVariable.QUERY_STRING : return GetQueryString();
268                                 case KnownServerVariable.REMOTE_ADDR : return GetRemoteAddress();
269                                 case KnownServerVariable.REMOTE_HOST : return GetRemoteName();
270                                 case KnownServerVariable.REMOTE_USER : return GetRemoteUser();
271                                 case KnownServerVariable.REQUEST_METHOD : return GetHttpVerbName ();
272                                 case KnownServerVariable.REQUEST_URI : return GetUriPath();
273                                 case KnownServerVariable.SCRIPT_NAME : return GetFilePath ();
274                                 case KnownServerVariable.SERVER_NAME : return GetServerName();
275                                 case KnownServerVariable.SERVER_PORT : return Convert.ToString(GetLocalPort());
276                                 case KnownServerVariable.SERVER_PROTOCOL : return GetHttpVersion ();
277                                 case KnownServerVariable.SERVER_SOFTWARE : return GetContext().getServerInfo();
278                                 case KnownServerVariable.PATH_INFO : return GetPathInfo();
279                                 default: throw new IndexOutOfRangeException("index");
280                         }
281                 }
282
283                 public override string GetUriPath() {
284                         return _requestUri;
285                 }
286
287                 public override IntPtr GetUserToken() {
288                         return IntPtr.Zero;
289                 }
290
291                 public override string GetAppPathTranslated () {
292                         return J2EEUtils.GetApplicationRealPath (GetContext ());
293                 }
294
295                 public override string MapPath (string virtualPath) {
296                         if (virtualPath == null)
297                                 throw new ArgumentNullException ("virtualPath");
298
299                         ServletContext context = GetContext ();
300
301                         string contextPath = GetAppPath ();
302                         if ((virtualPath.Length > contextPath.Length && virtualPath [contextPath.Length] != '/') ||
303                                 string.Compare (contextPath, 0, virtualPath, 0, contextPath.Length, StringComparison.OrdinalIgnoreCase) != 0) {
304
305                                 for (int appVirtualPathIndex = 0; appVirtualPathIndex > 0 && virtualPath.Length > appVirtualPathIndex; ) {
306                                         appVirtualPathIndex = virtualPath.IndexOf ('/', appVirtualPathIndex + 1);
307                                         string crossContextPath = appVirtualPathIndex > 0 ?
308                                                 virtualPath.Remove (appVirtualPathIndex) : virtualPath;
309                                         ServletContext other = context.getContext (crossContextPath);
310                                         if (other != null) {
311                                                 string appVirtualPath = appVirtualPathIndex > 0 ?
312                                                         virtualPath.Substring (appVirtualPathIndex) : String.Empty;
313                                                 return other.getRealPath (appVirtualPath);
314                                         }
315                                 }
316
317                                 throw new HttpException (
318                                         String.Format ("MapPath: Mapping across applications is not allowed. ApplicationPath is '{0}', VirtualPath is '{1}'.",
319                                         contextPath, virtualPath));
320                         }
321
322                         string thisAppVirtualPath = virtualPath.Length > contextPath.Length ? virtualPath.Substring (contextPath.Length) : String.Empty;
323                         return J2EEUtils.GetApplicationRealPath (context, thisAppVirtualPath);
324
325                 }
326
327                 public override void SendResponseFromFile (IntPtr handle, long offset, long length) {
328                         throw new NotSupportedException();
329                 }
330
331                 public override void SendResponseFromFile (string filename, long offset, long length) {
332                         using (FileStream fs = File.OpenRead (filename)) {
333                                 byte [] buffer = new byte [4 * 1024];
334
335                                 if (offset != 0)
336                                         fs.Position = offset;
337
338                                 long remain = length;
339                                 int n;
340                                 while (remain > 0 && (n = fs.Read (buffer, 0, (int) Math.Min (remain, buffer.Length))) != 0){
341                                         remain -= n;
342                                         SendResponseFromMemory(buffer, n);
343                                 }
344                         }
345                 }
346
347                 //kostat
348                 //private OutputStreamWrapper CreateOutputStream (bool binary)
349                 //{
350                 //    IPortletActionResponse resp = _HttpServletResponse as IPortletActionResponse;
351                 //    if (resp != null)
352                 //        return null; // no output stream while processAction
353
354                 //    if (_OutputStream != null)
355                 //        return _OutputStream;
356
357                 //    if (_HttpServletResponse != null) {
358                 //        if (binary)
359                 //            _OutputStream = new OutputStreamWrapper (_HttpServletResponse.getOutputStream ());
360                 //        else
361                 //            _OutputStream = new OutputStreamWrapper (_HttpServletResponse.getWriter ());
362                 //    }
363
364                 //    return _OutputStream;
365                 //}
366
367                 public override void SendResponseFromMemory (byte [] data, int length) {
368                         _OutputStream = CreateOutputStream (true);
369
370                         if (_OutputStream == null)
371                                 return;
372
373                         sbyte [] sdata = vmw.common.TypeUtils.ToSByteArray(data);
374                         _OutputStream.write(sdata, 0 , length);
375                 }
376
377                 public override void SendKnownResponseHeader (int index, string value) {
378                         SendUnknownResponseHeader (GetKnownResponseHeaderName (index), value);
379                 }
380
381                 public override string GetKnownRequestHeader (int index) {      
382                         return GetUnknownRequestHeader(GetKnownRequestHeaderName (index));
383                 }
384
385                 public override string GetUnknownRequestHeader (string name) {
386                         return getHeader(name);
387                 }
388
389                 public override string [][] GetUnknownRequestHeaders () {
390                         if (unknownHeaders == null) {
391                                 ArrayList pairs = new ArrayList ();
392                                 for (java.util.Enumeration he = getHeaderNames(); he.hasMoreElements() ;) {
393                                         string key = (string) he.nextElement();
394                                         int index = HttpWorkerRequest.GetKnownRequestHeaderIndex (key);
395                                         if (index != -1)
396                                                 continue;
397                                         pairs.Add (new string [] {key, getHeader(key)});
398                                 }
399                                 
400                                 if (pairs.Count != 0) {
401                                         unknownHeaders = new string [pairs.Count][];
402                                         for (int i = 0; i < pairs.Count; i++)
403                                                 unknownHeaders [i] = (string []) pairs [i];
404                                 }
405                         }
406                         if (unknownHeaders == null) unknownHeaders = new string [0][];
407
408                         return unknownHeaders;
409                 }
410
411                 public override int ReadEntityBody (byte [] buffer, int size) {
412                         if (buffer == null || size == 0)
413                                 return 0;
414                         sbyte [] sbuffer = vmw.common.TypeUtils.ToSByteArray(buffer);
415                         InputStream inp = getInputStream();
416                         if (inp == null)
417                                 return 0;
418                         int r = inp.read (sbuffer, 0, size);
419                         return r < 0 ? 0 : r;
420                 }
421
422                 public override void SetEndOfSendNotification(System.Web.HttpWorkerRequest.EndOfSendNotification callback, object extraData) {
423                         _endOfSendCallback = callback;
424                         _endOfSendArgs = extraData;
425                 }
426
427                 public abstract BaseHttpContext CreateContext (HttpContext context);
428         }
429 }
430