You've already forked linux-packaging-mono
416 lines
12 KiB
C#
416 lines
12 KiB
C#
//
|
|
// 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
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
using System.IO;
|
|
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
|
|
{
|
|
//
|
|
// 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)
|
|
{
|
|
this.context = context;
|
|
}
|
|
|
|
public void ClearError ()
|
|
{
|
|
context.ClearError ();
|
|
}
|
|
|
|
[SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
|
|
public object CreateObject (string progID)
|
|
{
|
|
throw new HttpException (500, "COM is not supported");
|
|
}
|
|
|
|
[SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
|
|
public object CreateObject (Type type)
|
|
{
|
|
throw new HttpException (500, "COM is not supported");
|
|
}
|
|
|
|
[SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
|
|
public object CreateObjectFromClsid (string clsid)
|
|
{
|
|
throw new HttpException (500, "COM is not supported");
|
|
}
|
|
|
|
public void Execute (string path)
|
|
{
|
|
Execute (path, null, true);
|
|
}
|
|
|
|
public void Execute (string path, TextWriter writer)
|
|
{
|
|
Execute (path, writer, true);
|
|
}
|
|
|
|
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 (path.IndexOf (':') != -1)
|
|
throw new ArgumentException ("Invalid path.");
|
|
|
|
string queryString = null;
|
|
int qmark = path.IndexOf ('?');
|
|
if (qmark != -1) {
|
|
queryString = path.Substring (qmark + 1);
|
|
path = path.Substring (0, qmark);
|
|
}
|
|
|
|
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;
|
|
if (queryString != null) {
|
|
request.QueryStringRaw = queryString;
|
|
} else if (!preserveForm) {
|
|
request.QueryStringRaw = String.Empty;
|
|
}
|
|
|
|
HttpResponse response = context.Response;
|
|
WebROCollection oldForm = request.Form as WebROCollection;
|
|
if (!preserveForm) {
|
|
request.SetForm (new WebROCollection ());
|
|
}
|
|
|
|
TextWriter output = writer;
|
|
if (output == null)
|
|
output = response.Output;
|
|
|
|
TextWriter previous = response.SetTextWriter (output);
|
|
string oldExePath = request.CurrentExecutionFilePath;
|
|
bool oldIsInclude = context.IsProcessingInclude;
|
|
try {
|
|
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);
|
|
} else {
|
|
IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler) handler;
|
|
IAsyncResult ar = asyncHandler.BeginProcessRequest (context, null, null);
|
|
WaitHandle asyncWaitHandle = ar != null ? ar.AsyncWaitHandle : null;
|
|
if (asyncWaitHandle != null)
|
|
asyncWaitHandle.WaitOne ();
|
|
asyncHandler.EndProcessRequest (ar);
|
|
}
|
|
} finally {
|
|
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 (!preserveForm)
|
|
request.SetForm (oldForm);
|
|
|
|
context.PopHandler ();
|
|
request.SetCurrentExePath (oldExePath);
|
|
context.IsProcessingInclude = oldIsInclude;
|
|
}
|
|
}
|
|
|
|
public Exception GetLastError ()
|
|
{
|
|
if (context == null)
|
|
return HttpContext.Current.Error;
|
|
return context.Error;
|
|
}
|
|
|
|
public string HtmlDecode (string s)
|
|
{
|
|
return HttpUtility.HtmlDecode (s);
|
|
}
|
|
|
|
public void HtmlDecode (string s, TextWriter output)
|
|
{
|
|
HttpUtility.HtmlDecode (s, output);
|
|
}
|
|
|
|
public string HtmlEncode (string s)
|
|
{
|
|
return HttpUtility.HtmlEncode (s);
|
|
}
|
|
|
|
public void HtmlEncode (string s, TextWriter output)
|
|
{
|
|
HttpUtility.HtmlEncode (s, output);
|
|
}
|
|
|
|
public string MapPath (string 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);
|
|
}
|
|
|
|
[MonoTODO ("Always throws PlatformNotSupportedException.")]
|
|
public void TransferRequest (string path, bool preserveForm, string method, NameValueCollection headers)
|
|
{
|
|
throw new PlatformNotSupportedException ();
|
|
}
|
|
|
|
public void Transfer (string path)
|
|
{
|
|
Transfer (path, true);
|
|
}
|
|
|
|
public void Transfer (string path, bool preserveForm) {
|
|
Execute (path, null, preserveForm, true);
|
|
context.Response.End ();
|
|
}
|
|
|
|
public void Transfer (IHttpHandler handler, bool preserveForm)
|
|
{
|
|
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)
|
|
{
|
|
HttpRequest request = context.Request;
|
|
if(request != null)
|
|
return HttpUtility.UrlDecode (s, request.ContentEncoding);
|
|
else
|
|
return HttpUtility.UrlDecode (s);
|
|
}
|
|
|
|
public void UrlDecode (string s, TextWriter output)
|
|
{
|
|
if (s != null)
|
|
output.Write (UrlDecode (s));
|
|
}
|
|
|
|
public string UrlEncode (string s)
|
|
{
|
|
HttpResponse response = context.Response;
|
|
if (response != null)
|
|
return HttpUtility.UrlEncode (s, response.ContentEncoding);
|
|
else
|
|
return HttpUtility.UrlEncode (s);
|
|
}
|
|
|
|
public void UrlEncode (string s, TextWriter output)
|
|
{
|
|
if (s != null)
|
|
output.Write (UrlEncode (s));
|
|
}
|
|
|
|
public string UrlPathEncode (string s)
|
|
{
|
|
if (s == null)
|
|
return null;
|
|
|
|
int idx = s.IndexOf ('?');
|
|
string s2 = null;
|
|
if (idx != -1) {
|
|
s2 = s.Substring (0, idx);
|
|
s2 = HttpUtility.UrlEncode (s2) + s.Substring (idx);
|
|
} else {
|
|
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); }
|
|
}
|
|
}
|
|
}
|