2 // System.Web.HttpRequest.cs
6 // Miguel de Icaza (miguel@novell.com)
7 // Gonzalo Paniagua Javier (gonzalo@novell.com)
11 // Copyright (C) 2005-2010 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.Threading;
40 using System.Web.Configuration;
41 using System.Web.SessionState;
46 // Methods exposed through HttpContext.Server property
49 // CAS - no InheritanceDemand here as the class is sealed
50 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
51 public sealed class HttpServerUtility {
54 internal HttpServerUtility (HttpContext context)
56 this.context = context;
59 public void ClearError ()
61 context.ClearError ();
64 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
65 public object CreateObject (string progID)
67 throw new HttpException (500, "COM is not supported");
70 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
71 public object CreateObject (Type type)
73 throw new HttpException (500, "COM is not supported");
76 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
77 public object CreateObjectFromClsid (string clsid)
79 throw new HttpException (500, "COM is not supported");
82 public void Execute (string path)
84 Execute (path, null, true);
87 public void Execute (string path, TextWriter writer)
89 Execute (path, writer, true);
92 public void Execute (string path, bool preserveForm)
94 Execute (path, null, preserveForm);
97 public void Execute (string path, TextWriter writer, bool preserveForm)
99 Execute (path, writer, preserveForm, false);
102 void Execute (string path, TextWriter writer, bool preserveForm, bool isTransfer)
105 throw new ArgumentNullException ("path");
107 if (path.IndexOf (':') != -1)
108 throw new ArgumentException ("Invalid path.");
110 string queryString = null;
111 int qmark = path.IndexOf ('?');
113 queryString = path.Substring (qmark + 1);
114 path = path.Substring (0, qmark);
117 string exePath = UrlUtils.Combine (context.Request.BaseVirtualDir, path);
118 bool cookieless = false;
119 SessionStateSection config = WebConfigurationManager.GetWebApplicationSection ("system.web/sessionState") as SessionStateSection;
120 cookieless = SessionStateModule.IsCookieLess (context, config);
123 exePath = UrlUtils.RemoveSessionId (VirtualPathUtility.GetDirectory (exePath), exePath);
125 IHttpHandler handler = context.ApplicationInstance.GetHandler (context, exePath, true);
126 Execute (handler, writer, preserveForm, exePath, queryString, isTransfer, true);
129 internal void Execute (IHttpHandler handler, TextWriter writer, bool preserveForm, string exePath, string queryString, bool isTransfer, bool isInclude)
131 // If the target handler is not Page, the transfer must not occur.
132 // InTransit == true means we're being called from Transfer
133 bool is_static = (handler is StaticFileHandler);
134 if (isTransfer && !(handler is Page) && !is_static)
135 throw new HttpException ("Transfer is only allowed to .aspx and static files");
137 HttpRequest request = context.Request;
138 string oldQuery = request.QueryStringRaw;
139 if (queryString != null) {
140 request.QueryStringRaw = queryString;
141 } else if (!preserveForm) {
142 request.QueryStringRaw = String.Empty;
145 HttpResponse response = context.Response;
146 WebROCollection oldForm = request.Form as WebROCollection;
148 request.SetForm (new WebROCollection ());
151 TextWriter output = writer;
153 output = response.Output;
155 TextWriter previous = response.SetTextWriter (output);
156 string oldExePath = request.CurrentExecutionFilePath;
157 bool oldIsInclude = context.IsProcessingInclude;
159 context.PushHandler (handler);
160 if (is_static) // Not sure if this should apply to Page too
161 request.SetFilePath (exePath);
163 request.SetCurrentExePath (exePath);
164 context.IsProcessingInclude = isInclude;
166 if (!(handler is IHttpAsyncHandler)) {
167 handler.ProcessRequest (context);
169 IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler) handler;
170 IAsyncResult ar = asyncHandler.BeginProcessRequest (context, null, null);
171 WaitHandle asyncWaitHandle = ar != null ? ar.AsyncWaitHandle : null;
172 if (asyncWaitHandle != null)
173 asyncWaitHandle.WaitOne ();
174 asyncHandler.EndProcessRequest (ar);
177 if (oldQuery != request.QueryStringRaw) {
178 if (oldQuery != null && oldQuery.Length > 0) {
179 oldQuery = oldQuery.Substring (1); // Ignore initial '?'
180 request.QueryStringRaw = oldQuery; // which is added here.
182 request.QueryStringRaw = String.Empty;
185 response.SetTextWriter (previous);
187 request.SetForm (oldForm);
189 context.PopHandler ();
190 request.SetCurrentExePath (oldExePath);
191 context.IsProcessingInclude = oldIsInclude;
195 public Exception GetLastError ()
198 return HttpContext.Current.Error;
199 return context.Error;
202 public string HtmlDecode (string s)
204 return HttpUtility.HtmlDecode (s);
207 public void HtmlDecode (string s, TextWriter output)
209 HttpUtility.HtmlDecode (s, output);
212 public string HtmlEncode (string s)
214 return HttpUtility.HtmlEncode (s);
217 public void HtmlEncode (string s, TextWriter output)
219 HttpUtility.HtmlEncode (s, output);
222 public string MapPath (string path)
224 return context.Request.MapPath (path);
228 public void TransferRequest (string path)
230 TransferRequest (path, false, null, null);
233 public void TransferRequest (string path, bool preserveForm)
235 TransferRequest (path, preserveForm, null, null);
238 [MonoTODO ("Always throws PlatformNotSupportedException.")]
239 public void TransferRequest (string path, bool preserveForm, string method, NameValueCollection headers)
241 throw new PlatformNotSupportedException ();
244 public void Transfer (string path)
246 Transfer (path, true);
249 public void Transfer (string path, bool preserveForm) {
250 Execute (path, null, preserveForm, true);
251 context.Response.End ();
254 public void Transfer (IHttpHandler handler, bool preserveForm)
257 throw new ArgumentNullException ("handler");
259 // TODO: see the MS doc and search for "enableViewStateMac": this method is not
260 // allowed for pages when preserveForm is true and the page IsCallback property
262 Execute (handler, null, preserveForm, context.Request.CurrentExecutionFilePath, null, true, true);
263 context.Response.End ();
266 public void Execute (IHttpHandler handler, TextWriter writer, bool preserveForm)
269 throw new ArgumentNullException ("handler");
271 Execute (handler, writer, preserveForm, context.Request.CurrentExecutionFilePath, null, false, true);
274 public static byte[] UrlTokenDecode (string input)
277 throw new ArgumentNullException ("input");
278 if (input.Length < 1)
280 byte[] bytes = Encoding.ASCII.GetBytes (input);
281 int inputLength = input.Length - 1;
282 int equalsCount = (int)(((char)bytes[inputLength]) - 0x30);
283 char[] ret = new char[inputLength + equalsCount];
285 for (; i < inputLength; i++) {
286 switch ((char)bytes[i]) {
296 ret[i] = (char)bytes[i];
300 while (equalsCount > 0) {
305 return Convert.FromBase64CharArray (ret, 0, ret.Length);
308 public static string UrlTokenEncode (byte[] input)
311 throw new ArgumentNullException ("input");
312 if (input.Length < 1)
314 string base64 = Convert.ToBase64String (input);
316 if (base64 == null || (retlen = base64.Length) == 0)
319 // MS.NET implementation seems to process the base64
320 // string before returning. It replaces the chars:
325 // Then removes trailing ==, which may appear in the
326 // base64 string, and replaces them with a single digit
327 // that's the count of removed '=' characters (0 if none
329 int equalsCount = 0x30;
330 while (retlen > 0 && base64[retlen - 1] == '=') {
334 char[] chars = new char[retlen + 1];
335 chars[retlen] = (char)equalsCount;
336 for (int i = 0; i < retlen; i++) {
347 chars[i] = base64[i];
351 return new string (chars);
354 public string UrlDecode (string s)
356 HttpRequest request = context.Request;
358 return HttpUtility.UrlDecode (s, request.ContentEncoding);
360 return HttpUtility.UrlDecode (s);
363 public void UrlDecode (string s, TextWriter output)
366 output.Write (UrlDecode (s));
369 public string UrlEncode (string s)
371 HttpResponse response = context.Response;
372 if (response != null)
373 return HttpUtility.UrlEncode (s, response.ContentEncoding);
375 return HttpUtility.UrlEncode (s);
378 public void UrlEncode (string s, TextWriter output)
381 output.Write (UrlEncode (s));
384 public string UrlPathEncode (string s)
389 int idx = s.IndexOf ('?');
392 s2 = s.Substring (0, idx);
393 s2 = HttpUtility.UrlEncode (s2) + s.Substring (idx);
395 s2 = HttpUtility.UrlEncode (s);
401 public string MachineName {
402 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
403 // Medium doesn't look heavy enough to replace this... reported as
404 [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
405 [EnvironmentPermission (SecurityAction.Assert, Read = "COMPUTERNAME")]
406 get { return Environment.MachineName; }
409 public int ScriptTimeout {
410 get { return (int) context.ConfigTimeout.TotalSeconds; }
411 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
412 set { context.ConfigTimeout = TimeSpan.FromSeconds (value); }