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, IHttpExtendedWorkerRequest, IServiceProvider
47 OutputStreamWrapper _OutputStream;
49 readonly string _contextPath;
50 readonly string _requestUri;
51 readonly string _pathInfo;
53 static readonly StringDictionary _srvVarsToHeaderMap;
55 private string [][] unknownHeaders;
58 private HttpWorkerRequest.EndOfSendNotification _endOfSendCallback;
59 private object _endOfSendArgs;
61 enum KnownServerVariable {
79 static readonly Hashtable KnownServerVariableMap;
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");
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;
98 public BaseWorkerRequest (string contextPath, string servletPath, string requestURI) {
101 _contextPath = contextPath;
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.
111 // the one containing more information wins.
112 if (contextPath.Length + servletPath.Length > requestURI.Length)
113 requestURI = contextPath + servletPath;
115 int contextPos = requestURI.IndexOf(contextPath, StringComparison.Ordinal);
117 requestURI = requestURI.Substring (contextPos);
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) {
126 _requestUri = _requestUri.Substring(0, _requestUri.Length - dotInvokeLength);
128 int paramNameStart = _requestUri.LastIndexOf('/');
129 _pathInfo = _requestUri.Substring(paramNameStart, _requestUri.Length - paramNameStart);
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) {
138 if (endingSlash == 0)
140 _requestUri += "Default.aspx";
144 static readonly Type typeOfWriter = typeof (java.io.Writer);
145 public virtual object GetService (Type serviceType)
147 if (serviceType == typeOfWriter)
148 return CreateOutputStream (false);
152 [MonoTODO("Implement security")]
153 public override string MachineInstallDirectory {
159 public override string MachineConfigPath {
163 public override void EndOfRequest () {
164 if (_endOfSendCallback != null)
165 _endOfSendCallback(this, _endOfSendArgs);
166 _OutputStream = null;
169 public override void FlushResponse (bool finalFlush) {
171 //IPortletActionResponse resp =_HttpServletResponse as IPortletActionResponse;
172 //if (_OutputStream == null || resp != null && resp.isRedirected())
174 if (_OutputStream == null)
177 _OutputStream.flush();
179 _OutputStream.close();
182 public override string GetAppPath () {
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);
195 public override string GetFilePathTranslated () {
196 string page = GetFilePath ();
198 if (Path.DirectorySeparatorChar != '/')
199 page = page.Replace ('/', Path.DirectorySeparatorChar);
201 if (page [0] == Path.DirectorySeparatorChar)
202 page = page.Substring (1);
204 return Path.Combine (GetAppPathTranslated (), page);
207 public override string GetPathInfo () {
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) {
219 builder.Append(query);
222 _rawUrl = builder.ToString();
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.
234 string headerName = _srvVarsToHeaderMap[name];
236 if (headerName != null)
237 return getHeader( headerName );
239 object knownVariable = KnownServerVariableMap[name];
240 if (knownVariable != null)
241 return GetKnownServerVariable((KnownServerVariable)knownVariable);
243 return getHeader( name );
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);
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 ();
262 string GetKnownServerVariable(KnownServerVariable 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");
283 public override string GetUriPath() {
287 public override IntPtr GetUserToken() {
291 public override string GetAppPathTranslated () {
292 return J2EEUtils.GetApplicationRealPath (GetContext ());
295 public override string MapPath (string virtualPath) {
296 if (virtualPath == null)
297 throw new ArgumentNullException ("virtualPath");
299 ServletContext context = GetContext ();
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) {
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);
311 string appVirtualPath = appVirtualPathIndex > 0 ?
312 virtualPath.Substring (appVirtualPathIndex) : String.Empty;
313 return other.getRealPath (appVirtualPath);
317 throw new HttpException (
318 String.Format ("MapPath: Mapping across applications is not allowed. ApplicationPath is '{0}', VirtualPath is '{1}'.",
319 contextPath, virtualPath));
322 string thisAppVirtualPath = virtualPath.Length > contextPath.Length ? virtualPath.Substring (contextPath.Length) : String.Empty;
323 return J2EEUtils.GetApplicationRealPath (context, thisAppVirtualPath);
327 public override void SendResponseFromFile (IntPtr handle, long offset, long length) {
328 throw new NotSupportedException();
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];
336 fs.Position = offset;
338 long remain = length;
340 while (remain > 0 && (n = fs.Read (buffer, 0, (int) Math.Min (remain, buffer.Length))) != 0){
342 SendResponseFromMemory(buffer, n);
348 //private OutputStreamWrapper CreateOutputStream (bool binary)
350 // IPortletActionResponse resp = _HttpServletResponse as IPortletActionResponse;
352 // return null; // no output stream while processAction
354 // if (_OutputStream != null)
355 // return _OutputStream;
357 // if (_HttpServletResponse != null) {
359 // _OutputStream = new OutputStreamWrapper (_HttpServletResponse.getOutputStream ());
361 // _OutputStream = new OutputStreamWrapper (_HttpServletResponse.getWriter ());
364 // return _OutputStream;
367 public override void SendResponseFromMemory (byte [] data, int length) {
368 _OutputStream = CreateOutputStream (true);
370 if (_OutputStream == null)
373 sbyte [] sdata = vmw.common.TypeUtils.ToSByteArray(data);
374 _OutputStream.write(sdata, 0 , length);
377 public override void SendKnownResponseHeader (int index, string value) {
378 SendUnknownResponseHeader (GetKnownResponseHeaderName (index), value);
381 public override string GetKnownRequestHeader (int index) {
382 return GetUnknownRequestHeader(GetKnownRequestHeaderName (index));
385 public override string GetUnknownRequestHeader (string name) {
386 return getHeader(name);
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);
397 pairs.Add (new string [] {key, getHeader(key)});
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];
406 if (unknownHeaders == null) unknownHeaders = new string [0][];
408 return unknownHeaders;
411 public override int ReadEntityBody (byte [] buffer, int size) {
412 if (buffer == null || size == 0)
414 sbyte [] sbuffer = vmw.common.TypeUtils.ToSByteArray(buffer);
415 InputStream inp = getInputStream();
418 int r = inp.read (sbuffer, 0, size);
419 return r < 0 ? 0 : r;
422 public override void SetEndOfSendNotification(System.Web.HttpWorkerRequest.EndOfSendNotification callback, object extraData) {
423 _endOfSendCallback = callback;
424 _endOfSendArgs = extraData;
427 public abstract BaseHttpContext CreateContext (HttpContext context);