2 // System.Web.HttpRequest.cs
6 // Miguel de Icaza (miguel@novell.com)
7 // Gonzalo Paniagua Javier (gonzalo@novell.com)
11 // Copyright (C) 2005 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.Web.Util;
36 using System.Collections.Specialized;
37 using System.Security.Permissions;
39 using System.Web.Configuration;
40 using System.Web.SessionState;
42 namespace System.Web {
45 // Methods exposed through HttpContext.Server property
48 // CAS - no InheritanceDemand here as the class is sealed
49 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
50 public sealed class HttpServerUtility {
53 internal HttpServerUtility (HttpContext context)
55 this.context = context;
58 public void ClearError ()
60 context.ClearError ();
63 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
64 public object CreateObject (string progID)
66 throw new HttpException (500, "COM is not supported");
69 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
70 public object CreateObject (Type type)
72 throw new HttpException (500, "COM is not supported");
75 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
76 public object CreateObjectFromClsid (string clsid)
78 throw new HttpException (500, "COM is not supported");
81 public void Execute (string path)
83 Execute (path, null, true);
86 public void Execute (string path, TextWriter writer)
88 Execute (path, writer, true);
92 public void Execute (string path, bool preserveForm)
94 Execute (path, null, preserveForm);
103 void Execute (string path, TextWriter writer, bool preserveForm)
105 Execute (path, writer, preserveForm, false);
108 void Execute (string path, TextWriter writer, bool preserveForm, bool isTransfer)
111 throw new ArgumentNullException ("path");
113 if (path.IndexOf (':') != -1)
114 throw new ArgumentException ("Invalid path.");
116 string queryString = null;
117 int qmark = path.IndexOf ('?');
119 queryString = path.Substring (qmark + 1);
120 path = path.Substring (0, qmark);
123 string exePath = UrlUtils.Combine (context.Request.BaseVirtualDir, path);
124 bool cookieless = false;
127 SessionStateSection config = WebConfigurationManager.GetWebApplicationSection ("system.web/sessionState") as SessionStateSection;
128 cookieless = SessionStateModule.IsCookieLess (context, config);
130 SessionConfig config = HttpContext.GetAppConfig ("system.web/sessionState") as SessionConfig;
131 cookieless = config.CookieLess;
134 exePath = UrlUtils.RemoveSessionId (VirtualPathUtility.GetDirectory (exePath), exePath);
136 IHttpHandler handler = context.ApplicationInstance.GetHandler (context, exePath, true);
137 Execute (handler, writer, preserveForm, exePath, queryString, isTransfer, true);
140 internal void Execute (IHttpHandler handler, TextWriter writer, bool preserveForm, string exePath, string queryString, bool isTransfer, bool isInclude) {
141 #if NET_2_0 && !TARGET_J2EE
142 // If the target handler is not Page, the transfer must not occur.
143 // InTransit == true means we're being called from Transfer
144 bool is_static = (handler is StaticFileHandler);
145 if (isTransfer && !(handler is Page) && !is_static)
146 throw new HttpException ("Transfer is only allowed to .aspx and static files");
149 HttpRequest request = context.Request;
150 string oldQuery = request.QueryStringRaw;
151 if (queryString != null) {
152 request.QueryStringRaw = queryString;
153 } else if (!preserveForm) {
154 request.QueryStringRaw = String.Empty;
157 HttpResponse response = context.Response;
158 WebROCollection oldForm = request.Form as WebROCollection;
160 request.SetForm (new WebROCollection ());
163 TextWriter output = writer;
165 output = response.Output;
167 TextWriter previous = response.SetTextWriter (output);
168 string oldExePath = request.CurrentExecutionFilePath;
169 bool oldIsInclude = context.IsProcessingInclude;
172 context.PushHandler (handler);
173 if (is_static) // Not sure if this should apply to Page too
174 request.SetFilePath (exePath);
176 request.SetCurrentExePath (exePath);
177 context.IsProcessingInclude = isInclude;
179 if (!(handler is IHttpAsyncHandler)) {
180 handler.ProcessRequest (context);
182 IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler) handler;
183 IAsyncResult ar = asyncHandler.BeginProcessRequest (context, null, null);
184 ar.AsyncWaitHandle.WaitOne ();
185 asyncHandler.EndProcessRequest (ar);
188 if (oldQuery != request.QueryStringRaw) {
189 if (oldQuery != null && oldQuery.Length > 0) {
190 oldQuery = oldQuery.Substring (1); // Ignore initial '?'
191 request.QueryStringRaw = oldQuery; // which is added here.
193 request.QueryStringRaw = String.Empty;
196 response.SetTextWriter (previous);
198 request.SetForm (oldForm);
200 context.PopHandler ();
202 request.SetCurrentExePath (oldExePath);
203 context.IsProcessingInclude = oldIsInclude;
207 public Exception GetLastError ()
210 return HttpContext.Current.Error;
211 return context.Error;
214 public string HtmlDecode (string s)
216 return HttpUtility.HtmlDecode (s);
219 public void HtmlDecode (string s, TextWriter output)
221 HttpUtility.HtmlDecode (s, output);
224 public string HtmlEncode (string s)
226 return HttpUtility.HtmlEncode (s);
229 public void HtmlEncode (string s, TextWriter output)
231 HttpUtility.HtmlEncode (s, output);
234 public string MapPath (string path)
236 return context.Request.MapPath (path);
239 public void Transfer (string path)
241 Transfer (path, true);
244 public void Transfer (string path, bool preserveForm) {
245 Execute (path, null, preserveForm, true);
246 context.Response.End ();
249 public void Transfer (IHttpHandler handler, bool preserveForm)
252 throw new ArgumentNullException ("handler");
254 // TODO: see the MS doc and search for "enableViewStateMac": this method is not
255 // allowed for pages when preserveForm is true and the page IsCallback property
257 Execute (handler, null, preserveForm, context.Request.CurrentExecutionFilePath, null, true, true);
258 context.Response.End ();
261 public void Execute (IHttpHandler handler, TextWriter writer, bool preserveForm)
264 throw new ArgumentNullException ("handler");
266 Execute (handler, writer, preserveForm, context.Request.CurrentExecutionFilePath, null, false, true);
269 public static byte[] UrlTokenDecode (string input)
272 throw new ArgumentNullException ("input");
273 if (input.Length < 1)
275 byte[] bytes = Encoding.ASCII.GetBytes (input);
276 int inputLength = input.Length - 1;
277 int equalsCount = (int)(((char)bytes[inputLength]) - 0x30);
278 char[] ret = new char[inputLength + equalsCount];
280 for (; i < inputLength; i++) {
281 switch ((char)bytes[i]) {
291 ret[i] = (char)bytes[i];
295 while (equalsCount > 0) {
300 return Convert.FromBase64CharArray (ret, 0, ret.Length);
303 public static string UrlTokenEncode (byte[] input)
306 throw new ArgumentNullException ("input");
307 if (input.Length < 1)
309 string base64 = Convert.ToBase64String (input);
311 if (base64 == null || (retlen = base64.Length) == 0)
314 // MS.NET implementation seems to process the base64
315 // string before returning. It replaces the chars:
320 // Then removes trailing ==, which may appear in the
321 // base64 string, and replaces them with a single digit
322 // that's the count of removed '=' characters (0 if none
324 int equalsCount = 0x30;
325 while (retlen > 0 && base64[retlen - 1] == '=') {
329 char[] chars = new char[retlen + 1];
330 chars[retlen] = (char)equalsCount;
331 for (int i = 0; i < retlen; i++) {
342 chars[i] = base64[i];
346 return new string (chars);
350 public string UrlDecode (string s)
352 HttpRequest request = context.Request;
354 return HttpUtility.UrlDecode (s, request.ContentEncoding);
356 return HttpUtility.UrlDecode (s);
359 public void UrlDecode (string s, TextWriter output)
362 output.Write (UrlDecode (s));
365 public string UrlEncode (string s)
367 HttpResponse response = context.Response;
368 if (response != null)
369 return HttpUtility.UrlEncode (s, response.ContentEncoding);
371 return HttpUtility.UrlEncode (s);
374 public void UrlEncode (string s, TextWriter output)
377 output.Write (UrlEncode (s));
380 public string UrlPathEncode (string s)
385 int idx = s.IndexOf ('?');
388 s2 = s.Substring (0, idx);
389 s2 = HttpUtility.UrlEncode (s2) + s.Substring (idx);
391 s2 = HttpUtility.UrlEncode (s);
397 public string MachineName {
398 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
399 // Medium doesn't look heavy enough to replace this... reported as
400 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
401 [EnvironmentPermission (SecurityAction.Assert, Read = "COMPUTERNAME")]
402 get { return Environment.MachineName; }
405 public int ScriptTimeout {
406 get { return (int) context.ConfigTimeout.TotalSeconds; }
407 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
408 set { context.ConfigTimeout = TimeSpan.FromSeconds (value); }