2004-09-09 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web / HttpServerUtility.cs
1
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
10 // 
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 // 
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 /**
23  * Namespace: System.Web
24  * Class:     HttpServerUtility
25  *
26  * Authosr:
27  *      Wictor Wilén (wictor@ibizkit.se)
28  *      Patrik Torstensson (patrik.torstensson@labs2.com)
29  *      Gonzalo Paniagua Javier (gonzalo@ximian.com)
30  *
31  * (c) Wictor Wilén (2002)
32  * (c) 2002 Patrik Torstensson
33  * (c) 2003 Ximian, Inc. (http://www.ximian.com)
34  *
35  * (This log is no longer maintained)
36  * ---------------------------------------
37  * 2002-03-27  Wictor      Started implementation
38  * 2002-04-09  Patrik      Added HttpContext constructor
39  * 2002-04-10  Patrik      Moved encoding to HttpUtility and
40  *                         fixed all functions that used
41  *                         HttpContext
42  * 
43  */
44 using System;
45 using System.Collections.Specialized;
46 using System.IO;
47 using System.Text;
48 using System.Web.Hosting;
49 using System.Web.UI;
50 using System.Web.Util;
51
52 namespace System.Web
53 {
54         public sealed class HttpServerUtility
55         {
56                 private static string _name;
57
58                 private HttpContext _Context;
59                 private HttpApplication _Application;
60
61                 internal HttpServerUtility (HttpContext Context)
62                 {
63                         _Context = Context;
64                 }
65
66                 internal HttpServerUtility (HttpApplication app)
67                 {
68                         _Application = app;
69                 }
70
71                 // Properties
72
73
74                 /// <summary>
75                 /// Gets the server's computer name.
76                 /// </summary>
77                 public string MachineName {
78                         get {
79                                 if(_name == null)
80                                         _name = Environment.MachineName;
81
82                                 return _name;
83                         }
84                 }
85
86                 public int ScriptTimeout {
87                         get {
88                                 return (int) _Context.ConfigTimeout.TotalSeconds;
89                         } 
90                         set {
91                                 if (value <= 0)
92                                         throw new ArgumentOutOfRangeException ("value");
93
94                                 _Context.ConfigTimeout = new TimeSpan (0, 0, value);
95                         }
96                 }
97
98                 // Methods
99
100                 /// <summary>
101                 /// Clears the previous exception.
102                 /// </summary>
103                 public void ClearError ()
104                 {
105                         if (null != _Context) {
106                                 _Context.ClearError ();
107                                 return;
108                         }
109
110                         if (null != _Application) {
111                                 _Application.ClearError ();
112                         }
113                 }
114
115
116                 /// <summary>
117                 /// Creates a server instance of a COM object identified by the object's Programmatic Identifier (ProgID).
118                 /// </summary>
119                 /// <param name="progID">The class or type of object to be instantiated. </param>
120                 /// <returns>The new object.</returns>
121                 public object CreateObject (string progID)
122                 {
123                         return CreateObject (Type.GetTypeFromProgID (progID));
124                 }
125
126
127                 /// <summary>
128                 /// Creates a server instance of a COM object identified by the object's type.
129                 /// </summary>
130                 /// <param name="type">A Type representing the object to create. </param>
131                 /// <returns>The new object.</returns>
132                 public object CreateObject (Type type)
133                 {
134                         return Activator.CreateInstance (type);
135                 }
136
137
138                 /// <summary>
139                 /// Creates a server instance of a COM object identified by the object's class identifier (CLSID).
140                 /// </summary>
141                 /// <param name="clsid">The class identifier of the object to be instantiated. </param>
142                 /// <returns>The new object.</returns>
143                 public object CreateObjectFromClsid (string clsid)
144                 {
145                         Guid guid = new Guid (clsid);
146                         return CreateObject (Type.GetTypeFromCLSID (guid));
147                 }
148
149
150                 /// <summary>
151                 /// Executes a request to another page using the specified URL path to the page.
152                 /// </summary>
153                 /// <param name="path">The URL path of the new request. </param>
154                 public void Execute (string path)
155                 {
156                         Execute (path, null);
157                 }
158
159
160                 /// <summary>
161                 /// Executes a request to another page using the specified URL path to the page.
162                 /// A TextWriter captures output from the page.
163                 /// </summary>
164                 /// <param name="path">The URL path of the new request. </param>
165                 /// <param name="writer">The TextWriter to capture the output. </param>
166                 public void Execute (string path, TextWriter writer)
167                 {
168                         Execute (path, writer, false);
169                 }
170
171 #if NET_2_0
172                 public
173 #else
174                 internal
175 #endif
176                 void Execute (string path, TextWriter writer, bool preserveQuery)
177                 {
178                         if (path == null)
179                                 throw new ArgumentNullException ("path");
180
181                         if (_Context == null)
182                                 throw new HttpException ("No context available.");
183
184                         if (path.IndexOf (':') != -1)
185                                 throw new ArgumentException ("Invalid path.");
186
187                         int qmark = path.IndexOf ('?');
188                         string query;
189                         if (qmark != -1) {
190                                 query = path.Substring (qmark + 1);
191                                 path = path.Substring (0, qmark);
192                         } else {
193                                 query = "";
194                         }
195                         
196                         string filePath = _Context.Request.MapPath (path);
197                         HttpResponse response = _Context.Response;
198                         TextWriter output = writer;
199                         if (output == null)
200                                 output = response.Output;
201
202                         HttpRequest request = _Context.Request;
203                         string oldFilePath = request.FilePath;
204                         request.SetFilePath (UrlUtils.Combine (_Context.Request.BaseVirtualDir, path));
205                         string oldQuery = request.QueryStringRaw;
206                         
207                         if (!preserveQuery)     request.QueryStringRaw = query;
208                         IHttpHandler handler = _Context.ApplicationInstance.CreateHttpHandler (_Context,
209                                                                                                request.RequestType,
210                                                                                                path,
211                                                                                                filePath);
212                         TextWriter previous = null;
213                         try {
214                                 previous = response.SetTextWriter (output);
215                                 if (!(handler is IHttpAsyncHandler)) {
216                                         handler.ProcessRequest (_Context);
217                                 } else {
218                                         IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler) handler;
219                                         IAsyncResult ar = asyncHandler.BeginProcessRequest (_Context, null, null);
220                                         ar.AsyncWaitHandle.WaitOne ();
221                                         asyncHandler.EndProcessRequest (ar);
222                                 }
223                         } finally {
224                                 request.SetFilePath (oldFilePath);
225                                 request.QueryStringRaw = oldQuery;
226                                 response.SetTextWriter (previous);
227                         }
228
229                 }
230
231                 /// <summary>
232                 /// Returns the previous exception.
233                 /// </summary>
234                 /// <returns>The previous exception that was thrown.</returns>
235                 public Exception GetLastError ()
236                 {
237                         if (_Context == null)
238                                 return null;
239
240                         return _Context.Error;
241                 }
242
243
244
245                 /// <summary>
246                 /// Decodes an HTML-encoded string and returns the decoded string.
247                 /// </summary>
248                 /// <param name="s">The HTML string to decode. </param>
249                 /// <returns>The decoded text.</returns>
250                 public string HtmlDecode (string s)
251                 {
252                         return HttpUtility.HtmlDecode (s);
253                 }
254
255
256                 /// <summary>
257                 /// Decodes an HTML-encoded string and sends the resulting output to a TextWriter output stream.
258                 /// </summary>
259                 /// <param name="s">The HTML string to decode</param>
260                 /// <param name="output">The TextWriter output stream containing the decoded string. </param>
261                 public void HtmlDecode (string s, TextWriter output)
262                 {
263                         output.Write (HttpUtility.HtmlDecode (s));
264                 }
265
266                 /// <summary>
267                 /// HTML-encodes a string and returns the encoded string.
268                 /// </summary>
269                 /// <param name="s">The text string to encode. </param>
270                 /// <returns>The HTML-encoded text.</returns>
271                 public string HtmlEncode (string s)
272                 {
273                         return HttpUtility.HtmlEncode (s);
274                 }
275
276                 /// <summary>
277                 /// HTML-encodes a string and sends the resulting output to a TextWriter output stream.
278                 /// </summary>
279                 /// <param name="s">The string to encode. </param>
280                 /// <param name="output">The TextWriter output stream containing the encoded string. </param>
281                 public void HtmlEncode (string s, TextWriter output)
282                 {
283                         output.Write (HtmlEncode (s));
284                 }
285
286
287                 /// <summary>
288                 /// Returns the physical file path that corresponds to the specified virtual path on the Web server.
289                 /// </summary>
290                 /// <param name="path">The virtual path on the Web server. </param>
291                 /// <returns>The physical file path that corresponds to path.</returns>
292                 public string MapPath (string path)
293                 {
294                         if (null == _Context)
295                                 throw new HttpException ("MapPath is not available");
296
297                         return _Context.Request.MapPath (path);
298                 }
299
300                 /// <summary>
301                 /// Terminates execution of the current page and begins execution of a new page using the specified
302                 /// URL path to the page.
303                 /// </summary>
304                 /// <param name="path">The URL path of the new page on the server to execute. </param>
305                 public void Transfer (string path)
306                 {
307                         // If it's a page and a postback, don't pass form data
308                         // See bug #65613.
309                         bool preserveForm = true;
310                         if (_Context.Handler is Page) {
311                                 Page page = (Page) _Context.Handler;
312                                 preserveForm = !page.IsPostBack;
313                         }
314
315                         Transfer (path, preserveForm);
316                 }
317
318                 /// <summary>
319                 /// Terminates execution of the current page and begins execution of a new page using the specified
320                 /// URL path to the page. Specifies whether to clear the QueryString and Form collections.
321                 /// </summary>
322                 /// <param name="path">The URL path of the new page on the server to execute. </param>
323                 /// <param name="preserveForm">If true, the QueryString and Form collections are preserved. If false,
324                 /// they are cleared. The default is false. </param>
325                 public void Transfer (string path, bool preserveForm)
326                 {
327                         HttpValueCollection oldForm = null;
328                         if (!preserveForm) {
329                                 oldForm = _Context.Request.Form as HttpValueCollection;
330                                 _Context.Request.SetForm (new HttpValueCollection ());
331                         }
332
333                         Execute (path, null, preserveForm);
334                         if (!preserveForm)
335                                 _Context.Request.SetForm (oldForm);
336
337                         _Context.Response.End ();
338                 }
339
340                 /// <summary>
341                 /// URL-decodes a string and returns the decoded string.
342                 /// </summary>
343                 /// <param name="s">The text string to decode. </param>
344                 /// <returns>The decoded text.</returns>
345                 /// <remarks>
346                 /// Post/html encoding @ ftp://ftp.isi.edu/in-notes/rfc1866.txt
347                 /// Uncomment the line marked with RFC1738 to get pure RFC1738
348                 /// and it will also consider the RFC1866 (ftp://ftp.isi.edu/in-notes/rfc1866.txt)
349                 /// `application/x-www-form-urlencoded' format
350                 /// </remarks>
351                 public string UrlDecode (string s)
352                 {
353                         return HttpUtility.UrlDecode (s);
354                 }
355
356                 /// <summary>
357                 /// Decodes an HTML string received in a URL and sends the resulting output to a TextWriter output stream.
358                 /// </summary>
359                 /// <param name="s"></param>
360                 /// <param name="output"></param>
361                 public void UrlDecode (string s, TextWriter output)
362                 {
363                         if (s != null)
364                                 output.Write (UrlDecode (s));
365                 }
366
367                 /// <summary>
368                 /// URL-encodes a string and returns the encoded string.
369                 /// </summary>
370                 /// <param name="s">The text to URL-encode. </param>
371                 /// <returns>The URL encoded text.</returns>
372                 public string UrlEncode (string s)
373                 {
374                         return HttpUtility.UrlEncode (s);
375                 }
376
377                 /// <summary>
378                 /// URL encodes a string and sends the resulting output to a TextWriter output stream.
379                 /// </summary>
380                 /// <param name="s">The text string to encode. </param>
381                 /// <param name="output">The TextWriter output stream containing the encoded string. </param>
382                 public void UrlEncode (string s, TextWriter output)
383                 {
384                         if (s != null)
385                                 output.Write (UrlEncode (s));
386                 }
387
388                 /// <summary>
389                 /// URL-encodes the path portion of a URL string and returns the encoded string.
390                 /// </summary>
391                 /// <param name="s">The text to URL-encode.</param>
392                 /// <returns>The URL encoded text.</returns>
393                 /// <remarks>Does not do any browser specific adjustments, just encode everything</remarks>
394                 public string UrlPathEncode (string s)
395                 {
396                         if (s == null)
397                                 return null;
398
399                         int idx = s.IndexOf ("?");
400                         string s2 = null;
401                         if (idx != -1) {
402                                 s2 = s.Substring (0, idx-1);
403                                 s2 = UrlEncode (s2) + s.Substring (idx);
404                         } else {
405                                 s2 = UrlEncode (s);
406                         }
407
408                         return s2;
409                 }
410         }
411 }