~ifolder-dev/simias/trunk-packaging

« back to all changes in this revision

Viewing changes to src/core/SimiasApp/.svn/text-base/InitialWorkerRequest.cs.svn-base

  • Committer: Jorge O. Castro
  • Date: 2007-12-03 06:56:46 UTC
  • Revision ID: jorge@ubuntu.com-20071203065646-mupcnjcwgm5mnhyt
* Remove a bunch of .svn directories we no longer need.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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.
28
 
//
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;
37
 
 
38
 
namespace Mono.ASPNET
39
 
{
40
 
        public class RequestData
41
 
        {
42
 
                public string Verb;
43
 
                public string Path;
44
 
                public string PathInfo;
45
 
                public string QueryString;
46
 
                public string Protocol;
47
 
                public byte [] InputBuffer;
48
 
 
49
 
                public RequestData (string verb, string path, string queryString, string protocol)
50
 
                {
51
 
                        this.Verb = verb;
52
 
                        this.Path = path;
53
 
                        this.QueryString = queryString;
54
 
                        this.Protocol = protocol;
55
 
                }
56
 
 
57
 
                public override string ToString ()
58
 
                {
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 ();
65
 
                }
66
 
        }
67
 
 
68
 
        class RequestLineException : ApplicationException {
69
 
                public RequestLineException () : base ("Error reading request line")
70
 
                {
71
 
                }
72
 
        }
73
 
 
74
 
        public class InitialWorkerRequest
75
 
        {
76
 
                string verb;
77
 
                string path;
78
 
                string queryString;
79
 
                string protocol;
80
 
                string pathInfo;
81
 
                NetworkStream stream;
82
 
                bool gotSomeInput;
83
 
 
84
 
                byte [] inputBuffer;
85
 
                int inputLength;
86
 
                int position;
87
 
                const int BSize = 1024 * 32;
88
 
                
89
 
                static Stack bufferStack = new Stack ();
90
 
                
91
 
                static byte [] AllocateBuffer ()
92
 
                {
93
 
                        lock (bufferStack) {
94
 
                                if (bufferStack.Count != 0)
95
 
                                        return (byte []) bufferStack.Pop ();
96
 
                        }
97
 
                        return new byte [BSize];
98
 
                }
99
 
                
100
 
                static void FreeBuffer (byte [] buf)
101
 
                {
102
 
                        lock (bufferStack) {
103
 
                                bufferStack.Push (buf);
104
 
                        }
105
 
                }
106
 
                
107
 
                public InitialWorkerRequest (NetworkStream ns)
108
 
                {
109
 
                        if (ns == null)
110
 
                                throw new ArgumentNullException ("ns");
111
 
 
112
 
                        stream = ns;
113
 
                }
114
 
 
115
 
                void FillBuffer ()
116
 
                {
117
 
                        inputBuffer = AllocateBuffer ();
118
 
                        inputLength = stream.Read (inputBuffer, 0, BSize);
119
 
                        if (inputLength == 0) // Socket closed
120
 
                                throw new IOException ("socket closed");
121
 
 
122
 
                        gotSomeInput = true;
123
 
                        position = 0;
124
 
                }
125
 
 
126
 
                int ReadInputByte ()
127
 
                {
128
 
                        if (inputBuffer == null)
129
 
                                FillBuffer ();
130
 
 
131
 
                        if (position >= inputLength)
132
 
                                return stream.ReadByte ();
133
 
 
134
 
                        return (int) inputBuffer [position++];
135
 
                }
136
 
 
137
 
                string ReadLine ()
138
 
                {
139
 
                        bool foundCR = false;
140
 
                        StringBuilder text = new StringBuilder ();
141
 
 
142
 
                        while (true) {
143
 
                                int c = ReadInputByte ();
144
 
 
145
 
                                if (c == -1) {                          // end of stream
146
 
                                        if (text.Length == 0)
147
 
                                                return null;
148
 
 
149
 
                                        if (foundCR)
150
 
                                                text.Length--;
151
 
 
152
 
                                        break;
153
 
                                }
154
 
 
155
 
                                if (c == '\n') {                        // newline
156
 
                                        if ((text.Length > 0) && (text [text.Length - 1] == '\r'))
157
 
                                                text.Length--;
158
 
 
159
 
                                        foundCR = false;
160
 
                                        break;
161
 
                                } else if (foundCR) {
162
 
                                        text.Length--;
163
 
                                        break;
164
 
                                }
165
 
 
166
 
                                if (c == '\r')
167
 
                                        foundCR = true;
168
 
                                        
169
 
 
170
 
                                text.Append ((char) c);
171
 
                                if (text.Length > 8192)
172
 
                                        throw new InvalidOperationException ("Input line too long.");
173
 
                        }
174
 
 
175
 
                        return text.ToString ();
176
 
                }
177
 
 
178
 
                bool GetRequestLine ()
179
 
                {
180
 
                        string req = null;
181
 
                        try {
182
 
                                req = ReadLine ();
183
 
                        } catch {
184
 
                        }
185
 
 
186
 
                        if (req == null)
187
 
                                return false;
188
 
 
189
 
                        req = req.Trim ();
190
 
                        string [] s = req.Split (' ');
191
 
 
192
 
                        switch (s.Length) {
193
 
                        case 2:
194
 
                                verb = s [0].Trim ();
195
 
                                path = s [1].Trim ();
196
 
                                break;
197
 
                        case 3:
198
 
                                verb = s [0].Trim ();
199
 
                                path = s [1].Trim ();
200
 
                                protocol = s [2].Trim ();
201
 
                                break;
202
 
                        default:
203
 
                                return false;
204
 
                        }
205
 
 
206
 
                        int qmark = path.IndexOf ('?');
207
 
                        if (qmark != -1) {
208
 
                                queryString = path.Substring (qmark + 1);
209
 
                                path = path.Substring (0, qmark);
210
 
                        }
211
 
 
212
 
                        path = HttpUtility.UrlDecode (path);
213
 
                        path = GetSafePath (path);
214
 
                        
215
 
                        // Yes, MS only looks for the '.'. Try setting a handler for
216
 
                        // something not containing a '.' and you won't get path_info.
217
 
                        int dot = path.LastIndexOf ('.');
218
 
                        int slash = (dot != -1) ? path.IndexOf ('/', dot) : -1;
219
 
                        if (dot >= 0 && slash >= 0) {
220
 
                                pathInfo = path.Substring (slash);
221
 
                                path = path.Substring (0, slash);
222
 
                        } else {
223
 
                                pathInfo = "";
224
 
                        }
225
 
 
226
 
                        if (path.StartsWith ("/~/")) {
227
 
                                // Not sure about this. It makes request such us /~/dir/file work
228
 
                                path = path.Substring (2);
229
 
                        }
230
 
 
231
 
                        return true;
232
 
                }
233
 
 
234
 
                string GetSafePath (string path)
235
 
                {
236
 
                        string trail = "";
237
 
                        if (path.EndsWith ("/"))
238
 
                                trail = "/";
239
 
 
240
 
                        path = HttpUtility.UrlDecode (path);
241
 
                        path = path.Replace ('\\','/');
242
 
                        while (path.IndexOf ("//") != -1)
243
 
                                path = path.Replace ("//", "/");
244
 
 
245
 
                        string [] parts = path.Split ('/');
246
 
                        ArrayList result = new ArrayList (parts.Length);
247
 
                        
248
 
                        int end = parts.Length;
249
 
                        for (int i = 0; i < end; i++) {
250
 
                                string current = parts [i];
251
 
                                if (current == "" || current == "." )
252
 
                                        continue;
253
 
 
254
 
                                if (current == "..") {
255
 
                                        if (result.Count > 0)
256
 
                                                result.RemoveAt (result.Count - 1);
257
 
                                        continue;
258
 
                                }
259
 
 
260
 
                                result.Add (current);
261
 
                        }
262
 
 
263
 
                        if (result.Count == 0)
264
 
                                return "/";
265
 
 
266
 
                        result.Insert (0, "");
267
 
                        return String.Join ("/", (string []) result.ToArray (typeof (string))) + trail;
268
 
                }
269
 
                
270
 
                public void ReadRequestData ()
271
 
                {
272
 
                        if (!GetRequestLine ())
273
 
                                throw new RequestLineException ();
274
 
 
275
 
                        if (protocol == null) {
276
 
                                protocol = "HTTP/1.0";
277
 
                        }
278
 
                }
279
 
 
280
 
                public bool GotSomeInput {
281
 
                        get { return gotSomeInput; }
282
 
                }
283
 
 
284
 
                public RequestData RequestData {
285
 
                        get {
286
 
                                RequestData rd = new RequestData (verb, path, queryString, protocol);
287
 
                                byte [] buffer = new byte [inputLength - position];
288
 
                                Buffer.BlockCopy (inputBuffer, position, buffer, 0, inputLength - position);
289
 
                                rd.InputBuffer = buffer;
290
 
                                rd.PathInfo = pathInfo;
291
 
                                FreeBuffer (inputBuffer);
292
 
                                return rd;
293
 
                        }
294
 
                }
295
 
        }
296
 
}
297