+//
+// System.Web.HttpRequest.cs
+//
+//
+// Author:
+// Miguel de Icaza (miguel@novell.com)
+// Gonzalo Paniagua Javier (gonzalo@novell.com)
+//
+//
+// Copyright (C) 2005-2010 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-/**
- * Namespace: System.Web
- * Class: HttpServerUtility
- *
- * Authosr:
- * Wictor Wilén (wictor@ibizkit.se)
- * Patrik Torstensson (patrik.torstensson@labs2.com)
- * Gonzalo Paniagua Javier (gonzalo@ximian.com)
- *
- * (c) Wictor Wilén (2002)
- * (c) 2002 Patrik Torstensson
- * (c) 2003 Ximian, Inc. (http://www.ximian.com)
- *
- * (This log is no longer maintained)
- * ---------------------------------------
- * 2002-03-27 Wictor Started implementation
- * 2002-04-09 Patrik Added HttpContext constructor
- * 2002-04-10 Patrik Moved encoding to HttpUtility and
- * fixed all functions that used
- * HttpContext
- *
- */
-using System;
-using System.Collections.Specialized;
+
using System.IO;
-using System.Text;
-using System.Web.Hosting;
using System.Web.UI;
using System.Web.Util;
+using System.Collections.Specialized;
+using System.Security.Permissions;
+using System.Text;
+using System.Threading;
+using System.Web.Configuration;
+using System.Web.SessionState;
namespace System.Web
{
- public sealed class HttpServerUtility
- {
- private static string _name;
-
- private HttpContext _Context;
- private HttpApplication _Application;
-
- internal HttpServerUtility (HttpContext Context)
+ //
+ // Methods exposed through HttpContext.Server property
+ //
+
+ // CAS - no InheritanceDemand here as the class is sealed
+ [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
+ public sealed class HttpServerUtility {
+ HttpContext context;
+
+ internal HttpServerUtility (HttpContext context)
{
- _Context = Context;
- }
-
- internal HttpServerUtility (HttpApplication app)
- {
- _Application = app;
- }
-
- // Properties
-
-
- /// <summary>
- /// Gets the server's computer name.
- /// </summary>
- public string MachineName {
- get {
- if(_name == null)
- _name = Environment.MachineName;
-
- return _name;
- }
- }
-
- public int ScriptTimeout {
- get {
- return (int) _Context.ConfigTimeout.TotalSeconds;
- }
- set {
- if (value <= 0)
- throw new ArgumentOutOfRangeException ("value");
-
- _Context.ConfigTimeout = new TimeSpan (0, 0, value);
- }
+ this.context = context;
}
- // Methods
-
- /// <summary>
- /// Clears the previous exception.
- /// </summary>
public void ClearError ()
{
- if (null != _Context) {
- _Context.ClearError ();
- return;
- }
-
- if (null != _Application) {
- _Application.ClearError ();
- }
+ context.ClearError ();
}
-
- /// <summary>
- /// Creates a server instance of a COM object identified by the object's Programmatic Identifier (ProgID).
- /// </summary>
- /// <param name="progID">The class or type of object to be instantiated. </param>
- /// <returns>The new object.</returns>
+ [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
public object CreateObject (string progID)
{
- return CreateObject (Type.GetTypeFromProgID (progID));
+ throw new HttpException (500, "COM is not supported");
}
-
- /// <summary>
- /// Creates a server instance of a COM object identified by the object's type.
- /// </summary>
- /// <param name="type">A Type representing the object to create. </param>
- /// <returns>The new object.</returns>
+ [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
public object CreateObject (Type type)
{
- return Activator.CreateInstance (type);
+ throw new HttpException (500, "COM is not supported");
}
-
- /// <summary>
- /// Creates a server instance of a COM object identified by the object's class identifier (CLSID).
- /// </summary>
- /// <param name="clsid">The class identifier of the object to be instantiated. </param>
- /// <returns>The new object.</returns>
+ [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
public object CreateObjectFromClsid (string clsid)
{
- Guid guid = new Guid (clsid);
- return CreateObject (Type.GetTypeFromCLSID (guid));
+ throw new HttpException (500, "COM is not supported");
}
-
- /// <summary>
- /// Executes a request to another page using the specified URL path to the page.
- /// </summary>
- /// <param name="path">The URL path of the new request. </param>
public void Execute (string path)
{
- Execute (path, null);
+ Execute (path, null, true);
}
-
- /// <summary>
- /// Executes a request to another page using the specified URL path to the page.
- /// A TextWriter captures output from the page.
- /// </summary>
- /// <param name="path">The URL path of the new request. </param>
- /// <param name="writer">The TextWriter to capture the output. </param>
public void Execute (string path, TextWriter writer)
{
- Execute (path, writer, false);
+ Execute (path, writer, true);
}
-#if NET_2_0
- public
-#else
- internal
-#endif
- void Execute (string path, TextWriter writer, bool preserveQuery)
+ public void Execute (string path, bool preserveForm)
+ {
+ Execute (path, null, preserveForm);
+ }
+
+ public void Execute (string path, TextWriter writer, bool preserveForm)
+ {
+ Execute (path, writer, preserveForm, false);
+ }
+
+ void Execute (string path, TextWriter writer, bool preserveForm, bool isTransfer)
{
if (path == null)
throw new ArgumentNullException ("path");
- if (_Context == null)
- throw new HttpException ("No context available.");
-
if (path.IndexOf (':') != -1)
throw new ArgumentException ("Invalid path.");
+ string queryString = null;
int qmark = path.IndexOf ('?');
- string query;
if (qmark != -1) {
- query = path.Substring (qmark + 1);
+ queryString = path.Substring (qmark + 1);
path = path.Substring (0, qmark);
- } else {
- query = "";
}
- HttpRequest request = _Context.Request;
- HttpResponse response = _Context.Response;
+ string exePath = UrlUtils.Combine (context.Request.BaseVirtualDir, path);
+ bool cookieless = false;
+ SessionStateSection config = WebConfigurationManager.GetWebApplicationSection ("system.web/sessionState") as SessionStateSection;
+ cookieless = SessionStateModule.IsCookieLess (context, config);
+
+ if (cookieless)
+ exePath = UrlUtils.RemoveSessionId (VirtualPathUtility.GetDirectory (exePath), exePath);
+
+ IHttpHandler handler = context.ApplicationInstance.GetHandler (context, exePath, true);
+ Execute (handler, writer, preserveForm, exePath, queryString, isTransfer, true);
+ }
+
+ internal void Execute (IHttpHandler handler, TextWriter writer, bool preserveForm, string exePath, string queryString, bool isTransfer, bool isInclude)
+ {
+ // If the target handler is not Page, the transfer must not occur.
+ // InTransit == true means we're being called from Transfer
+ bool is_static = (handler is StaticFileHandler);
+ if (isTransfer && !(handler is Page) && !is_static)
+ throw new HttpException ("Transfer is only allowed to .aspx and static files");
+ HttpRequest request = context.Request;
string oldQuery = request.QueryStringRaw;
- request.QueryStringRaw = query;
+ if (queryString != null) {
+ request.QueryStringRaw = queryString;
+ } else if (!preserveForm) {
+ request.QueryStringRaw = String.Empty;
+ }
- HttpValueCollection oldForm = null;
- if (!preserveQuery) {
- oldForm = _Context.Request.Form as HttpValueCollection;
- _Context.Request.SetForm (new HttpValueCollection ());
+ HttpResponse response = context.Response;
+ WebROCollection oldForm = request.Form as WebROCollection;
+ if (!preserveForm) {
+ request.SetForm (new WebROCollection ());
}
- string filePath = _Context.Request.MapPath (path);
TextWriter output = writer;
if (output == null)
output = response.Output;
-
- string oldFilePath = request.FilePath;
- request.SetCurrentExePath (UrlUtils.Combine (_Context.Request.BaseVirtualDir, path));
- IHttpHandler handler = _Context.ApplicationInstance.CreateHttpHandler (_Context,
- request.RequestType,
- path,
- filePath);
- TextWriter previous = null;
+
+ TextWriter previous = response.SetTextWriter (output);
+ string oldExePath = request.CurrentExecutionFilePath;
+ bool oldIsInclude = context.IsProcessingInclude;
try {
- previous = response.SetTextWriter (output);
+ context.PushHandler (handler);
+ if (is_static) // Not sure if this should apply to Page too
+ request.SetFilePath (exePath);
+
+ request.SetCurrentExePath (exePath);
+ context.IsProcessingInclude = isInclude;
+
if (!(handler is IHttpAsyncHandler)) {
- handler.ProcessRequest (_Context);
+ handler.ProcessRequest (context);
} else {
IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler) handler;
- IAsyncResult ar = asyncHandler.BeginProcessRequest (_Context, null, null);
- ar.AsyncWaitHandle.WaitOne ();
+ IAsyncResult ar = asyncHandler.BeginProcessRequest (context, null, null);
+ WaitHandle asyncWaitHandle = ar != null ? ar.AsyncWaitHandle : null;
+ if (asyncWaitHandle != null)
+ asyncWaitHandle.WaitOne ();
asyncHandler.EndProcessRequest (ar);
}
} finally {
- request.SetCurrentExePath (oldFilePath);
- request.QueryStringRaw = oldQuery;
+ if (oldQuery != request.QueryStringRaw) {
+ if (oldQuery != null && oldQuery.Length > 0) {
+ oldQuery = oldQuery.Substring (1); // Ignore initial '?'
+ request.QueryStringRaw = oldQuery; // which is added here.
+ } else
+ request.QueryStringRaw = String.Empty;
+ }
+
response.SetTextWriter (previous);
- if (!preserveQuery)
- _Context.Request.SetForm (oldForm);
- }
+ if (!preserveForm)
+ request.SetForm (oldForm);
+ context.PopHandler ();
+ request.SetCurrentExePath (oldExePath);
+ context.IsProcessingInclude = oldIsInclude;
+ }
}
- /// <summary>
- /// Returns the previous exception.
- /// </summary>
- /// <returns>The previous exception that was thrown.</returns>
public Exception GetLastError ()
{
- if (_Context == null)
- return null;
-
- return _Context.Error;
+ if (context == null)
+ return HttpContext.Current.Error;
+ return context.Error;
}
-
-
- /// <summary>
- /// Decodes an HTML-encoded string and returns the decoded string.
- /// </summary>
- /// <param name="s">The HTML string to decode. </param>
- /// <returns>The decoded text.</returns>
public string HtmlDecode (string s)
{
return HttpUtility.HtmlDecode (s);
}
-
- /// <summary>
- /// Decodes an HTML-encoded string and sends the resulting output to a TextWriter output stream.
- /// </summary>
- /// <param name="s">The HTML string to decode</param>
- /// <param name="output">The TextWriter output stream containing the decoded string. </param>
public void HtmlDecode (string s, TextWriter output)
{
- output.Write (HttpUtility.HtmlDecode (s));
+ HttpUtility.HtmlDecode (s, output);
}
- /// <summary>
- /// HTML-encodes a string and returns the encoded string.
- /// </summary>
- /// <param name="s">The text string to encode. </param>
- /// <returns>The HTML-encoded text.</returns>
public string HtmlEncode (string s)
{
return HttpUtility.HtmlEncode (s);
}
- /// <summary>
- /// HTML-encodes a string and sends the resulting output to a TextWriter output stream.
- /// </summary>
- /// <param name="s">The string to encode. </param>
- /// <param name="output">The TextWriter output stream containing the encoded string. </param>
public void HtmlEncode (string s, TextWriter output)
{
- output.Write (HtmlEncode (s));
+ HttpUtility.HtmlEncode (s, output);
}
-
- /// <summary>
- /// Returns the physical file path that corresponds to the specified virtual path on the Web server.
- /// </summary>
- /// <param name="path">The virtual path on the Web server. </param>
- /// <returns>The physical file path that corresponds to path.</returns>
public string MapPath (string path)
{
- if (null == _Context)
- throw new HttpException ("MapPath is not available");
+ return context.Request.MapPath (path);
+ }
- return _Context.Request.MapPath (path);
+
+ public void TransferRequest (string path)
+ {
+ TransferRequest (path, false, null, null);
+ }
+
+ public void TransferRequest (string path, bool preserveForm)
+ {
+ TransferRequest (path, preserveForm, null, null);
}
- /// <summary>
- /// Terminates execution of the current page and begins execution of a new page using the specified
- /// URL path to the page.
- /// </summary>
- /// <param name="path">The URL path of the new page on the server to execute. </param>
+ [MonoTODO ("Always throws PlatformNotSupportedException.")]
+ public void TransferRequest (string path, bool preserveForm, string method, NameValueCollection headers)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
public void Transfer (string path)
{
- // If it's a page and a postback, don't pass form data
- // See bug #65613.
- bool preserveForm = true;
- if (_Context.Handler is Page) {
- Page page = (Page) _Context.Handler;
- preserveForm = !page.IsPostBack;
- }
+ Transfer (path, true);
+ }
- Transfer (path, preserveForm);
+ public void Transfer (string path, bool preserveForm) {
+ Execute (path, null, preserveForm, true);
+ context.Response.End ();
}
- /// <summary>
- /// Terminates execution of the current page and begins execution of a new page using the specified
- /// URL path to the page. Specifies whether to clear the QueryString and Form collections.
- /// </summary>
- /// <param name="path">The URL path of the new page on the server to execute. </param>
- /// <param name="preserveForm">If true, the QueryString and Form collections are preserved. If false,
- /// they are cleared. The default is false. </param>
- public void Transfer (string path, bool preserveForm)
+ public void Transfer (IHttpHandler handler, bool preserveForm)
{
- Execute (path, null, preserveForm);
- _Context.Response.End ();
- }
-
- /// <summary>
- /// URL-decodes a string and returns the decoded string.
- /// </summary>
- /// <param name="s">The text string to decode. </param>
- /// <returns>The decoded text.</returns>
- /// <remarks>
- /// Post/html encoding @ ftp://ftp.isi.edu/in-notes/rfc1866.txt
- /// Uncomment the line marked with RFC1738 to get pure RFC1738
- /// and it will also consider the RFC1866 (ftp://ftp.isi.edu/in-notes/rfc1866.txt)
- /// `application/x-www-form-urlencoded' format
- /// </remarks>
+ if (handler == null)
+ throw new ArgumentNullException ("handler");
+
+ // TODO: see the MS doc and search for "enableViewStateMac": this method is not
+ // allowed for pages when preserveForm is true and the page IsCallback property
+ // is true.
+ Execute (handler, null, preserveForm, context.Request.CurrentExecutionFilePath, null, true, true);
+ context.Response.End ();
+ }
+
+ public void Execute (IHttpHandler handler, TextWriter writer, bool preserveForm)
+ {
+ if (handler == null)
+ throw new ArgumentNullException ("handler");
+
+ Execute (handler, writer, preserveForm, context.Request.CurrentExecutionFilePath, null, false, true);
+ }
+
+ public static byte[] UrlTokenDecode (string input)
+ {
+ if (input == null)
+ throw new ArgumentNullException ("input");
+ if (input.Length < 1)
+ return new byte[0];
+ byte[] bytes = Encoding.ASCII.GetBytes (input);
+ int inputLength = input.Length - 1;
+ int equalsCount = (int)(((char)bytes[inputLength]) - 0x30);
+ char[] ret = new char[inputLength + equalsCount];
+ int i = 0;
+ for (; i < inputLength; i++) {
+ switch ((char)bytes[i]) {
+ case '-':
+ ret[i] = '+';
+ break;
+
+ case '_':
+ ret[i] = '/';
+ break;
+
+ default:
+ ret[i] = (char)bytes[i];
+ break;
+ }
+ }
+ while (equalsCount > 0) {
+ ret[i++] = '=';
+ equalsCount--;
+ }
+
+ return Convert.FromBase64CharArray (ret, 0, ret.Length);
+ }
+
+ public static string UrlTokenEncode (byte[] input)
+ {
+ if (input == null)
+ throw new ArgumentNullException ("input");
+ if (input.Length < 1)
+ return String.Empty;
+ string base64 = Convert.ToBase64String (input);
+ int retlen;
+ if (base64 == null || (retlen = base64.Length) == 0)
+ return String.Empty;
+
+ // MS.NET implementation seems to process the base64
+ // string before returning. It replaces the chars:
+ //
+ // + with -
+ // / with _
+ //
+ // Then removes trailing ==, which may appear in the
+ // base64 string, and replaces them with a single digit
+ // that's the count of removed '=' characters (0 if none
+ // were removed)
+ int equalsCount = 0x30;
+ while (retlen > 0 && base64[retlen - 1] == '=') {
+ equalsCount++;
+ retlen--;
+ }
+ char[] chars = new char[retlen + 1];
+ chars[retlen] = (char)equalsCount;
+ for (int i = 0; i < retlen; i++) {
+ switch (base64[i]) {
+ case '+':
+ chars[i] = '-';
+ break;
+
+ case '/':
+ chars[i] = '_';
+ break;
+
+ default:
+ chars[i] = base64[i];
+ break;
+ }
+ }
+ return new string (chars);
+ }
+
public string UrlDecode (string s)
{
- return HttpUtility.UrlDecode (s);
+ HttpRequest request = context.Request;
+ if(request != null)
+ return HttpUtility.UrlDecode (s, request.ContentEncoding);
+ else
+ return HttpUtility.UrlDecode (s);
}
- /// <summary>
- /// Decodes an HTML string received in a URL and sends the resulting output to a TextWriter output stream.
- /// </summary>
- /// <param name="s"></param>
- /// <param name="output"></param>
public void UrlDecode (string s, TextWriter output)
{
if (s != null)
output.Write (UrlDecode (s));
}
- /// <summary>
- /// URL-encodes a string and returns the encoded string.
- /// </summary>
- /// <param name="s">The text to URL-encode. </param>
- /// <returns>The URL encoded text.</returns>
public string UrlEncode (string s)
{
- return HttpUtility.UrlEncode (s);
+ HttpResponse response = context.Response;
+ if (response != null)
+ return HttpUtility.UrlEncode (s, response.ContentEncoding);
+ else
+ return HttpUtility.UrlEncode (s);
}
- /// <summary>
- /// URL encodes a string and sends the resulting output to a TextWriter output stream.
- /// </summary>
- /// <param name="s">The text string to encode. </param>
- /// <param name="output">The TextWriter output stream containing the encoded string. </param>
public void UrlEncode (string s, TextWriter output)
{
if (s != null)
output.Write (UrlEncode (s));
}
- /// <summary>
- /// URL-encodes the path portion of a URL string and returns the encoded string.
- /// </summary>
- /// <param name="s">The text to URL-encode.</param>
- /// <returns>The URL encoded text.</returns>
- /// <remarks>Does not do any browser specific adjustments, just encode everything</remarks>
public string UrlPathEncode (string s)
{
if (s == null)
return null;
- int idx = s.IndexOf ("?");
+ int idx = s.IndexOf ('?');
string s2 = null;
if (idx != -1) {
- s2 = s.Substring (0, idx-1);
- s2 = UrlEncode (s2) + s.Substring (idx);
+ s2 = s.Substring (0, idx);
+ s2 = HttpUtility.UrlEncode (s2) + s.Substring (idx);
} else {
- s2 = UrlEncode (s);
+ s2 = HttpUtility.UrlEncode (s);
}
return s2;
}
+
+ public string MachineName {
+ [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
+ // Medium doesn't look heavy enough to replace this... reported as
+ [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
+ [EnvironmentPermission (SecurityAction.Assert, Read = "COMPUTERNAME")]
+ get { return Environment.MachineName; }
+ }
+
+ public int ScriptTimeout {
+ get { return (int) context.ConfigTimeout.TotalSeconds; }
+ [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
+ set { context.ConfigTimeout = TimeSpan.FromSeconds (value); }
+ }
}
}