2016-08-03 10:59:49 +00:00
//------------------------------------------------------------------------------
// <copyright file="httpserverutility.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/ *
* Server intrinsic used to match ASP ' s object model
*
* Copyright ( c ) 1999 Microsoft Corporation
* /
// Don't entity encode high chars (160 to 256), to fix bugs VSWhidbey 85857/111927
//
#define ENTITY_ENCODE_HIGH_ASCII_CHARS
namespace System.Web {
using System.Collections ;
using System.Collections.Specialized ;
using System.Globalization ;
using System.IO ;
using System.Security.Permissions ;
using System.Text ;
using System.Threading ;
using System.Web.Configuration ;
using System.Web.Hosting ;
using System.Web.UI ;
using System.Web.Util ;
internal abstract class ErrorFormatterGenerator {
internal abstract ErrorFormatter GetErrorFormatter ( Exception e ) ;
}
/// <devdoc>
/// <para>
/// Provides several
/// helper methods that can be used in the processing of Web requests.
/// </para>
/// </devdoc>
public sealed class HttpServerUtility {
private HttpContext _context ;
private HttpApplication _application ;
private static IDictionary _cultureCache = Hashtable . Synchronized ( new Hashtable ( ) ) ;
internal HttpServerUtility ( HttpContext context ) {
_context = context ;
}
internal HttpServerUtility ( HttpApplication application ) {
_application = application ;
}
//
// Misc ASP compatibility methods
//
/// <devdoc>
/// <para>
/// Instantiates a COM object identified via a progid.
/// </para>
/// </devdoc>
[SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
public object CreateObject ( string progID ) {
EnsureHasNotTransitionedToWebSocket ( ) ;
Type type = null ;
object obj = null ;
try {
#if ! FEATURE_PAL // FEATURE_PAL does not enable COM
type = Type . GetTypeFromProgID ( progID ) ;
#else // !FEATURE_PAL
throw new NotImplementedException ( "ROTORTODO" ) ;
#endif // !FEATURE_PAL
}
catch {
}
if ( type = = null ) {
throw new HttpException ( SR . GetString ( SR . Could_not_create_object_of_type , progID ) ) ;
}
// Disallow Apartment components in non-compat mode
AspCompatApplicationStep . CheckThreadingModel ( progID , type . GUID ) ;
// Instantiate the object
obj = Activator . CreateInstance ( type ) ;
// For ASP compat: take care of OnPageStart/OnPageEnd
AspCompatApplicationStep . OnPageStart ( obj ) ;
return obj ;
}
/// <devdoc>
/// <para>
/// Instantiates a COM object identified via a Type.
/// </para>
/// </devdoc>
[SecurityPermission(SecurityAction.Demand, UnmanagedCode=true)]
public object CreateObject ( Type type ) {
EnsureHasNotTransitionedToWebSocket ( ) ;
// Disallow Apartment components in non-compat mode
AspCompatApplicationStep . CheckThreadingModel ( type . FullName , type . GUID ) ;
// Instantiate the object
Object obj = Activator . CreateInstance ( type ) ;
// For ASP compat: take care of OnPageStart/OnPageEnd
AspCompatApplicationStep . OnPageStart ( obj ) ;
return obj ;
}
/// <devdoc>
/// <para>
/// Instantiates a COM object identified via a clsid.
/// </para>
/// </devdoc>
[SecurityPermission(SecurityAction.Demand, UnmanagedCode=true)]
public object CreateObjectFromClsid ( string clsid ) {
EnsureHasNotTransitionedToWebSocket ( ) ;
Type type = null ;
object obj = null ;
// Create a Guid out of it
Guid guid = new Guid ( clsid ) ;
// Disallow Apartment components in non-compat mode
AspCompatApplicationStep . CheckThreadingModel ( clsid , guid ) ;
try {
#if ! FEATURE_PAL // FEATURE_PAL does not enable COM
type = Type . GetTypeFromCLSID ( guid , null , true /*throwOnError*/ ) ;
#else // !FEATURE_PAL
throw new NotImplementedException ( "ROTORTODO" ) ;
#endif // !FEATURE_PAL
// Instantiate the object
obj = Activator . CreateInstance ( type ) ;
}
catch {
}
if ( obj = = null ) {
throw new HttpException (
SR . GetString ( SR . Could_not_create_object_from_clsid , clsid ) ) ;
}
// For ASP compat: take care of OnPageStart/OnPageEnd
AspCompatApplicationStep . OnPageStart ( obj ) ;
return obj ;
}
// Internal static method that returns a read-only, non-user override accounted, CultureInfo object
internal static CultureInfo CreateReadOnlyCultureInfo ( string name ) {
if ( ! _cultureCache . Contains ( name ) ) {
// To be threadsafe, get the lock before creating
lock ( _cultureCache ) {
if ( _cultureCache [ name ] = = null ) {
_cultureCache [ name ] = CultureInfo . ReadOnly ( new CultureInfo ( name ) ) ;
}
}
}
return ( CultureInfo ) _cultureCache [ name ] ;
}
// Internal static method that returns a read-only, non-user override accounted, culture specific CultureInfo object
internal static CultureInfo CreateReadOnlySpecificCultureInfo ( string name ) {
if ( name . IndexOf ( '-' ) > 0 ) {
return CreateReadOnlyCultureInfo ( name ) ;
}
CultureInfo ci = CultureInfo . CreateSpecificCulture ( name ) ;
if ( ! _cultureCache . Contains ( ci . Name ) ) {
//To be threadsafe, get the lock before creating
lock ( _cultureCache ) {
if ( _cultureCache [ ci . Name ] = = null ) {
_cultureCache [ ci . Name ] = CultureInfo . ReadOnly ( ci ) ;
}
}
}
return ( CultureInfo ) _cultureCache [ ci . Name ] ;
}
// Internal static method that returns a read-only, non-user override accounted, CultureInfo object
internal static CultureInfo CreateReadOnlyCultureInfo ( int culture ) {
if ( ! _cultureCache . Contains ( culture ) ) {
// To be threadsafe, get the lock before creating
lock ( _cultureCache ) {
if ( _cultureCache [ culture ] = = null ) {
_cultureCache [ culture ] = CultureInfo . ReadOnly ( new CultureInfo ( culture ) ) ;
}
}
}
return ( CultureInfo ) _cultureCache [ culture ] ;
}
/// <devdoc>
/// <para>
/// Maps a virtual path to a physical path.
/// </para>
/// </devdoc>
public string MapPath ( string path ) {
if ( _context = = null )
throw new HttpException ( SR . GetString ( SR . Server_not_available ) ) ;
// Disable hiding the request so that Server.MapPath works when called from
// Application_Start in integrated mode
bool unhideRequest = _context . HideRequestResponse ;
string realPath ;
try {
if ( unhideRequest ) {
_context . HideRequestResponse = false ;
}
realPath = _context . Request . MapPath ( path ) ;
}
finally {
if ( unhideRequest ) {
_context . HideRequestResponse = true ;
}
}
return realPath ;
}
/// <devdoc>
/// <para>Returns the last recorded exception.</para>
/// </devdoc>
public Exception GetLastError ( ) {
if ( _context ! = null )
return _context . Error ;
else if ( _application ! = null )
return _application . LastError ;
else
return null ;
}
/// <devdoc>
/// <para>Clears the last error.</para>
/// </devdoc>
public void ClearError ( ) {
if ( _context ! = null )
_context . ClearError ( ) ;
else if ( _application ! = null )
_application . ClearError ( ) ;
}
//
// Server.Transfer/Server.Execute -- child requests
//
/// <devdoc>
/// <para>
/// Executes a new request (using the specified URL path as the target). Unlike
/// the Transfer method, execution of the original page continues after the executed
/// page completes.
/// </para>
/// </devdoc>
public void Execute ( string path ) {
Execute ( path , null , true /*preserveForm*/ ) ;
}
/// <devdoc>
/// <para>
/// Executes a new request (using the specified URL path as the target). Unlike
/// the Transfer method, execution of the original page continues after the executed
/// page completes.
/// </para>
/// </devdoc>
public void Execute ( string path , TextWriter writer ) {
Execute ( path , writer , true /*preserveForm*/ ) ;
}
/// <devdoc>
/// <para>
/// Executes a new request (using the specified URL path as the target). Unlike
/// the Transfer method, execution of the original page continues after the executed
/// page completes.
/// If preserveForm is false, the QueryString and Form collections are cleared.
/// </para>
/// </devdoc>
public void Execute ( string path , bool preserveForm ) {
Execute ( path , null , preserveForm ) ;
}
/// <devdoc>
/// <para>
/// Executes a new request (using the specified URL path as the target). Unlike
/// the Transfer method, execution of the original page continues after the executed
/// page completes.
/// If preserveForm is false, the QueryString and Form collections are cleared.
/// </para>
/// </devdoc>
public void Execute ( string path , TextWriter writer , bool preserveForm ) {
EnsureHasNotTransitionedToWebSocket ( ) ;
if ( _context = = null )
throw new HttpException ( SR . GetString ( SR . Server_not_available ) ) ;
if ( path = = null )
throw new ArgumentNullException ( "path" ) ;
string queryStringOverride = null ;
HttpRequest request = _context . Request ;
HttpResponse response = _context . Response ;
// Remove potential cookie-less session id (ASURT 100558)
path = response . RemoveAppPathModifier ( path ) ;
// Allow query string override
int iqs = path . IndexOf ( '?' ) ;
if ( iqs > = 0 ) {
queryStringOverride = path . Substring ( iqs + 1 ) ;
path = path . Substring ( 0 , iqs ) ;
}
if ( ! UrlPath . IsValidVirtualPathWithoutProtocol ( path ) ) {
throw new ArgumentException ( SR . GetString ( SR . Invalid_path_for_child_request , path ) ) ;
}
VirtualPath virtualPath = VirtualPath . Create ( path ) ;
// Find the handler for the path
IHttpHandler handler = null ;
string physPath = request . MapPath ( virtualPath ) ; // get physical path
VirtualPath filePath = request . FilePathObject . Combine ( virtualPath ) ; // vpath
// Demand read access to the physical path of the target handler
InternalSecurityPermissions . FileReadAccess ( physPath ) . Demand ( ) ;
// We need to Assert since there typically is user code on the stack (VSWhidbey 270965)
if ( HttpRuntime . IsLegacyCas ) {
InternalSecurityPermissions . Unrestricted . Assert ( ) ;
}
try {
// paths that ends with . are disallowed as they are used to get around
// extension mappings and server source as static file
if ( StringUtil . StringEndsWith ( virtualPath . VirtualPathString , '.' ) )
throw new HttpException ( 404 , String . Empty ) ;
bool useAppConfig = ! filePath . IsWithinAppRoot ;
using ( new DisposableHttpContextWrapper ( _context ) ) {
try {
// We need to increase the depth when calling MapHttpHandler,
// since PageHandlerFactory relies on it
_context . ServerExecuteDepth + + ;
if ( _context . WorkerRequest is IIS7WorkerRequest ) {
handler = _context . ApplicationInstance . MapIntegratedHttpHandler (
_context ,
request . RequestType ,
filePath ,
physPath ,
useAppConfig ,
true /*convertNativeStaticFileModule*/ ) ;
}
else {
handler = _context . ApplicationInstance . MapHttpHandler (
_context ,
request . RequestType ,
filePath ,
physPath ,
useAppConfig ) ;
}
}
finally {
_context . ServerExecuteDepth - - ;
}
}
}
catch ( Exception e ) {
// 500 errors (compilation errors) get preserved
if ( e is HttpException ) {
int code = ( ( HttpException ) e ) . GetHttpCode ( ) ;
if ( code ! = 500 & & code ! = 404 ) {
e = null ;
}
}
throw new HttpException ( SR . GetString ( SR . Error_executing_child_request_for_path , path ) , e ) ;
}
ExecuteInternal ( handler , writer , preserveForm , true /*setPreviousPage*/ ,
virtualPath , filePath , physPath , null , queryStringOverride ) ;
}
public void Execute ( IHttpHandler handler , TextWriter writer , bool preserveForm ) {
if ( _context = = null )
throw new HttpException ( SR . GetString ( SR . Server_not_available ) ) ;
Execute ( handler , writer , preserveForm , true /*setPreviousPage*/ ) ;
}
internal void Execute ( IHttpHandler handler , TextWriter writer , bool preserveForm , bool setPreviousPage ) {
HttpRequest request = _context . Request ;
VirtualPath filePath = request . CurrentExecutionFilePathObject ;
string physicalPath = request . MapPath ( filePath ) ;
ExecuteInternal ( handler , writer , preserveForm , setPreviousPage ,
null , filePath , physicalPath , null , null ) ;
}
private void ExecuteInternal ( IHttpHandler handler , TextWriter writer , bool preserveForm , bool setPreviousPage ,
VirtualPath path , VirtualPath filePath , string physPath , Exception error , string queryStringOverride ) {
EnsureHasNotTransitionedToWebSocket ( ) ;
if ( handler = = null )
throw new ArgumentNullException ( "handler" ) ;
HttpRequest request = _context . Request ;
HttpResponse response = _context . Response ;
HttpApplication app = _context . ApplicationInstance ;
HttpValueCollection savedForm = null ;
VirtualPath savedCurrentExecutionFilePath = null ;
string savedQueryString = null ;
TextWriter savedOutputWriter = null ;
AspNetSynchronizationContextBase savedSyncContext = null ;
// Transaction wouldn't flow into ASPCOMPAT mode -- need to report an error
VerifyTransactionFlow ( handler ) ;
// create new trace context
_context . PushTraceContext ( ) ;
// set the new handler as the current handler
_context . SetCurrentHandler ( handler ) ;
// because we call this synchrnously async operations must be disabled
bool originalSyncContextWasEnabled = _context . SyncContext . Enabled ;
_context . SyncContext . Disable ( ) ;
// Execute the handler
try {
try {
_context . ServerExecuteDepth + + ;
savedCurrentExecutionFilePath = request . SwitchCurrentExecutionFilePath ( filePath ) ;
if ( ! preserveForm ) {
savedForm = request . SwitchForm ( new HttpValueCollection ( ) ) ;
// Clear out the query string, but honor overrides
if ( queryStringOverride = = null )
queryStringOverride = String . Empty ;
}
// override query string if requested
if ( queryStringOverride ! = null ) {
savedQueryString = request . QueryStringText ;
request . QueryStringText = queryStringOverride ;
}
// capture output if requested
if ( writer ! = null )
savedOutputWriter = response . SwitchWriter ( writer ) ;
Page targetPage = handler as Page ;
if ( targetPage ! = null ) {
if ( setPreviousPage ) {
// Set the previousPage of the new Page as the previous Page
targetPage . SetPreviousPage ( _context . PreviousHandler as Page ) ;
}
Page sourcePage = _context . Handler as Page ;
#pragma warning disable 0618 // To avoid deprecation warning
// If the source page of the transfer has smart nav on,
// always do as if the destination has it too (ASURT 97732)
if ( sourcePage ! = null & & sourcePage . SmartNavigation )
targetPage . SmartNavigation = true ;
#pragma warning restore 0618
2017-08-21 15:34:15 +00:00
// If the target page is async need to save/restore sync context
2016-08-03 10:59:49 +00:00
if ( targetPage is IHttpAsyncHandler ) {
savedSyncContext = _context . InstallNewAspNetSynchronizationContext ( ) ;
}
}
if ( ( handler is StaticFileHandler | | handler is DefaultHttpHandler ) & &
! DefaultHttpHandler . IsClassicAspRequest ( filePath . VirtualPathString ) ) {
// cannot apply static files handler directly
// -- it would dump the source of the current page
// instead just dump the file content into response
try {
response . WriteFile ( physPath ) ;
}
catch {
// hide the real error as it could be misleading
// in case of mismapped requests like /foo.asmx/bar
error = new HttpException ( 404 , String . Empty ) ;
}
}
else if ( ! ( handler is Page ) ) {
// disallow anything but pages
error = new HttpException ( 404 , String . Empty ) ;
}
else if ( handler is IHttpAsyncHandler ) {
// Asynchronous handler
// suspend cancellable period (don't abort this thread while
// we wait for another to finish)
bool isCancellable = _context . IsInCancellablePeriod ;
if ( isCancellable )
_context . EndCancellablePeriod ( ) ;
try {
IHttpAsyncHandler asyncHandler = ( IHttpAsyncHandler ) handler ;
if ( ! AppSettings . UseTaskFriendlySynchronizationContext ) {
// Legacy code path: behavior ASP.NET <= 4.0
IAsyncResult ar = asyncHandler . BeginProcessRequest ( _context , null , null ) ;
// wait for completion
if ( ! ar . IsCompleted ) {
// suspend app lock while waiting
bool needToRelock = false ;
try {
try { }
finally {
_context . SyncContext . DisassociateFromCurrentThread ( ) ;
needToRelock = true ;
}
WaitHandle h = ar . AsyncWaitHandle ;
if ( h ! = null ) {
h . WaitOne ( ) ;
}
else {
while ( ! ar . IsCompleted )
Thread . Sleep ( 1 ) ;
}
}
finally {
if ( needToRelock ) {
_context . SyncContext . AssociateWithCurrentThread ( ) ;
}
}
}
// end the async operation (get error if any)
try {
asyncHandler . EndProcessRequest ( ar ) ;
}
catch ( Exception e ) {
error = e ;
}
}
else {
// New code path: behavior ASP.NET >= 4.5
IAsyncResult ar ;
bool blockedThread ;
using ( CountdownEvent countdownEvent = new CountdownEvent ( 1 ) ) {
using ( _context . SyncContext . AcquireThreadLock ( ) ) {
// Kick off the asynchronous operation
ar = asyncHandler . BeginProcessRequest ( _context ,
cb : _ = > { countdownEvent . Signal ( ) ; } ,
extraData : null ) ;
}
// The callback passed to BeginProcessRequest will signal the CountdownEvent.
// The Wait() method blocks until the callback executes; no-ops if the operation completed synchronously.
blockedThread = ! countdownEvent . IsSet ;
countdownEvent . Wait ( ) ;
}
// end the async operation (get error if any)
try {
using ( _context . SyncContext . AcquireThreadLock ( ) ) {
asyncHandler . EndProcessRequest ( ar ) ;
}
// If we blocked the thread, YSOD the request to display a diagnostic message.
if ( blockedThread & & ! _context . SyncContext . AllowAsyncDuringSyncStages ) {
throw new InvalidOperationException ( SR . GetString ( SR . Server_execute_blocked_on_async_handler ) ) ;
}
}
catch ( Exception e ) {
error = e ;
}
}
}
finally {
// resume cancelleable period
if ( isCancellable )
_context . BeginCancellablePeriod ( ) ;
}
}
else {
// Synchronous handler
using ( new DisposableHttpContextWrapper ( _context ) ) {
try {
handler . ProcessRequest ( _context ) ;
}
catch ( Exception e ) {
error = e ;
}
}
}
}
finally {
_context . ServerExecuteDepth - - ;
// Restore the handlers;
_context . RestoreCurrentHandler ( ) ;
// restore output writer
if ( savedOutputWriter ! = null )
response . SwitchWriter ( savedOutputWriter ) ;
// restore overriden query string
if ( queryStringOverride ! = null & & savedQueryString ! = null )
request . QueryStringText = savedQueryString ;
if ( savedForm ! = null )
request . SwitchForm ( savedForm ) ;
request . SwitchCurrentExecutionFilePath ( savedCurrentExecutionFilePath ) ;
if ( savedSyncContext ! = null ) {
_context . RestoreSavedAspNetSynchronizationContext ( savedSyncContext ) ;
}
if ( originalSyncContextWasEnabled ) {
_context . SyncContext . Enable ( ) ;
}
// restore trace context
_context . PopTraceContext ( ) ;
}
}
catch { // Protect against exception filters
throw ;
}
// Report any error
if ( error ! = null ) {
// suppress errors with HTTP codes (for child requests they mislead more than help)
if ( error is HttpException & & ( ( HttpException ) error ) . GetHttpCode ( ) ! = 500 )
error = null ;
if ( path ! = null )
throw new HttpException ( SR . GetString ( SR . Error_executing_child_request_for_path , path ) , error ) ;
throw new HttpException ( SR . GetString ( SR . Error_executing_child_request_for_handler , handler . GetType ( ) . ToString ( ) ) , error ) ;
}
}
/// <devdoc>
/// <para>
/// Terminates execution of the current page and begins execution of a new
/// request using the supplied URL path.
/// If preserveForm is false, the QueryString and Form collections are cleared.
/// </para>
/// </devdoc>
public void Transfer ( string path , bool preserveForm ) {
Page page = _context . Handler as Page ;
if ( ( page ! = null ) & & page . IsCallback ) {
throw new ApplicationException ( SR . GetString ( SR . Transfer_not_allowed_in_callback ) ) ;
}
// execute child request
Execute ( path , null , preserveForm ) ;
// suppress the remainder of the current one
_context . Response . End ( ) ;
}
/// <devdoc>
/// <para>
/// Terminates execution of the current page and begins execution of a new
/// request using the supplied URL path.
/// </para>
/// </devdoc>
public void Transfer ( string path ) {
// Make sure the transfer is not treated as a postback, which could cause a stack
// overflow if the user doesn't expect it (VSWhidbey 181013).
// If the use *does* want it treated as a postback, they can call Transfer(path, true).
bool savedPreventPostback = _context . PreventPostback ;
_context . PreventPostback = true ;
Transfer ( path , true /*preserveForm*/ ) ;
_context . PreventPostback = savedPreventPostback ;
}
public void Transfer ( IHttpHandler handler , bool preserveForm ) {
Page page = handler as Page ;
if ( ( page ! = null ) & & page . IsCallback ) {
throw new ApplicationException ( SR . GetString ( SR . Transfer_not_allowed_in_callback ) ) ;
}
Execute ( handler , null , preserveForm ) ;
// suppress the remainder of the current one
_context . Response . End ( ) ;
}
public void TransferRequest ( string path )
{
TransferRequest ( path , false , null , null , preserveUser : true ) ;
}
public void TransferRequest ( string path , bool preserveForm )
{
TransferRequest ( path , preserveForm , null , null , preserveUser : true ) ;
}
public void TransferRequest ( string path , bool preserveForm , string method , NameValueCollection headers ) {
TransferRequest ( path , preserveForm , method , headers , preserveUser : true ) ;
}
public void TransferRequest ( string path , bool preserveForm , string method , NameValueCollection headers , bool preserveUser ) {
EnsureHasNotTransitionedToWebSocket ( ) ;
if ( ! HttpRuntime . UseIntegratedPipeline ) {
throw new PlatformNotSupportedException ( SR . GetString ( SR . Requires_Iis_Integrated_Mode ) ) ;
}
if ( _context = = null ) {
throw new HttpException ( SR . GetString ( SR . Server_not_available ) ) ;
}
if ( path = = null ) {
throw new ArgumentNullException ( "path" ) ;
}
IIS7WorkerRequest wr = _context . WorkerRequest as IIS7WorkerRequest ;
HttpRequest request = _context . Request ;
HttpResponse response = _context . Response ;
if ( wr = = null ) {
throw new HttpException ( SR . GetString ( SR . Server_not_available ) ) ;
}
// Remove potential cookie-less session id (ASURT 100558)
path = response . RemoveAppPathModifier ( path ) ;
// Extract query string if specified
String qs = null ;
int iqs = path . IndexOf ( '?' ) ;
if ( iqs > = 0 ) {
qs = ( iqs < path . Length - 1 ) ? path . Substring ( iqs + 1 ) : String . Empty ;
path = path . Substring ( 0 , iqs ) ;
}
if ( ! UrlPath . IsValidVirtualPathWithoutProtocol ( path ) ) {
throw new ArgumentException ( SR . GetString ( SR . Invalid_path_for_child_request , path ) ) ;
}
VirtualPath virtualPath = request . FilePathObject . Combine ( VirtualPath . Create ( path ) ) ;
// Schedule the child execution
wr . ScheduleExecuteUrl ( virtualPath . VirtualPathString ,
qs ,
method ,
preserveForm ,
preserveForm ? request . EntityBody : null ,
headers ,
preserveUser ) ;
// force the completion of the current request so that the
// child execution can be performed immediately after unwind
_context . ApplicationInstance . EnsureReleaseState ( ) ;
// DevDiv Bugs 162750: IIS7 Integrated Mode: TransferRequest performance issue
// Instead of calling Response.End we call HttpApplication.CompleteRequest()
_context . ApplicationInstance . CompleteRequest ( ) ;
}
private void VerifyTransactionFlow ( IHttpHandler handler ) {
Page topPage = _context . Handler as Page ;
Page childPage = handler as Page ;
if ( childPage ! = null & & childPage . IsInAspCompatMode & & // child page aspcompat
topPage ! = null & & ! topPage . IsInAspCompatMode & & // top page is not aspcompat
Transactions . Utils . IsInTransaction ) { // we are in transaction
throw new HttpException ( SR . GetString ( SR . Transacted_page_calls_aspcompat ) ) ;
}
}
//
// Static method to execute a request outside of HttpContext and capture the response
//
internal static void ExecuteLocalRequestAndCaptureResponse ( String path , TextWriter writer ,
ErrorFormatterGenerator errorFormatterGenerator ) {
HttpRequest request = new HttpRequest (
VirtualPath . CreateAbsolute ( path ) ,
String . Empty ) ;
HttpResponse response = new HttpResponse ( writer ) ;
HttpContext context = new HttpContext ( request , response ) ;
HttpApplication app = HttpApplicationFactory . GetApplicationInstance ( context ) as HttpApplication ;
context . ApplicationInstance = app ;
try {
context . Server . Execute ( path ) ;
}
catch ( HttpException e ) {
if ( errorFormatterGenerator ! = null ) {
context . Response . SetOverrideErrorFormatter ( errorFormatterGenerator . GetErrorFormatter ( e ) ) ;
}
context . Response . ReportRuntimeError ( e , false , true ) ;
}
finally {
if ( app ! = null ) {
context . ApplicationInstance = null ;
HttpApplicationFactory . RecycleApplicationInstance ( app ) ;
}
}
}
//
// Computer name
//
private static object _machineNameLock = new object ( ) ;
private static string _machineName ;
private const int _maxMachineNameLength = 256 ;
/// <devdoc>
/// <para>
/// Gets
/// the server machine name.
/// </para>
/// </devdoc>
public string MachineName {
[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)]
get {
return GetMachineNameInternal ( ) ;
}
}
internal static string GetMachineNameInternal ( )
{
if ( _machineName ! = null )
return _machineName ;
lock ( _machineNameLock )
{
if ( _machineName ! = null )
return _machineName ;
StringBuilder buf = new StringBuilder ( _maxMachineNameLength ) ;
int len = _maxMachineNameLength ;
if ( UnsafeNativeMethods . GetComputerName ( buf , ref len ) = = 0 )
throw new HttpException ( SR . GetString ( SR . Get_computer_name_failed ) ) ;
_machineName = buf . ToString ( ) ;
}
return _machineName ;
}
//
// Request Timeout
//
/// <devdoc>
/// <para>
/// Request timeout in seconds
/// </para>
/// </devdoc>
public int ScriptTimeout {
get {
if ( _context ! = null ) {
return Convert . ToInt32 ( _context . Timeout . TotalSeconds ) ;
}
else {
return HttpRuntimeSection . DefaultExecutionTimeout ;
}
}
[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)]
set {
if ( _context = = null )
throw new HttpException ( SR . GetString ( SR . Server_not_available ) ) ;
if ( value < = 0 )
throw new ArgumentOutOfRangeException ( "value" ) ;
_context . Timeout = new TimeSpan ( 0 , 0 , value ) ;
}
}
//
// Encoding / Decoding -- wrappers for HttpUtility
//
/// <devdoc>
/// <para>
/// HTML
/// decodes a given string and
/// returns the decoded string.
/// </para>
/// </devdoc>
public string HtmlDecode ( string s ) {
return HttpUtility . HtmlDecode ( s ) ;
}
/// <devdoc>
/// <para>
/// HTML
/// decode a string and send the result to a TextWriter output
/// stream.
/// </para>
/// </devdoc>
public void HtmlDecode ( string s , TextWriter output ) {
HttpUtility . HtmlDecode ( s , output ) ;
}
/// <devdoc>
/// <para>
/// HTML
/// encodes a given string and
/// returns the encoded string.
/// </para>
/// </devdoc>
public string HtmlEncode ( string s ) {
return HttpUtility . HtmlEncode ( s ) ;
}
/// <devdoc>
/// <para>
/// HTML
/// encodes
/// a string and returns the output to a TextWriter stream of output.
/// </para>
/// </devdoc>
public void HtmlEncode ( string s , TextWriter output ) {
HttpUtility . HtmlEncode ( s , output ) ;
}
/// <devdoc>
/// <para>
/// URL
/// encodes a given
/// string and returns the encoded string.
/// </para>
/// </devdoc>
public string UrlEncode ( string s ) {
Encoding e = ( _context ! = null ) ? _context . Response . ContentEncoding : Encoding . UTF8 ;
return HttpUtility . UrlEncode ( s , e ) ;
}
/// <devdoc>
/// <para>
/// URL encodes a path portion of a URL string and returns the encoded string.
/// </para>
/// </devdoc>
public string UrlPathEncode ( string s ) {
return HttpUtility . UrlPathEncode ( s ) ;
}
/// <devdoc>
/// <para>
/// URL
/// encodes
/// a string and returns the output to a TextWriter output stream.
/// </para>
/// </devdoc>
public void UrlEncode ( string s , TextWriter output ) {
if ( s ! = null )
output . Write ( UrlEncode ( s ) ) ;
}
/// <devdoc>
/// <para>
/// URL decodes a string and returns the output in a string.
/// </para>
/// </devdoc>
public string UrlDecode ( string s ) {
Encoding e = ( _context ! = null ) ? _context . Request . ContentEncoding : Encoding . UTF8 ;
return HttpUtility . UrlDecode ( s , e ) ;
}
/// <devdoc>
/// <para>
/// URL decodes a string and returns the output as a TextWriter output
/// stream.
/// </para>
/// </devdoc>
public void UrlDecode ( string s , TextWriter output ) {
if ( s ! = null )
output . Write ( UrlDecode ( s ) ) ;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
static public string UrlTokenEncode ( byte [ ] input )
{
return HttpEncoder . Current . UrlTokenEncode ( input ) ;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
static public byte [ ] UrlTokenDecode ( string input ) {
return HttpEncoder . Current . UrlTokenDecode ( input ) ;
}
// helper that throws an exception if we have transitioned the current request to a WebSocket request
internal void EnsureHasNotTransitionedToWebSocket ( ) {
if ( _context ! = null ) {
_context . EnsureHasNotTransitionedToWebSocket ( ) ;
}
}
}
/// <devdoc>
/// </devdoc>
// VSWhidbey 473228 - removed link demand from HttpUtility for ClickOnce scenario
public sealed class HttpUtility {
public HttpUtility ( ) { }
//////////////////////////////////////////////////////////////////////////
//
// HTML Encoding / Decoding
//
/// <devdoc>
/// <para>
/// HTML decodes a string and returns the decoded string.
/// </para>
/// </devdoc>
public static string HtmlDecode ( string s ) {
return HttpEncoder . Current . HtmlDecode ( s ) ;
}
/// <devdoc>
/// <para>
/// HTML decode a string and send the result to a TextWriter output stream.
/// </para>
/// </devdoc>
public static void HtmlDecode ( string s , TextWriter output ) {
HttpEncoder . Current . HtmlDecode ( s , output ) ;
}
/// <devdoc>
/// <para>
/// HTML encodes a string and returns the encoded string.
/// </para>
/// </devdoc>
public static String HtmlEncode ( String s ) {
return HttpEncoder . Current . HtmlEncode ( s ) ;
}
/// <devdoc>
/// <para>
/// HTML encodes an object's string representation and returns the encoded string.
/// If the object implements IHtmlString, don't encode it
/// </para>
/// </devdoc>
public static String HtmlEncode ( object value ) {
if ( value = = null ) {
// Return null to be consistent with HtmlEncode(string)
return null ;
}
var htmlString = value as IHtmlString ;
if ( htmlString ! = null ) {
return htmlString . ToHtmlString ( ) ;
}
return HtmlEncode ( Convert . ToString ( value , CultureInfo . CurrentCulture ) ) ;
}
/// <devdoc>
/// <para>
/// HTML encodes a string and returns the output to a TextWriter stream of
/// output.
/// </para>
/// </devdoc>
public static void HtmlEncode ( String s , TextWriter output ) {
HttpEncoder . Current . HtmlEncode ( s , output ) ;
}
/// <devdoc>
/// <para>
/// Encodes a string to make it a valid HTML attribute and returns the encoded string.
/// </para>
/// </devdoc>
public static String HtmlAttributeEncode ( String s ) {
return HttpEncoder . Current . HtmlAttributeEncode ( s ) ;
}
/// <devdoc>
/// <para>
/// Encodes a string to make it a valid HTML attribute and returns the output
/// to a TextWriter stream of
/// output.
/// </para>
/// </devdoc>
public static void HtmlAttributeEncode ( String s , TextWriter output ) {
HttpEncoder . Current . HtmlAttributeEncode ( s , output ) ;
}
internal static string FormatPlainTextSpacesAsHtml ( string s ) {
if ( s = = null ) {
return null ;
}
StringBuilder builder = new StringBuilder ( ) ;
StringWriter writer = new StringWriter ( builder ) ;
int cb = s . Length ;
for ( int i = 0 ; i < cb ; i + + ) {
char ch = s [ i ] ;
if ( ch = = ' ' ) {
writer . Write ( " " ) ;
}
else {
writer . Write ( ch ) ;
}
}
return builder . ToString ( ) ;
}
internal static String FormatPlainTextAsHtml ( String s ) {
if ( s = = null )
return null ;
StringBuilder builder = new StringBuilder ( ) ;
StringWriter writer = new StringWriter ( builder ) ;
FormatPlainTextAsHtml ( s , writer ) ;
return builder . ToString ( ) ;
}
internal static void FormatPlainTextAsHtml ( String s , TextWriter output ) {
if ( s = = null )
return ;
int cb = s . Length ;
char prevCh = '\0' ;
for ( int i = 0 ; i < cb ; i + + ) {
char ch = s [ i ] ;
switch ( ch ) {
case '<' :
output . Write ( "<" ) ;
break ;
case '>' :
output . Write ( ">" ) ;
break ;
case '"' :
output . Write ( """ ) ;
break ;
case '&' :
output . Write ( "&" ) ;
break ;
case ' ' :
if ( prevCh = = ' ' )
output . Write ( " " ) ;
else
output . Write ( ch ) ;
break ;
case '\r' :
// Ignore \r, only handle \n
break ;
case '\n' :
output . Write ( "<br>" ) ;
break ;
//
default :
#if ENTITY_ENCODE_HIGH_ASCII_CHARS
// The seemingly arbitrary 160 comes from RFC
if ( ch > = 160 & & ch < 256 ) {
output . Write ( "&#" ) ;
output . Write ( ( ( int ) ch ) . ToString ( NumberFormatInfo . InvariantInfo ) ) ;
output . Write ( ';' ) ;
break ;
}
#endif // ENTITY_ENCODE_HIGH_ASCII_CHARS
output . Write ( ch ) ;
break ;
}
prevCh = ch ;
}
}
//////////////////////////////////////////////////////////////////////////
//
// ASII encode - everything all non-7-bit to '?'
//
/ * internal static String AsciiEncode ( String s ) {
if ( s = = null )
return null ;
StringBuilder sb = new StringBuilder ( s . Length ) ;
for ( int i = 0 ; i < s . Length ; i + + ) {
char ch = s [ i ] ;
if ( ( ( ch & 0xff80 ) ! = 0 ) | | ( ch < ' ' & & ch ! = '\r' & & ch ! = '\n' & & ch ! = '\t' ) )
ch = '?' ;
sb . Append ( ch ) ;
}
return sb . ToString ( ) ;
} * /
//
// Query string parsing support
//
public static NameValueCollection ParseQueryString ( string query ) {
return ParseQueryString ( query , Encoding . UTF8 ) ;
}
public static NameValueCollection ParseQueryString ( string query , Encoding encoding ) {
if ( query = = null ) {
throw new ArgumentNullException ( "query" ) ;
}
if ( encoding = = null ) {
throw new ArgumentNullException ( "encoding" ) ;
}
if ( query . Length > 0 & & query [ 0 ] = = '?' ) {
query = query . Substring ( 1 ) ;
}
return new HttpValueCollection ( query , false , true , encoding ) ;
}
//////////////////////////////////////////////////////////////////////////
//
// URL decoding / encoding
//
//////////////////////////////////////////////////////////////////////////
//
// Public static methods
//
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static string UrlEncode ( string str ) {
if ( str = = null )
return null ;
return UrlEncode ( str , Encoding . UTF8 ) ;
}
/// <devdoc>
/// <para>
/// URL encodes a path portion of a URL string and returns the encoded string.
/// </para>
/// </devdoc>
public static string UrlPathEncode ( string str ) {
return HttpEncoder . Current . UrlPathEncode ( str ) ;
}
internal static string AspCompatUrlEncode ( string s ) {
s = UrlEncode ( s ) ;
s = s . Replace ( "!" , "%21" ) ;
s = s . Replace ( "*" , "%2A" ) ;
s = s . Replace ( "(" , "%28" ) ;
s = s . Replace ( ")" , "%29" ) ;
s = s . Replace ( "-" , "%2D" ) ;
s = s . Replace ( "." , "%2E" ) ;
s = s . Replace ( "_" , "%5F" ) ;
s = s . Replace ( "\\" , "%5C" ) ;
return s ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static string UrlEncode ( string str , Encoding e ) {
if ( str = = null )
return null ;
return Encoding . ASCII . GetString ( UrlEncodeToBytes ( str , e ) ) ;
}
// Helper to encode the non-ASCII url characters only
internal static String UrlEncodeNonAscii ( string str , Encoding e ) {
return HttpEncoder . Current . UrlEncodeNonAscii ( str , e ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static string UrlEncode ( byte [ ] bytes ) {
if ( bytes = = null )
return null ;
return Encoding . ASCII . GetString ( UrlEncodeToBytes ( bytes ) ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static string UrlEncode ( byte [ ] bytes , int offset , int count ) {
if ( bytes = = null )
return null ;
return Encoding . ASCII . GetString ( UrlEncodeToBytes ( bytes , offset , count ) ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static byte [ ] UrlEncodeToBytes ( string str ) {
if ( str = = null )
return null ;
return UrlEncodeToBytes ( str , Encoding . UTF8 ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static byte [ ] UrlEncodeToBytes ( string str , Encoding e ) {
if ( str = = null )
return null ;
byte [ ] bytes = e . GetBytes ( str ) ;
return HttpEncoder . Current . UrlEncode ( bytes , 0 , bytes . Length , false /* alwaysCreateNewReturnValue */ ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static byte [ ] UrlEncodeToBytes ( byte [ ] bytes ) {
if ( bytes = = null )
return null ;
return UrlEncodeToBytes ( bytes , 0 , bytes . Length ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static byte [ ] UrlEncodeToBytes ( byte [ ] bytes , int offset , int count ) {
return HttpEncoder . Current . UrlEncode ( bytes , offset , count , true /* alwaysCreateNewReturnValue */ ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Obsolete("This method produces non-standards-compliant output and has interoperability issues. The preferred alternative is UrlEncode(String).")]
public static string UrlEncodeUnicode ( string str ) {
return HttpEncoder . Current . UrlEncodeUnicode ( str , false /* ignoreAscii */ ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[Obsolete("This method produces non-standards-compliant output and has interoperability issues. The preferred alternative is UrlEncodeToBytes(String).")]
public static byte [ ] UrlEncodeUnicodeToBytes ( string str ) {
if ( str = = null )
return null ;
return Encoding . ASCII . GetBytes ( UrlEncodeUnicode ( str ) ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static string UrlDecode ( string str ) {
if ( str = = null )
return null ;
return UrlDecode ( str , Encoding . UTF8 ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static string UrlDecode ( string str , Encoding e ) {
return HttpEncoder . Current . UrlDecode ( str , e ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static string UrlDecode ( byte [ ] bytes , Encoding e ) {
if ( bytes = = null )
return null ;
return UrlDecode ( bytes , 0 , bytes . Length , e ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static string UrlDecode ( byte [ ] bytes , int offset , int count , Encoding e ) {
return HttpEncoder . Current . UrlDecode ( bytes , offset , count , e ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static byte [ ] UrlDecodeToBytes ( string str ) {
if ( str = = null )
return null ;
return UrlDecodeToBytes ( str , Encoding . UTF8 ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static byte [ ] UrlDecodeToBytes ( string str , Encoding e ) {
if ( str = = null )
return null ;
return UrlDecodeToBytes ( e . GetBytes ( str ) ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static byte [ ] UrlDecodeToBytes ( byte [ ] bytes ) {
if ( bytes = = null )
return null ;
return UrlDecodeToBytes ( bytes , 0 , ( bytes ! = null ) ? bytes . Length : 0 ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static byte [ ] UrlDecodeToBytes ( byte [ ] bytes , int offset , int count ) {
return HttpEncoder . Current . UrlDecode ( bytes , offset , count ) ;
}
//////////////////////////////////////////////////////////////////////////
//
// Misc helpers
//
//////////////////////////////////////////////////////////////////////////
internal static String FormatHttpDateTime ( DateTime dt ) {
if ( dt < DateTime . MaxValue . AddDays ( - 1 ) & & dt > DateTime . MinValue . AddDays ( 1 ) )
dt = dt . ToUniversalTime ( ) ;
return dt . ToString ( "R" , DateTimeFormatInfo . InvariantInfo ) ;
}
internal static String FormatHttpDateTimeUtc ( DateTime dt ) {
return dt . ToString ( "R" , DateTimeFormatInfo . InvariantInfo ) ;
}
internal static String FormatHttpCookieDateTime ( DateTime dt ) {
if ( dt < DateTime . MaxValue . AddDays ( - 1 ) & & dt > DateTime . MinValue . AddDays ( 1 ) )
dt = dt . ToUniversalTime ( ) ;
return dt . ToString ( "ddd, dd-MMM-yyyy HH':'mm':'ss 'GMT'" , DateTimeFormatInfo . InvariantInfo ) ;
}
//
// JavaScriptStringEncode
//
public static String JavaScriptStringEncode ( string value ) {
return JavaScriptStringEncode ( value , false ) ;
}
public static String JavaScriptStringEncode ( string value , bool addDoubleQuotes ) {
string encoded = HttpEncoder . Current . JavaScriptStringEncode ( value ) ;
return ( addDoubleQuotes ) ? "\"" + encoded + "\"" : encoded ;
}
/// <summary>
/// Attempts to parse a co-ordinate as a double precision floating point value.
/// This essentially does a Double.TryParse while disallowing specific floating point constructs such as the exponent.
/// </summary>
internal static bool TryParseCoordinates ( string value , out double doubleValue ) {
var flags = NumberStyles . AllowLeadingWhite | NumberStyles . AllowTrailingWhite | NumberStyles . AllowDecimalPoint | NumberStyles . AllowLeadingSign ;
return Double . TryParse ( value , flags , CultureInfo . InvariantCulture , out doubleValue ) ;
}
}
}