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;
30 using System.Web.J2EE;
31 using System.Collections;
34 using javax.servlet.http;
35 using System.Collections.Specialized;
36 using System.Globalization;
37 using System.Web.Hosting;
39 using InputStream=java.io.InputStream;
42 namespace Mainsoft.Web.Hosting {
43 [MonoTODO("Implement security demands on the path usage functions (and review)")]
45 public abstract class BaseWorkerRequest : HttpWorkerRequest, IServiceProvider {
46 OutputStreamWrapper _OutputStream;
48 readonly string _contextPath;
49 readonly string _requestUri;
50 readonly string _pathInfo;
52 static readonly StringDictionary _srvVarsToHeaderMap;
54 private string [][] unknownHeaders;
57 private HttpWorkerRequest.EndOfSendNotification _endOfSendCallback;
58 private object _endOfSendArgs;
60 enum KnownServerVariable {
78 static readonly Hashtable KnownServerVariableMap;
80 static BaseWorkerRequest() {
81 _srvVarsToHeaderMap = new StringDictionary();
82 _srvVarsToHeaderMap.Add("HTTP_ACCEPT", "Accept");
83 _srvVarsToHeaderMap.Add("HTTP_REFERER", "Referer");
84 _srvVarsToHeaderMap.Add("HTTP_ACCEPT_LANGUAGE", "Accept-Language");
85 _srvVarsToHeaderMap.Add("HTTP_ACCEPT_ENCODING", "Accept-Encoding");
86 _srvVarsToHeaderMap.Add("HTTP_CONNECTION", "Connection");
87 _srvVarsToHeaderMap.Add("HTTP_HOST", "Host");
88 _srvVarsToHeaderMap.Add("HTTP_USER_AGENT", "User-Agent");
89 _srvVarsToHeaderMap.Add("HTTP_SOAPACTION", "SOAPAction");
91 string[] knownServerVariableNames = Enum.GetNames(typeof(KnownServerVariable));
92 KnownServerVariableMap = CollectionsUtil.CreateCaseInsensitiveHashtable(knownServerVariableNames.Length);
93 for (int i = 0; i < knownServerVariableNames.Length; i++)
94 KnownServerVariableMap[knownServerVariableNames[i]] = (KnownServerVariable)i;
97 public BaseWorkerRequest (string contextPath, string servletPath, string requestURI) {
100 _contextPath = contextPath;
102 //string contextPath = req.getContextPath();
103 //string servletPath = req.getServletPath ();
104 //string requestURI = req.getRequestURI ();
105 // servletPath - Returns the part of this request's URL that calls the servlet.
106 // so it contains default page.
107 // 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.
108 // so it contains what the user passed.
110 // the one containing more information wins.
111 if (contextPath.Length + servletPath.Length > requestURI.Length)
112 requestURI = contextPath + servletPath;
114 int contextPos = requestURI.IndexOf(contextPath, StringComparison.Ordinal);
116 requestURI = requestURI.Substring (contextPos);
119 _requestUri = Uri.UnescapeDataString(requestURI);
120 const int dotInvokeLength = 7; //".invoke".Length
121 if (_requestUri.Length > dotInvokeLength &&
122 String.CompareOrdinal(".invoke", 0, _requestUri,
123 _requestUri.Length - dotInvokeLength, dotInvokeLength) == 0) {
125 _requestUri = _requestUri.Substring(0, _requestUri.Length - dotInvokeLength);
127 int paramNameStart = _requestUri.LastIndexOf('/');
128 _pathInfo = _requestUri.Substring(paramNameStart, _requestUri.Length - paramNameStart);
131 const int aspnetconfigLength = 12; //"aspnetconfig".Length
132 int endingSlash = _requestUri [_requestUri.Length - 1] == '/' ? 1 : 0;
133 if (_requestUri.Length > aspnetconfigLength &&
134 String.CompareOrdinal ("aspnetconfig", 0, _requestUri,
135 _requestUri.Length - aspnetconfigLength - endingSlash, aspnetconfigLength) == 0) {
137 if (endingSlash == 0)
139 _requestUri += "Default.aspx";
143 static readonly Type typeOfWriter = typeof (java.io.Writer);
144 public virtual object GetService (Type serviceType)
146 if (serviceType == typeOfWriter)
147 return CreateOutputStream (false);
151 [MonoTODO("Implement security")]
152 public override string MachineInstallDirectory {
158 public override string MachineConfigPath {
162 public override void EndOfRequest () {
163 if (_endOfSendCallback != null)
164 _endOfSendCallback(this, _endOfSendArgs);
165 _OutputStream = null;
168 public override void FlushResponse (bool finalFlush) {
170 //IPortletActionResponse resp =_HttpServletResponse as IPortletActionResponse;
171 //if (_OutputStream == null || resp != null && resp.isRedirected())
173 if (_OutputStream == null)
176 _OutputStream.flush();
178 _OutputStream.close();
181 public override string GetAppPath () {
185 public override string GetFilePath () {
186 string uri = GetUriPath();
187 string pathInfo = GetPathInfo();
188 if (pathInfo != null && pathInfo.Length > 0)
189 uri = uri.Substring(0, uri.Length - pathInfo.Length);
194 public override string GetFilePathTranslated () {
195 string page = GetFilePath ();
197 if (Path.DirectorySeparatorChar != '/')
198 page = page.Replace ('/', Path.DirectorySeparatorChar);
200 if (page [0] == Path.DirectorySeparatorChar)
201 page = page.Substring (1);
203 return Path.Combine (GetAppPathTranslated (), page);
206 public override string GetPathInfo () {
210 public override string GetRawUrl () {
211 if (_rawUrl == null) {
212 StringBuilder builder = new StringBuilder();
213 builder.Append(GetUriPath());
214 string pathInfo = GetPathInfo();
215 string query = GetQueryString();
216 if (query != null && query.Length > 0) {
218 builder.Append(query);
221 _rawUrl = builder.ToString();
227 public override string GetServerVariable(string name) {
228 // FIXME: We need to make a proper mapping between the standard server
229 // variables and java equivalent. probably we have to have a configuration file
230 // which associates between the two. Pay a special attention on GetUnknownRequestHeader/s
231 // while implementing. Ensure that system web "common" code correctly calls each method.
233 string headerName = _srvVarsToHeaderMap[name];
235 if (headerName != null)
236 return getHeader( headerName );
238 object knownVariable = KnownServerVariableMap[name];
239 if (knownVariable != null)
240 return GetKnownServerVariable((KnownServerVariable)knownVariable);
242 return getHeader( name );
245 public abstract string GetAuthType ();
246 protected abstract int getContentLength ();
247 protected abstract string getContentType ();
248 public abstract string GetRemoteUser ();
249 protected abstract string getHeader (string name);
250 protected abstract java.util.Enumeration getHeaderNames ();
251 protected abstract InputStream getInputStream ();
252 public abstract ServletContext GetContext ();
253 protected abstract OutputStreamWrapper CreateOutputStream (bool binary);
255 public abstract HttpSession GetSession (bool create);
256 public abstract bool IsRequestedSessionIdValid ();
257 public abstract string GetRequestedSessionId ();
258 public abstract bool IsUserInRole (string name);
259 public abstract Principal GetUserPrincipal ();
261 string GetKnownServerVariable(KnownServerVariable index) {
263 case KnownServerVariable.AUTH_TYPE : return GetAuthType();
264 case KnownServerVariable.CONTENT_LENGTH : return Convert.ToString(getContentLength());
265 case KnownServerVariable.CONTENT_TYPE : return getContentType();
266 case KnownServerVariable.QUERY_STRING : return GetQueryString();
267 case KnownServerVariable.REMOTE_ADDR : return GetRemoteAddress();
268 case KnownServerVariable.REMOTE_HOST : return GetRemoteName();
269 case KnownServerVariable.REMOTE_USER : return GetRemoteUser();
270 case KnownServerVariable.REQUEST_METHOD : return GetHttpVerbName ();
271 case KnownServerVariable.REQUEST_URI : return GetUriPath();
272 case KnownServerVariable.SCRIPT_NAME : return GetFilePath ();
273 case KnownServerVariable.SERVER_NAME : return GetServerName();
274 case KnownServerVariable.SERVER_PORT : return Convert.ToString(GetLocalPort());
275 case KnownServerVariable.SERVER_PROTOCOL : return GetHttpVersion ();
276 case KnownServerVariable.SERVER_SOFTWARE : return GetContext().getServerInfo();
277 case KnownServerVariable.PATH_INFO : return GetPathInfo();
278 default: throw new IndexOutOfRangeException("index");
282 public override string GetUriPath() {
286 public override IntPtr GetUserToken() {
290 public override string GetAppPathTranslated () {
291 return J2EEUtils.GetApplicationRealPath (GetContext ());
294 public override string MapPath (string virtualPath) {
295 if (virtualPath == null)
296 throw new ArgumentNullException ("virtualPath");
298 ServletContext context = GetContext ();
300 string contextPath = GetAppPath ();
301 if ((virtualPath.Length > contextPath.Length && virtualPath [contextPath.Length] != '/') ||
302 string.Compare (contextPath, 0, virtualPath, 0, contextPath.Length, StringComparison.OrdinalIgnoreCase) != 0) {
304 for (int appVirtualPathIndex = 0; appVirtualPathIndex > 0 && virtualPath.Length > appVirtualPathIndex; ) {
305 appVirtualPathIndex = virtualPath.IndexOf ('/', appVirtualPathIndex + 1);
306 string crossContextPath = appVirtualPathIndex > 0 ?
307 virtualPath.Remove (appVirtualPathIndex) : virtualPath;
308 ServletContext other = context.getContext (crossContextPath);
310 string appVirtualPath = appVirtualPathIndex > 0 ?
311 virtualPath.Substring (appVirtualPathIndex) : String.Empty;
312 return other.getRealPath (appVirtualPath);
316 throw new HttpException (
317 String.Format ("MapPath: Mapping across applications is not allowed. ApplicationPath is '{0}', VirtualPath is '{1}'.",
318 contextPath, virtualPath));
321 string thisAppVirtualPath = virtualPath.Length > contextPath.Length ? virtualPath.Substring (contextPath.Length) : String.Empty;
322 return J2EEUtils.GetApplicationRealPath (context, thisAppVirtualPath);
326 public override void SendResponseFromFile (IntPtr handle, long offset, long length) {
327 throw new NotSupportedException();
330 public override void SendResponseFromFile (string filename, long offset, long length) {
331 using (FileStream fs = File.OpenRead (filename)) {
332 byte [] buffer = new byte [4 * 1024];
335 fs.Position = offset;
337 long remain = length;
339 while (remain > 0 && (n = fs.Read (buffer, 0, (int) Math.Min (remain, buffer.Length))) != 0){
341 SendResponseFromMemory(buffer, n);
347 //private OutputStreamWrapper CreateOutputStream (bool binary)
349 // IPortletActionResponse resp = _HttpServletResponse as IPortletActionResponse;
351 // return null; // no output stream while processAction
353 // if (_OutputStream != null)
354 // return _OutputStream;
356 // if (_HttpServletResponse != null) {
358 // _OutputStream = new OutputStreamWrapper (_HttpServletResponse.getOutputStream ());
360 // _OutputStream = new OutputStreamWrapper (_HttpServletResponse.getWriter ());
363 // return _OutputStream;
366 public override void SendResponseFromMemory (byte [] data, int length) {
367 _OutputStream = CreateOutputStream (true);
369 if (_OutputStream == null)
372 sbyte [] sdata = vmw.common.TypeUtils.ToSByteArray(data);
373 _OutputStream.write(sdata, 0 , length);
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 getHeader(name);
388 public override string [][] GetUnknownRequestHeaders () {
389 if (unknownHeaders == null) {
390 ArrayList pairs = new ArrayList ();
391 for (java.util.Enumeration he = getHeaderNames(); he.hasMoreElements() ;) {
392 string key = (string) he.nextElement();
393 int index = HttpWorkerRequest.GetKnownRequestHeaderIndex (key);
396 pairs.Add (new string [] {key, 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 InputStream inp = getInputStream();
417 int r = inp.read (sbuffer, 0, size);
418 return r < 0 ? 0 : r;
421 public override void SetEndOfSendNotification(System.Web.HttpWorkerRequest.EndOfSendNotification callback, object extraData) {
422 _endOfSendCallback = callback;
423 _endOfSendArgs = extraData;
426 public abstract BaseHttpContext CreateContext (HttpContext context);