2 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
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:
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
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.
28 using System.Runtime.InteropServices;
29 using System.Web.Util;
31 using System.Web.J2EE;
32 using System.Collections;
35 using javax.servlet.http;
37 namespace System.Web.Hosting
39 [MonoTODO("Implement security demands on the path usage functions (and review)")]
41 internal class ServletWorkerRequest : HttpWorkerRequest
44 private string _Query;
45 private string _PathInfo = String.Empty;
46 private string _AppVirtualPath;
47 private string _AppPhysicalPath;
48 private string _AppInstallPath;
49 private bool _HasInstallInfo;
51 private static string SLASH = "/";
53 private ServletOutputStream _ServletOutputStream;
54 private HttpServlet _HttpServlet;
55 private HttpServletRequest _HttpServletRequest;
56 private HttpServletResponse _HttpServletResponse;
57 private string [][] unknownHeaders;
59 private HttpWorkerRequest.EndOfSendNotification _endOfSendCallback;
60 private object _endOfSendArgs;
63 private ServletWorkerRequest ()
67 public ServletWorkerRequest (HttpServlet servlet, HttpServletRequest req, HttpServletResponse resp, ServletOutputStream output)
68 :this(String.Empty, String.Empty ,String.Empty, String.Empty ,null)
71 Console.WriteLine("Constructor 1 of ServletWorkerRequest!! -->");
73 _HttpServlet = servlet;
74 _HttpServletRequest = req;
75 _HttpServletResponse = resp;
76 _ServletOutputStream = output;
78 string contextPath = req.getContextPath();
79 string requestURI = req.getRequestURI();
80 if (requestURI.Equals(contextPath) ||
81 ((requestURI.Length - contextPath.Length) == 1) && requestURI[requestURI.Length-1] == '/' && requestURI.StartsWith(contextPath))
82 requestURI = contextPath + req.getServletPath();
84 _Page = requestURI.Substring(contextPath.Length);
86 if (_Page.StartsWith("/"))
87 _Page = _Page.Substring(1);
89 _Query = req.getQueryString();
90 //_PathInfo = req.getPathInfo();
91 _AppVirtualPath = req.getContextPath();
92 _AppPhysicalPath = J2EEUtils.GetApplicationRealPath(servlet.getServletConfig());
94 LogCurrentPageLocation();
98 public ServletWorkerRequest (string Page, string Query, ServletOutputStream output)
102 Console.WriteLine("Constructor 2 of ServletWorkerRequest!! -->");
108 AppDomain current = AppDomain.CurrentDomain;
109 object o = current.GetData (".appPath");
111 throw new HttpException ("Cannot get .appPath");
112 _AppPhysicalPath = (string)current.GetData(IAppDomainConfig.WEB_APP_DIR);
114 o = current.GetData (".hostingVirtualPath");
116 throw new HttpException ("Cannot get .hostingVirtualPath");
117 _AppVirtualPath = CheckAndAddVSlash (o.ToString ());
119 o = current.GetData (".hostingInstallDir");
121 throw new HttpException ("Cannot get .hostingInstallDir");
122 _AppInstallPath = o.ToString ();
123 _ServletOutputStream = output;
125 if (_AppPhysicalPath == null)
126 throw new HttpException ("Invalid app domain");
128 _HasInstallInfo = true;
130 LogCurrentPageLocation();
134 public ServletWorkerRequest (string AppVirtualPath,
135 string AppPhysicalPath,
138 ServletOutputStream output) : this (Page, Query)
141 Console.WriteLine("Constructor 3 of ServletWorkerRequest!! -->");
143 if (AppDomain.CurrentDomain.GetData (".appPath") == null)
144 throw new HttpException ("Invalid app domain");
149 _AppVirtualPath = AppVirtualPath;
150 _AppPhysicalPath = CheckAndAddSlash (AppPhysicalPath);
151 _ServletOutputStream = output;
152 _HasInstallInfo = false;
154 LogCurrentPageLocation();
158 public ServletWorkerRequest (string Page, string Query)
163 AppDomain current = AppDomain.CurrentDomain;
164 object o = current.GetData (".appPath");
166 throw new HttpException ("Cannot get .appPath");
167 _AppPhysicalPath = o.ToString ();
169 o = current.GetData (".hostingVirtualPath");
171 throw new HttpException ("Cannot get .hostingVirtualPath");
172 _AppVirtualPath = o.ToString ();
174 o = current.GetData (".hostingInstallDir");
176 throw new HttpException ("Cannot get .hostingInstallDir");
177 _AppInstallPath = o.ToString ();
179 if (_AppPhysicalPath == null)
180 throw new HttpException ("Invalid app domain");
182 _HasInstallInfo = true;
184 ExtractPagePathInfo();
187 public ServletOutputStream ServletOutputStream
191 return _ServletOutputStream;
195 public HttpServlet Servlet
202 public HttpServletRequest ServletRequest
205 return _HttpServletRequest;
209 public HttpServletResponse ServletResponse
212 return _HttpServletResponse;
216 [MonoTODO("Implement security")]
217 public override string MachineInstallDirectory
221 return _AppInstallPath;
223 return ICalls.GetMachineInstallDirectory ();
227 public override string MachineConfigPath
229 get { return ICalls.GetMachineConfigPath (); }
232 public override void EndOfRequest ()
234 _ServletOutputStream = null;
236 _HttpServletRequest = null;
237 _HttpServletResponse = null;
238 if (_endOfSendCallback != null)
239 _endOfSendCallback(this, _endOfSendArgs);
242 public override void FlushResponse (bool finalFlush)
244 _ServletOutputStream.flush();
246 _ServletOutputStream.close();
249 public override string GetAppPath ()
251 return _AppVirtualPath;
254 public override string GetAppPathTranslated ()
256 return _AppPhysicalPath;
259 public override string GetFilePath ()
261 return CreatePath (false);
264 public override string GetFilePathTranslated ()
268 if (Path.DirectorySeparatorChar != '/')
269 page = _Page.Replace ('/', Path.DirectorySeparatorChar);
271 if (page [0] == Path.DirectorySeparatorChar)
272 page = page.Substring (1);
274 return (Path.Combine (_AppPhysicalPath, page));
277 public override string GetHttpVerbName ()
279 return _HttpServletRequest.getMethod();
282 public override string GetHttpVersion ()
284 return _HttpServletRequest.getProtocol();
287 public override string GetLocalAddress ()
289 return _HttpServletRequest.getServerName();
292 public override int GetLocalPort ()
294 return _HttpServletRequest.getServerPort();
297 public override string GetPathInfo ()
299 return (null != _PathInfo) ? _PathInfo : String.Empty;
302 public override string GetQueryString ()
307 public override string GetRawUrl ()
309 string path = CreatePath (true);
310 if (null != _Query && _Query.Length > 0)
311 return path + "?" + _Query;
316 public override string GetRemoteAddress()
318 return _HttpServletRequest.getRemoteAddr();
321 public override int GetRemotePort()
325 return _HttpServletRequest.getRemotePort();
327 catch(Exception e) //should catch also java.lang.Throwable
329 //if servlet API is 2.3 and below - there is no
330 //method getRemotePort in ServletRequest interface...
331 //should be described as limitation.
336 public override string GetServerVariable(string name)
341 public override string GetUriPath()
343 return CreatePath (true);
346 public override IntPtr GetUserToken()
351 public override string MapPath (string path)
353 if (path.StartsWith(_AppVirtualPath))
355 path = path.Remove(0,_AppVirtualPath.Length);
356 if (path.StartsWith("/"))
357 path = path.Remove(0,1);
359 //string realPath = Servlet.getServletContext().getRealPath(path);
360 // if (Path.IsPathRooted(path))
362 // if (!path.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL)&&
363 // !path.StartsWith("/") && !path.StartsWith("\\")&& !Path.IsPathRooted(path))
364 // return IAppDomainConfig.WAR_ROOT_SYMBOL + "/" + path;
365 // else if (!path.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL)&& !Path.IsPathRooted(path))
366 // return IAppDomainConfig.WAR_ROOT_SYMBOL + path;
370 if (path.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL))
375 string retVal = IAppDomainConfig.WAR_ROOT_SYMBOL;
377 if (!path.StartsWith("/") && !path.StartsWith("\\"))
385 public override void SendResponseFromFile (IntPtr handle, long offset, long length)
389 public override void SendResponseFromFile (string filename, long offset, long length)
391 using (FileStream fs = File.OpenRead (filename)) {
392 byte [] buffer = new byte [4 * 1024];
395 fs.Position = offset;
397 long remain = length;
399 while (remain > 0 && (n = fs.Read (buffer, 0, (int) Math.Min (remain, buffer.Length))) != 0){
401 SendResponseFromMemory(buffer, n);
406 public override void SendResponseFromMemory (byte [] data, int length)
408 sbyte [] sdata = vmw.common.TypeUtils.ToSByteArray(data);
409 _ServletOutputStream.write(sdata, 0 , length);
412 public override void SendStatus(int statusCode, string statusDescription)
414 _HttpServletResponse.setStatus(statusCode, statusDescription);
417 public override void SendUnknownResponseHeader(string name, string value)
419 _HttpServletResponse.addHeader(name, value);
422 public override bool HeadersSent ()
427 public override void SendCalculatedContentLength (int contentLength)
429 //FIXME: Should we ignore this for apache2?
430 SendUnknownResponseHeader ("Content-Length", contentLength.ToString ());
433 public override void SendKnownResponseHeader (int index, string value)
438 string headerName = HttpWorkerRequest.GetKnownResponseHeaderName (index);
439 SendUnknownResponseHeader (headerName, value);
442 // Create's a path string
443 private string CheckAndAddSlash(string sPath)
448 if (String.Empty == sPath)
451 if (!sPath.EndsWith ("" + Path.DirectorySeparatorChar))
452 return sPath + Path.DirectorySeparatorChar;
457 // Creates a path string
458 private string CheckAndAddVSlash(string sPath)
463 if (!sPath.EndsWith ("/"))
469 // Create's a path string
470 private string CreatePath (bool bIncludePathInfo)
472 string sPath = Path.Combine (_AppVirtualPath, _Page);
474 if (bIncludePathInfo && null != _PathInfo)
482 // "The extra path information, as given by the client. In
483 // other words, scripts can be accessed by their virtual
484 // pathname, followed by extra information at the end of this
485 // path. The extra information is sent as PATH_INFO."
486 private void ExtractPagePathInfo ()
488 if (_Page == null || _Page == String.Empty)
491 string FullPath = GetFilePathTranslated ();
492 int PathInfoLength = 0;
493 string LastFile = String.Empty;
495 while (PathInfoLength < _Page.Length) {
496 if (LastFile.Length > 0) {
497 // increase it by the length of the file plus
500 PathInfoLength += LastFile.Length + 1;
503 if (File.Exists (FullPath) == true)
506 if (Directory.Exists (FullPath) == true) {
507 PathInfoLength -= (LastFile.Length + 1);
511 LastFile = Path.GetFileName (FullPath);
512 FullPath = Path.GetDirectoryName (FullPath);
515 if (PathInfoLength <= 0 || PathInfoLength > _Page.Length)
518 _PathInfo = _Page.Substring (_Page.Length - PathInfoLength);
519 _Page = _Page.Substring (0, _Page.Length - PathInfoLength);
522 // Parses out the string after / known as the "path info"
523 private void ParsePathInfo ()
525 int iPos = _Page.LastIndexOf("/");
527 _PathInfo = _Page.Substring (iPos);
528 _Page = _Page.Substring (0, iPos);
532 public override string GetKnownRequestHeader (int index)
534 if (_HttpServletRequest == null)
537 string headerName = HttpWorkerRequest.GetKnownRequestHeaderName (index);
539 return _HttpServletRequest.getHeader(headerName);
542 public override string GetUnknownRequestHeader (string name)
544 if (_HttpServletRequest == null)
547 return _HttpServletRequest.getHeader(name);
550 public override string [][] GetUnknownRequestHeaders ()
552 if (unknownHeaders == null) {
553 ArrayList pairs = new ArrayList ();
554 for (java.util.Enumeration he = _HttpServletRequest.getHeaderNames(); he.hasMoreElements() ;) {
555 string key = (string) he.nextElement();
556 int index = HttpWorkerRequest.GetKnownRequestHeaderIndex (key);
559 pairs.Add (new string [] {key, _HttpServletRequest.getHeader(key)});
562 if (pairs.Count != 0) {
563 unknownHeaders = new string [pairs.Count][];
564 for (int i = 0; i < pairs.Count; i++)
565 unknownHeaders [i] = (string []) pairs [i];
568 if (unknownHeaders == null) unknownHeaders = new string [0][];
570 return unknownHeaders;
573 public override int ReadEntityBody (byte [] buffer, int size)
575 if (buffer == null || size == 0)
577 sbyte [] sbuffer = new sbyte [size];
578 int r = _HttpServletRequest.getInputStream().read(sbuffer, 0, size);
579 for (int i=0; i < r; i++) buffer[i] = (byte) sbuffer[i];
583 public override void SetEndOfSendNotification(System.Web.HttpWorkerRequest.EndOfSendNotification callback, object extraData)
585 _endOfSendCallback = callback;
586 _endOfSendArgs = extraData;
589 // Prints some stats about the current _Page.
590 private void LogCurrentPageLocation()
593 Console.WriteLine(" relpath=" + _AppVirtualPath);
594 Console.WriteLine(" physical path=" + _AppPhysicalPath);
595 Console.WriteLine(" page=" + _Page);