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);