2 // MonoWorkerRequest.cs
5 // Daniel Lopez Ridruejo
6 // Gonzalo Paniagua Javier
8 // Copyright (c) 2002 Daniel Lopez Ridruejo.
9 // (c) 2002,2003 Ximian, Inc.
10 // All rights reserved.
11 // (C) Copyright 2004 Novell, Inc. (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System
.Collections
;
36 using System
.Diagnostics
;
39 using System
.Net
.Sockets
;
40 using System
.Reflection
;
42 using System
.Threading
;
44 using System
.Web
.Hosting
;
48 public class MapPathEventArgs
: EventArgs
54 public MapPathEventArgs (string path
)
64 public bool IsMapped
{
65 get { return isMapped; }
68 public string MappedPath
{
69 get { return mapped; }
72 isMapped
= (value != null && value != "");
77 public delegate void MapPathEventHandler (object sender
, MapPathEventArgs args
);
78 public delegate void EndOfRequestHandler (MonoWorkerRequest request
);
80 public abstract class MonoWorkerRequest
: SimpleWorkerRequest
82 IApplicationHost appHostBase
;
84 byte [] queryStringBytes
;
88 public MonoWorkerRequest (IApplicationHost appHost
)
89 : base (String
.Empty
, String
.Empty
, null)
92 throw new ArgumentNullException ("appHost");
94 appHostBase
= appHost
;
97 public event MapPathEventHandler MapPathEvent
;
98 public event EndOfRequestHandler EndOfRequestEvent
;
102 if (hostPath
== null)
103 hostPath
= appHostBase
.Path
;
111 if (hostVPath
== null)
112 hostVPath
= appHostBase
.VPath
;
118 protected virtual Encoding Encoding
{
120 if (encoding
== null)
121 encoding
= new UTF8Encoding (false);
126 set { encoding = value; }
129 public override string GetAppPath ()
134 public override string GetAppPathTranslated ()
139 public override string GetFilePathTranslated ()
141 return MapPath (GetFilePath ());
144 public override string GetLocalAddress ()
149 public override string GetServerName ()
151 string hostHeader
= GetKnownRequestHeader(HeaderHost
);
152 if (hostHeader
== null || hostHeader
.Length
== 0) {
153 hostHeader
= GetLocalAddress ();
155 int colonIndex
= hostHeader
.IndexOf (':');
156 if (colonIndex
> 0) {
157 hostHeader
= hostHeader
.Substring (0, colonIndex
);
158 } else if (colonIndex
== 0) {
159 hostHeader
= GetLocalAddress ();
166 public override int GetLocalPort ()
171 public override byte [] GetPreloadedEntityBody ()
176 public override byte [] GetQueryStringRawBytes ()
178 if (queryStringBytes
== null) {
179 string queryString
= GetQueryString ();
180 if (queryString
!= null)
181 queryStringBytes
= Encoding
.GetBytes (queryString
);
184 return queryStringBytes
;
187 string DoMapPathEvent (string path
)
189 if (MapPathEvent
!= null) {
190 MapPathEventArgs args
= new MapPathEventArgs (path
);
191 foreach (MapPathEventHandler evt
in MapPathEvent
.GetInvocationList ()) {
194 return args
.MappedPath
;
201 public override string MapPath (string path
)
203 string eventResult
= DoMapPathEvent (path
);
204 if (eventResult
!= null)
207 if (path
== null || path
.Length
== 0 || path
== HostVPath
)
208 return HostPath
.Replace ('/', Path
.DirectorySeparatorChar
);
210 if (path
[0] == '~' && path
.Length
> 2 && path
[1] == '/')
211 path
= path
.Substring (1);
213 int len
= HostVPath
.Length
;
214 if (path
.StartsWith (HostVPath
) && (path
.Length
== len
|| path
[len
] == '/'))
215 path
= path
.Substring (len
+ 1);
217 if (path
.Length
> 0 && path
[0] == '/')
218 path
= path
.Substring (1);
220 return Path
.Combine (HostPath
, path
.Replace ('/', Path
.DirectorySeparatorChar
));
223 protected abstract bool GetRequestData ();
224 public abstract int RequestId { get; }
226 public bool ReadRequestData ()
228 return GetRequestData ();
231 public void ProcessRequest ()
233 HttpRuntime
.ProcessRequest (this);
236 public override void EndOfRequest ()
238 if (EndOfRequestEvent
!= null)
239 EndOfRequestEvent (this);
242 public override void SendCalculatedContentLength (int contentLength
)
244 //FIXME: Should we ignore this for apache2?
245 SendUnknownResponseHeader ("Content-Length", contentLength
.ToString ());
248 public override void SendKnownResponseHeader (int index
, string value)
253 string headerName
= HttpWorkerRequest
.GetKnownResponseHeaderName (index
);
254 SendUnknownResponseHeader (headerName
, value);
257 private void SendStream (Stream stream
, long offset
, long length
)
259 if (offset
< 0 || length
<= 0)
262 long stLength
= stream
.Length
;
263 if (offset
+ length
> stLength
)
264 length
= stLength
- offset
;
267 stream
.Seek (offset
, SeekOrigin
.Begin
);
269 byte [] fileContent
= new byte [8192];
270 int count
= fileContent
.Length
;
271 while (length
> 0 && (count
= stream
.Read (fileContent
, 0, count
)) != 0) {
272 SendResponseFromMemory (fileContent
, count
);
274 count
= (int) System
.Math
.Min (length
, fileContent
.Length
);
278 public override void SendResponseFromFile (string filename
, long offset
, long length
)
282 file
= File
.OpenRead (filename
);
283 SendStream (file
, offset
, length
);
290 public override void SendResponseFromFile (IntPtr handle
, long offset
, long length
)
294 file
= new FileStream (handle
, FileAccess
.Read
);
295 SendStream (file
, offset
, length
);