//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ /* * 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); } /// /// /// Provides several /// helper methods that can be used in the processing of Web requests. /// /// 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 // /// /// /// Instantiates a COM object identified via a progid. /// /// [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; } /// /// /// Instantiates a COM object identified via a Type. /// /// [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; } /// /// /// Instantiates a COM object identified via a clsid. /// /// [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]; } /// /// /// Maps a virtual path to a physical path. /// /// 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; } /// /// Returns the last recorded exception. /// public Exception GetLastError() { if (_context != null) return _context.Error; else if (_application != null) return _application.LastError; else return null; } /// /// Clears the last error. /// public void ClearError() { if (_context != null) _context.ClearError(); else if (_application != null) _application.ClearError(); } // // Server.Transfer/Server.Execute -- child requests // /// /// /// 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. /// /// public void Execute(string path) { Execute(path, null, true /*preserveForm*/); } /// /// /// 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. /// /// public void Execute(string path, TextWriter writer) { Execute(path, writer, true /*preserveForm*/); } /// /// /// 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. /// /// public void Execute(string path, bool preserveForm) { Execute(path, null, preserveForm); } /// /// /// 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. /// /// 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 // If the target page is async need to save/restore sync context 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); } } /// /// /// 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. /// /// 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(); } /// /// /// Terminates execution of the current page and begins execution of a new /// request using the supplied URL path. /// /// 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; /// /// /// Gets /// the server machine name. /// /// 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 // /// /// /// Request timeout in seconds /// /// 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 // /// /// /// HTML /// decodes a given string and /// returns the decoded string. /// /// public string HtmlDecode(string s) { return HttpUtility.HtmlDecode(s); } /// /// /// HTML /// decode a string and send the result to a TextWriter output /// stream. /// /// public void HtmlDecode(string s, TextWriter output) { HttpUtility.HtmlDecode(s, output); } /// /// /// HTML /// encodes a given string and /// returns the encoded string. /// /// public string HtmlEncode(string s) { return HttpUtility.HtmlEncode(s); } /// /// /// HTML /// encodes /// a string and returns the output to a TextWriter stream of output. /// /// public void HtmlEncode(string s, TextWriter output) { HttpUtility.HtmlEncode(s, output); } /// /// /// URL /// encodes a given /// string and returns the encoded string. /// /// public string UrlEncode(string s) { Encoding e = (_context != null) ? _context.Response.ContentEncoding : Encoding.UTF8; return HttpUtility.UrlEncode(s, e); } /// /// /// URL encodes a path portion of a URL string and returns the encoded string. /// /// public string UrlPathEncode(string s) { return HttpUtility.UrlPathEncode(s); } /// /// /// URL /// encodes /// a string and returns the output to a TextWriter output stream. /// /// public void UrlEncode(string s, TextWriter output) { if (s != null) output.Write(UrlEncode(s)); } /// /// /// URL decodes a string and returns the output in a string. /// /// public string UrlDecode(string s) { Encoding e = (_context != null) ? _context.Request.ContentEncoding : Encoding.UTF8; return HttpUtility.UrlDecode(s, e); } /// /// /// URL decodes a string and returns the output as a TextWriter output /// stream. /// /// 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(); } } } /// /// // VSWhidbey 473228 - removed link demand from HttpUtility for ClickOnce scenario public sealed class HttpUtility { public HttpUtility () {} ////////////////////////////////////////////////////////////////////////// // // HTML Encoding / Decoding // /// /// /// HTML decodes a string and returns the decoded string. /// /// public static string HtmlDecode(string s) { return HttpEncoder.Current.HtmlDecode(s); } /// /// /// HTML decode a string and send the result to a TextWriter output stream. /// /// public static void HtmlDecode(string s, TextWriter output) { HttpEncoder.Current.HtmlDecode(s, output); } /// /// /// HTML encodes a string and returns the encoded string. /// /// public static String HtmlEncode(String s) { return HttpEncoder.Current.HtmlEncode(s); } /// /// /// HTML encodes an object's string representation and returns the encoded string. /// If the object implements IHtmlString, don't encode it /// /// 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)); } /// /// /// HTML encodes a string and returns the output to a TextWriter stream of /// output. /// /// public static void HtmlEncode(String s, TextWriter output) { HttpEncoder.Current.HtmlEncode(s, output); } /// /// /// Encodes a string to make it a valid HTML attribute and returns the encoded string. /// /// public static String HtmlAttributeEncode(String s) { return HttpEncoder.Current.HtmlAttributeEncode(s); } /// /// /// Encodes a string to make it a valid HTML attribute and returns the output /// to a TextWriter stream of /// output. /// /// 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': 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("
"); 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 // /// /// [To be supplied.] /// public static string UrlEncode(string str) { if (str == null) return null; return UrlEncode(str, Encoding.UTF8); } /// /// /// URL encodes a path portion of a URL string and returns the encoded string. /// /// 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; } /// /// [To be supplied.] /// 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); } /// /// [To be supplied.] /// public static string UrlEncode(byte[] bytes) { if (bytes == null) return null; return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes)); } /// /// [To be supplied.] /// public static string UrlEncode(byte[] bytes, int offset, int count) { if (bytes == null) return null; return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes, offset, count)); } /// /// [To be supplied.] /// public static byte[] UrlEncodeToBytes(string str) { if (str == null) return null; return UrlEncodeToBytes(str, Encoding.UTF8); } /// /// [To be supplied.] /// 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 */); } /// /// [To be supplied.] /// public static byte[] UrlEncodeToBytes(byte[] bytes) { if (bytes == null) return null; return UrlEncodeToBytes(bytes, 0, bytes.Length); } /// /// [To be supplied.] /// public static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count) { return HttpEncoder.Current.UrlEncode(bytes, offset, count, true /* alwaysCreateNewReturnValue */); } /// /// [To be supplied.] /// [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 */); } /// /// [To be supplied.] /// [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)); } /// /// [To be supplied.] /// public static string UrlDecode(string str) { if (str == null) return null; return UrlDecode(str, Encoding.UTF8); } /// /// [To be supplied.] /// public static string UrlDecode(string str, Encoding e) { return HttpEncoder.Current.UrlDecode(str, e); } /// /// [To be supplied.] /// public static string UrlDecode(byte[] bytes, Encoding e) { if (bytes == null) return null; return UrlDecode(bytes, 0, bytes.Length, e); } /// /// [To be supplied.] /// public static string UrlDecode(byte[] bytes, int offset, int count, Encoding e) { return HttpEncoder.Current.UrlDecode(bytes, offset, count, e); } /// /// [To be supplied.] /// public static byte[] UrlDecodeToBytes(string str) { if (str == null) return null; return UrlDecodeToBytes(str, Encoding.UTF8); } /// /// [To be supplied.] /// public static byte[] UrlDecodeToBytes(string str, Encoding e) { if (str == null) return null; return UrlDecodeToBytes(e.GetBytes(str)); } /// /// [To be supplied.] /// public static byte[] UrlDecodeToBytes(byte[] bytes) { if (bytes == null) return null; return UrlDecodeToBytes(bytes, 0, (bytes != null) ? bytes.Length : 0); } /// /// [To be supplied.] /// 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; } /// /// 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. /// 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); } } }