Dont index style nodes.
[beagle.git] / beagled / WebServices / WebServer / InitialWorkerRequest.cs
blobeb871d4dea14ec83464f706c3ff840c2194dd5d6
1 //
2 // Mono.ASPNET.InitialWorkerRequest
3 //
4 // Authors:
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (C) 2003 Ximian, Inc (http://www.ximian.com)
8 // (C) Copyright 2004 Novell, Inc
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System;
30 using System.Collections;
31 using System.Configuration;
32 using System.IO;
33 using System.Net;
34 using System.Net.Sockets;
35 using System.Text;
36 using System.Web;
38 namespace Mono.ASPNET
40 public class RequestData
42 public string Verb;
43 public string Path;
44 public string PathInfo;
45 public string QueryString;
46 public string Protocol;
47 public byte [] InputBuffer;
49 public RequestData (string verb, string path, string queryString, string protocol)
51 this.Verb = verb;
52 this.Path = path;
53 this.QueryString = queryString;
54 this.Protocol = protocol;
57 public override string ToString ()
59 StringBuilder sb = new StringBuilder ();
60 sb.AppendFormat ("Verb: {0}\n", Verb);
61 sb.AppendFormat ("Path: {0}\n", Path);
62 sb.AppendFormat ("PathInfo: {0}\n", PathInfo);
63 sb.AppendFormat ("QueryString: {0}\n", QueryString);
64 return sb.ToString ();
68 class RequestLineException : ApplicationException {
69 public RequestLineException () : base ("Error reading request line")
74 public class InitialWorkerRequest
76 string verb;
77 string path;
78 string queryString;
79 string protocol;
80 NetworkStream stream;
81 bool gotSomeInput;
83 byte [] inputBuffer;
84 int inputLength;
85 int position;
86 const int BSize = 1024 * 32;
88 static Stack bufferStack = new Stack ();
90 static byte [] AllocateBuffer ()
92 lock (bufferStack) {
93 if (bufferStack.Count != 0)
94 return (byte []) bufferStack.Pop ();
96 return new byte [BSize];
99 static void FreeBuffer (byte [] buf)
101 lock (bufferStack) {
102 bufferStack.Push (buf);
106 public InitialWorkerRequest (NetworkStream ns)
108 if (ns == null)
109 throw new ArgumentNullException ("ns");
111 stream = ns;
114 void FillBuffer ()
116 inputBuffer = AllocateBuffer ();
117 inputLength = stream.Read (inputBuffer, 0, BSize);
118 if (inputLength == 0) // Socket closed
119 throw new IOException ("socket closed");
121 gotSomeInput = true;
122 position = 0;
125 int ReadInputByte ()
127 if (inputBuffer == null)
128 FillBuffer ();
130 if (position >= inputLength)
131 return stream.ReadByte ();
133 return (int) inputBuffer [position++];
136 string ReadLine ()
138 bool foundCR = false;
139 StringBuilder text = new StringBuilder ();
141 while (true) {
142 int c = ReadInputByte ();
144 if (c == -1) { // end of stream
145 if (text.Length == 0)
146 return null;
148 if (foundCR)
149 text.Length--;
151 break;
154 if (c == '\n') { // newline
155 if ((text.Length > 0) && (text [text.Length - 1] == '\r'))
156 text.Length--;
158 foundCR = false;
159 break;
160 } else if (foundCR) {
161 text.Length--;
162 break;
165 if (c == '\r')
166 foundCR = true;
169 text.Append ((char) c);
170 if (text.Length > 8192)
171 throw new InvalidOperationException ("Input line too long.");
174 return text.ToString ();
177 bool GetRequestLine ()
179 string req = null;
180 try {
181 while (true) {
182 req = ReadLine ();
183 if (req == null) {
184 gotSomeInput = false;
185 return false;
188 req = req.Trim ();
189 // Ignore empty lines before the actual request.
190 if (req != "")
191 break;
193 } catch {
194 gotSomeInput = false;
195 return false;
198 string [] s = req.Split (' ');
200 switch (s.Length) {
201 case 2:
202 verb = s [0].Trim ();
203 path = s [1].Trim ();
204 break;
205 case 3:
206 verb = s [0].Trim ();
207 path = s [1].Trim ();
208 protocol = s [2].Trim ();
209 break;
210 default:
211 return false;
214 int qmark = path.IndexOf ('?');
215 if (qmark != -1) {
216 queryString = path.Substring (qmark + 1);
217 path = path.Substring (0, qmark);
220 path = HttpUtility.UrlDecode (path);
221 path = GetSafePath (path);
222 if (path.StartsWith ("/~/")) {
223 // Not sure about this. It makes request such us /~/dir/file work
224 path = path.Substring (2);
227 return true;
230 string GetSafePath (string path)
232 string trail = "";
233 if (path.EndsWith ("/"))
234 trail = "/";
236 path = HttpUtility.UrlDecode (path);
237 path = path.Replace ('\\','/');
238 while (path.IndexOf ("//") != -1)
239 path = path.Replace ("//", "/");
241 string [] parts = path.Split ('/');
242 ArrayList result = new ArrayList (parts.Length);
244 int end = parts.Length;
245 for (int i = 0; i < end; i++) {
246 string current = parts [i];
247 if (current == "" || current == "." )
248 continue;
250 if (current == "..") {
251 if (result.Count > 0)
252 result.RemoveAt (result.Count - 1);
253 continue;
256 result.Add (current);
259 if (result.Count == 0)
260 return "/";
262 result.Insert (0, "");
263 return String.Join ("/", (string []) result.ToArray (typeof (string))) + trail;
266 public void ReadRequestData ()
268 if (!GetRequestLine ())
269 throw new RequestLineException ();
271 if (protocol == null) {
272 protocol = "HTTP/1.0";
276 public bool GotSomeInput {
277 get { return gotSomeInput; }
280 public RequestData RequestData {
281 get {
282 RequestData rd = new RequestData (verb, path, queryString, protocol);
283 byte [] buffer = new byte [inputLength - position];
284 Buffer.BlockCopy (inputBuffer, position, buffer, 0, inputLength - position);
285 rd.InputBuffer = buffer;
286 FreeBuffer (inputBuffer);
287 return rd;