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;
36 using System.Collections.Specialized;
37 using System.Globalization;
39 namespace System.Web.Hosting {
40 [MonoTODO("Implement security demands on the path usage functions (and review)")]
42 internal sealed class ServletWorkerRequest : HttpWorkerRequest {
43 readonly HttpServlet _HttpServlet;
44 readonly HttpServletRequest _HttpServletRequest;
45 readonly HttpServletResponse _HttpServletResponse;
47 readonly string _requestUri;
48 readonly string _pathInfo;
50 static readonly StringDictionary _srvVarsToHeaderMap;
52 private string [][] unknownHeaders;
55 private HttpWorkerRequest.EndOfSendNotification _endOfSendCallback;
56 private object _endOfSendArgs;
58 enum KnownServerVariable {
76 static readonly Hashtable KnownServerVariableMap;
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");
89 string[] knownServerVariableNames = Enum.GetNames(typeof(KnownServerVariable));
90 KnownServerVariableMap = CollectionsUtil.CreateCaseInsensitiveHashtable(knownServerVariableNames.Length);
91 for (int i = 0; i < knownServerVariableNames.Length; i++)
92 KnownServerVariableMap[knownServerVariableNames[i]] = (KnownServerVariable)i;
95 public ServletWorkerRequest (HttpServlet servlet, HttpServletRequest req, HttpServletResponse resp) {
96 _HttpServlet = servlet;
97 _HttpServletRequest = req;
98 _HttpServletResponse = resp;
100 string contextPath = req.getContextPath();
101 string requestURI = req.getRequestURI();
102 if (String.CompareOrdinal(requestURI, contextPath) == 0 ||
103 (((requestURI.Length - contextPath.Length) == 1) &&
104 requestURI[contextPath.Length] == '/' &&
105 String.CompareOrdinal(requestURI, 0, contextPath, 0, contextPath.Length) == 0 ))
106 requestURI = contextPath + req.getServletPath();
108 _requestUri = HttpUtility.UrlDecode(requestURI);
109 const int dotInvokeLength = 7; //".invoke".Length
110 if (_requestUri.Length > dotInvokeLength &&
111 String.CompareOrdinal(".invoke", 0, _requestUri,
112 _requestUri.Length - dotInvokeLength, dotInvokeLength) == 0) {
114 _requestUri = _requestUri.Substring(0, _requestUri.Length - dotInvokeLength);
116 int paramNameStart = _requestUri.LastIndexOf('/');
117 _pathInfo = _requestUri.Substring(paramNameStart, _requestUri.Length - paramNameStart);
121 public HttpServlet Servlet {
127 public HttpServletRequest ServletRequest {
129 return _HttpServletRequest;
133 public HttpServletResponse ServletResponse {
135 return _HttpServletResponse;
139 [MonoTODO("Implement security")]
140 public override string MachineInstallDirectory {
142 return ICalls.GetMachineInstallDirectory ();
146 public override string MachineConfigPath {
147 get { return ICalls.GetMachineConfigPath (); }
150 public override void EndOfRequest () {
151 if (_endOfSendCallback != null)
152 _endOfSendCallback(this, _endOfSendArgs);
155 public override void FlushResponse (bool finalFlush) {
156 ServletOutputStream servletOutputStream = _HttpServletResponse.getOutputStream();
157 servletOutputStream.flush();
159 servletOutputStream.close();
162 public override string GetAppPath () {
163 return _HttpServletRequest.getContextPath();
165 public override string GetAppPathTranslated () {
166 return J2EEUtils.GetApplicationRealPath(_HttpServlet.getServletConfig());;
169 public override string GetFilePath () {
170 string uri = GetUriPath();
171 string pathInfo = GetPathInfo();
172 if (pathInfo != null && pathInfo.Length > 0)
173 uri = uri.Substring(0, uri.Length - pathInfo.Length);
178 public override string GetFilePathTranslated () {
179 string page = GetFilePath ();
181 if (Path.DirectorySeparatorChar != '/')
182 page = page.Replace ('/', Path.DirectorySeparatorChar);
184 if (page [0] == Path.DirectorySeparatorChar)
185 page = page.Substring (1);
187 return Path.Combine (GetAppPathTranslated (), page);
190 public override string GetHttpVerbName () {
191 return _HttpServletRequest.getMethod();
194 public override string GetHttpVersion () {
195 return _HttpServletRequest.getProtocol();
198 public override string GetLocalAddress () {
199 return _HttpServletRequest.getLocalAddr();
202 public override int GetLocalPort () {
203 return _HttpServletRequest.getLocalPort();
206 public override string GetPathInfo () {
207 return _pathInfo != null ? _pathInfo : _HttpServletRequest.getPathInfo();
210 public override string GetQueryString () {
211 return _HttpServletRequest.getQueryString();
214 public override string GetRawUrl () {
215 if (_rawUrl == null) {
216 StringBuilder builder = new StringBuilder();
217 builder.Append(GetUriPath());
218 string pathInfo = GetPathInfo();
219 string query = GetQueryString();
220 if (query != null && query.Length > 0) {
222 builder.Append(query);
225 _rawUrl = builder.ToString();
231 public override string GetRemoteAddress() {
232 return _HttpServletRequest.getRemoteAddr();
235 public override string GetRemoteName() {
236 return _HttpServletRequest.getRemoteHost();
240 public override int GetRemotePort() {
242 return _HttpServletRequest.getRemotePort();
244 catch(Exception e) { //should catch also java.lang.Throwable
245 //if servlet API is 2.3 and below - there is no
246 //method getRemotePort in ServletRequest interface...
247 //should be described as limitation.
252 public override string GetServerVariable(string name) {
253 // FIXME: We need to make a proper mapping between the standard server
254 // variables and java equivalent. probably we have to have a configuration file
255 // which associates between the two. Pay a special attention on GetUnknownRequestHeader/s
256 // while implementing. Ensure that system web "common" code correctly calls each method.
258 string headerName = _srvVarsToHeaderMap[name];
260 if (headerName != null)
261 return _HttpServletRequest.getHeader( headerName );
263 object knownVariable = KnownServerVariableMap[name];
264 if (knownVariable != null)
265 return GetKnownServerVariable((KnownServerVariable)knownVariable);
267 return _HttpServletRequest.getHeader( name );
270 string GetKnownServerVariable(KnownServerVariable 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");
291 public override string GetUriPath() {
295 public override IntPtr GetUserToken() {
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);
306 //string realPath = Servlet.getServletContext().getRealPath(path);
307 // if (Path.IsPathRooted(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;
317 if (path.StartsWith(IAppDomainConfig.WAR_ROOT_SYMBOL)) {
321 string retVal = IAppDomainConfig.WAR_ROOT_SYMBOL;
323 if (!path.StartsWith("/") && !path.StartsWith("\\"))
331 public override void SendResponseFromFile (IntPtr handle, long offset, long length) {
332 throw new NotSupportedException();
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];
340 fs.Position = offset;
342 long remain = length;
344 while (remain > 0 && (n = fs.Read (buffer, 0, (int) Math.Min (remain, buffer.Length))) != 0){
346 SendResponseFromMemory(buffer, n);
351 public override void SendResponseFromMemory (byte [] data, int length) {
352 sbyte [] sdata = vmw.common.TypeUtils.ToSByteArray(data);
353 _HttpServletResponse.getOutputStream().write(sdata, 0 , length);
356 public override void SendStatus(int statusCode, string statusDescription) {
357 // setStatus(int, string) is deprecated
358 _HttpServletResponse.setStatus(statusCode/*, statusDescription*/);
361 public override void SendUnknownResponseHeader(string name, string value) {
365 _HttpServletResponse.addHeader(name, value);
368 public override bool HeadersSent () {
369 return _HttpServletResponse.isCommitted();
372 public override void SendCalculatedContentLength (int contentLength) {
373 _HttpServletResponse.setContentLength(contentLength);
376 public override void SendKnownResponseHeader (int index, string value) {
377 SendUnknownResponseHeader (GetKnownResponseHeaderName (index), value);
380 public override string GetKnownRequestHeader (int index) {
381 return GetUnknownRequestHeader(GetKnownRequestHeaderName (index));
384 public override string GetUnknownRequestHeader (string name) {
385 return _HttpServletRequest.getHeader(name);
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);
396 pairs.Add (new string [] {key, _HttpServletRequest.getHeader(key)});
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];
405 if (unknownHeaders == null) unknownHeaders = new string [0][];
407 return unknownHeaders;
410 public override int ReadEntityBody (byte [] buffer, int size) {
411 if (buffer == null || size == 0)
413 sbyte [] sbuffer = vmw.common.TypeUtils.ToSByteArray(buffer);
414 int r = _HttpServletRequest.getInputStream().read(sbuffer, 0, size);
418 public override void SetEndOfSendNotification(System.Web.HttpWorkerRequest.EndOfSendNotification callback, object extraData) {
419 _endOfSendCallback = callback;
420 _endOfSendArgs = extraData;
423 public override string GetProtocol() {
424 return _HttpServletRequest.getScheme();
427 public override string GetServerName() {
428 return _HttpServletRequest.getServerName();
431 public override bool IsSecure() {
432 return _HttpServletRequest.isSecure();