Merge branch 'cecil-light'
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels.Http / HttpContextInfo.cs
1 //
2 // HttpContextInfo.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2010 Novell, Inc.  http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Collections.Generic;
30 using System.Collections.Specialized;
31 using System.Globalization;
32 using System.IO;
33 using System.Net;
34 using System.Security.Principal;
35 using System.ServiceModel;
36 using System.Text;
37 using System.Threading;
38 using System.Web;
39
40 namespace System.ServiceModel.Channels.Http
41 {
42         // Context
43         
44         abstract class HttpContextInfo
45         {
46                 public abstract HttpRequestInfo Request { get; }
47                 public abstract HttpResponseInfo Response { get; }
48
49                 public abstract string User { get; }
50                 public abstract string Password { get; }
51                 public abstract void ReturnUnauthorized ();
52
53                 public void Abort ()
54                 {
55                         Response.Abort ();
56                         OnContextClosed ();
57                 }
58
59                 public void Close ()
60                 {
61                         Response.Close ();
62                         OnContextClosed ();
63                 }
64                 
65                 protected virtual void OnContextClosed ()
66                 {
67                 }
68         }
69
70         class HttpStandaloneContextInfo : HttpContextInfo
71         {
72                 public HttpStandaloneContextInfo (HttpListenerContext ctx)
73                 {
74                         this.ctx = ctx;
75                         request = new HttpStandaloneRequestInfo (ctx.Request);
76                         response = new HttpStandaloneResponseInfo (ctx.Response);
77                 }
78                 
79                 HttpListenerContext ctx;
80                 HttpStandaloneRequestInfo request;
81                 HttpStandaloneResponseInfo response;
82
83                 public HttpListenerContext Source {
84                         get { return ctx; }
85                 }
86
87                 public override HttpRequestInfo Request {
88                         get { return request; }
89                 }
90
91                 public override HttpResponseInfo Response {
92                         get { return response; }
93                 }
94
95                 public override string User {
96                         get { return ctx.User != null ? ((HttpListenerBasicIdentity) ctx.User.Identity).Name : null; }
97                 }
98
99                 public override string Password {
100                         get { return ctx.User != null ? ((HttpListenerBasicIdentity) ctx.User.Identity).Password : null; }
101                 }
102
103                 public override void ReturnUnauthorized ()
104                 {
105                         ctx.Response.StatusCode = 401;
106                 }
107         }
108
109         class AspNetHttpContextInfo : HttpContextInfo
110         {
111                 public AspNetHttpContextInfo (SvcHttpHandler handler, HttpContext ctx)
112                 {
113                         this.ctx = ctx;
114                         this.handler = handler;
115                         this.request = new AspNetHttpRequestInfo (ctx.Request);
116                         this.response = new AspNetHttpResponseInfo (ctx.Response);
117                 }
118                 
119                 HttpContext ctx;
120                 SvcHttpHandler handler;
121                 AspNetHttpRequestInfo request;
122                 AspNetHttpResponseInfo response;
123
124                 public HttpContext Source {
125                         get { return ctx; }
126                 }
127                 
128                 public override HttpRequestInfo Request {
129                         get { return request; }
130                 }
131
132                 public override HttpResponseInfo Response {
133                         get { return response; }
134                 }
135
136                 public override string User {
137                         get { return ctx.User != null ? ((GenericIdentity) ctx.User.Identity).Name : null; }
138                 }
139
140                 // FIXME: how to acquire this?
141                 public override string Password {
142                         get { return null; }
143                 }
144
145                 public override void ReturnUnauthorized ()
146                 {
147                         ctx.Response.StatusCode = 401;
148                 }
149
150                 protected override void OnContextClosed ()
151                 {
152                         handler.EndHttpRequest (ctx);
153                 }
154         }
155
156         // Request
157
158         abstract class HttpRequestInfo
159         {
160                 public abstract long ContentLength64 { get; }
161                 public abstract NameValueCollection QueryString { get; }
162                 public abstract NameValueCollection Headers { get; }
163                 public abstract Uri Url { get; }
164                 public abstract string ContentType { get; }
165                 public abstract string HttpMethod { get; }
166                 public abstract Stream InputStream { get; }
167         }
168
169         class HttpStandaloneRequestInfo : HttpRequestInfo
170         {
171                 public HttpStandaloneRequestInfo (HttpListenerRequest request)
172                 {
173                         this.req = request;
174                 }
175                 
176                 HttpListenerRequest req;
177
178                 public override long ContentLength64 {
179                         get { return req.ContentLength64; }
180                 }
181                 public override NameValueCollection QueryString {
182                         get { return req.QueryString; }
183                 }
184                 public override NameValueCollection Headers {
185                         get { return req.Headers; }
186                 }
187                 public override Uri Url {
188                         get { return req.Url; }
189                 }
190                 public override string ContentType {
191                         get { return req.ContentType; }
192                 }
193                 public override string HttpMethod {
194                         get { return req.HttpMethod; }
195                 }
196                 public override Stream InputStream {
197                         get { return req.InputStream; }
198                 }
199         }
200
201         class AspNetHttpRequestInfo : HttpRequestInfo
202         {
203                 public AspNetHttpRequestInfo (HttpRequest request)
204                 {
205                         this.req = request;
206                 }
207                 
208                 HttpRequest req;
209
210                 public override long ContentLength64 {
211                         get { return req.ContentLength; }
212                 }
213                 public override NameValueCollection QueryString {
214                         get { return req.QueryString; }
215                 }
216                 public override NameValueCollection Headers {
217                         get { return req.Headers; }
218                 }
219                 public override Uri Url {
220                         get { return req.Url; }
221                 }
222                 public override string ContentType {
223                         get { return req.ContentType; }
224                 }
225                 public override string HttpMethod {
226                         get { return req.HttpMethod; }
227                 }
228                 public override Stream InputStream {
229                         get { return req.InputStream; }
230                 }
231         }
232         
233         // Response
234         
235         abstract class HttpResponseInfo
236         {
237                 public abstract string ContentType { get; set; }
238                 public abstract NameValueCollection Headers { get; }
239                 public abstract Stream OutputStream { get; }
240                 public abstract int StatusCode { get; set; }
241                 public abstract string StatusDescription { get; set; }
242                 public abstract void Abort ();
243                 public abstract void Close ();
244                 public abstract void SetLength (long value);
245                 
246                 public virtual bool SuppressContent { get; set; }
247         }
248
249         class HttpStandaloneResponseInfo : HttpResponseInfo
250         {
251                 public HttpStandaloneResponseInfo (HttpListenerResponse response)
252                 {
253                         this.res = response;
254                 }
255                 
256                 HttpListenerResponse res;
257
258                 public override string ContentType {
259                         get { return res.ContentType; }
260                         set { res.ContentType = value; }
261                 }
262                 public override NameValueCollection Headers {
263                         get { return res.Headers; }
264                 }
265                 public override int StatusCode {
266                         get { return res.StatusCode; }
267                         set { res.StatusCode = value; }
268                 }
269                 public override string StatusDescription {
270                         get { return res.StatusDescription; }
271                         set { res.StatusDescription = value; }
272                 }
273                 public override Stream OutputStream {
274                         get { return res.OutputStream; }
275                 }
276                 
277                 public override void Abort ()
278                 {
279                         res.Abort ();
280                 }
281                 
282                 public override void Close ()
283                 {
284                         res.Close ();
285                 }
286                 
287                 public override void SetLength (long value)
288                 {
289                         res.ContentLength64 = value;
290                 }
291         }
292
293         class AspNetHttpResponseInfo : HttpResponseInfo
294         {
295                 public AspNetHttpResponseInfo (HttpResponse response)
296                 {
297                         this.res = response;
298                 }
299                 
300                 HttpResponse res;
301                 
302                 public override bool SuppressContent {
303                         get { return res.SuppressContent; }
304                         set { res.SuppressContent = value; }
305                 }
306                 public override string ContentType {
307                         get { return res.ContentType; }
308                         set { res.ContentType = value; }
309                 }
310                 public override NameValueCollection Headers {
311                         get { return res.Headers; }
312                 }
313                 public override int StatusCode {
314                         get { return res.StatusCode; }
315                         set { res.StatusCode = value; }
316                 }
317                 
318                 public override string StatusDescription {
319                         get { return res.StatusDescription; }
320                         set { res.StatusDescription = value; }
321                 }
322                 public override Stream OutputStream {
323                         get { return res.OutputStream; }
324                 }
325                 
326                 public override void Abort ()
327                 {
328                         res.End ();
329                 }
330                 
331                 public override void Close ()
332                 {
333                         // We must not close the response here, as everything is taking place in the
334                         // HttpApplication's pipeline context and the output is sent to the client
335                         // _after_ we leave this method. Closing the response here will stop any
336                         // output from reaching the client.
337                 }
338                 
339                 public override void SetLength (long value)
340                 {
341                         res.AddHeader ("Content-Length", value.ToString (CultureInfo.InvariantCulture));
342                 }
343         }
344 }