httpserverutility.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / xsp / System / Web / httpserverutility.cs / 9 / httpserverutility.cs

                            //------------------------------------------------------------------------------ 
// 
//     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.Text;
    using System.Runtime.Serialization.Formatters; 
    using System.Threading;
    using System.Runtime.InteropServices;
    using System.IO;
    using System.Collections; 
    using System.Collections.Specialized;
    using System.Globalization; 
    using System.Web.Hosting; 
    using System.Web.Util;
    using System.Web.UI; 
    using System.Web.Configuration;
    using System.Security;
    using System.Security.Permissions;
    using System.Web.Management; 

    internal abstract class ErrorFormatterGenerator { 
        internal abstract ErrorFormatter GetErrorFormatter(Exception e); 
    }
 

    /// 
    ///    
    ///       Provides several 
    ///       helper methods that can be used in the processing of Web requests.
    ///     
    ///  
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    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) { 
            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) {
            // 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) {
            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) {
            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)
            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 HttpContextWrapper(_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) {
 
            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; 
            AspNetSynchronizationContext 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; 

                            IAsyncResult ar = asyncHandler.BeginProcessRequest(_context, null, null); 

                            // wait for completion
                            if (!ar.IsCompleted) {
                                // suspend app lock while waiting 
                                bool needToRelock = false;
 
                                try { 
                                    try {} finally {
                                        Monitor.Exit(app); 
                                        needToRelock = true;
                                    }

                                    WaitHandle h = ar.AsyncWaitHandle; 

                                    if (h != null) { 
                                        h.WaitOne(); 
                                    }
                                    else { 
                                        while (!ar.IsCompleted)
                                            Thread.Sleep(1);
                                    }
                                } 
                                finally {
                                    if (needToRelock) { 
                                        Monitor.Enter(app); 
                                    }
                                } 
                            }

                            // end the async operation (get error if any)
 
                            try {
                                asyncHandler.EndProcessRequest(ar); 
                            } 
                            catch (Exception e) {
                                error = e; 
                            }
                        }
                        finally {
                            // resume cancelleable period 
                            if (isCancellable)
                                _context.BeginCancellablePeriod(); 
                        } 
                    }
                    else { 
                        // Synchronous handler

                        using (new HttpContextWrapper(_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);
        }
 
        public void TransferRequest(string path, bool preserveForm)
        { 
            TransferRequest(path, preserveForm, null, null); 
        }
 
        public void TransferRequest(string path, bool preserveForm, string method, NameValueCollection headers) {
            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));
            string physPath = request.MapPath(path);

            // Demand read access to the physical path of the target handler 
            InternalSecurityPermissions.FileReadAccess(physPath).Demand();
 
            //  Schedule the child execution 
            wr.ScheduleExecuteUrl( virtualPath.VirtualPathString,
                                   qs, 
                                   method,
                                   preserveForm,
                                   preserveForm ? request.EntityBody : null,
                                   headers); 

            // force the completion of the current request so that the 
            // child execution can be performed immediately after unwind 
            _context.Response.End();
        } 

        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, CultureInfo.InvariantCulture);
                } 
                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)
        {
            if (input == null) 
                throw new ArgumentNullException("input");
            if (input.Length < 1) 
                return String.Empty; 

            string  base64Str   = null; 
            int     endPos      = 0;
            char[]  base64Chars = null;

            //////////////////////////////////////////////////////// 
            // Step 1: Do a Base64 encoding
            base64Str = Convert.ToBase64String(input); 
            if (base64Str == null) 
                return null;
 
            ////////////////////////////////////////////////////////
            // Step 2: Find how many padding chars are present in the end
            for (endPos = base64Str.Length; endPos > 0; endPos--)
            { 
                if (base64Str[endPos - 1] != '=') // Found a non-padding char!
                { 
                    break; // Stop here 
                }
            } 

            ////////////////////////////////////////////////////////
            // Step 3: Create char array to store all non-padding chars,
            //      plus a char to indicate how many padding chars are needed 
            base64Chars = new char[endPos + 1];
            base64Chars[endPos] = (char)((int)'0' + base64Str.Length - endPos); // Store a char at the end, to indicate how many padding chars are needed 
 
            ////////////////////////////////////////////////////////
            // Step 3: Copy in the other chars. Transform the "+" to "-", and "/" to "_" 
            for (int iter = 0; iter < endPos; iter++)
            {
                char c = base64Str[iter];
 
                switch (c)
                { 
                    case '+': 
                        base64Chars[iter] = '-';
                        break; 

                    case '/':
                        base64Chars[iter] = '_';
                        break; 

                    case '=': 
                        Debug.Assert (false); 
                        base64Chars[iter] = c;
                        break; 

                    default:
                        base64Chars[iter] = c;
                        break; 
                }
            } 
            return new string(base64Chars); 
        }
 
        /////////////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////////////
 
        static public byte [] UrlTokenDecode(string input) {
            if (input == null) 
                throw new ArgumentNullException("input"); 

            int len = input.Length; 
            if (len < 1)
                return new byte[0];

            /////////////////////////////////////////////////////////////////// 
            // Step 1: Calculate the number of padding chars to append to this string.
            //         The number of padding chars to append is stored in the last char of the string. 
            int numPadChars = (int)input[len - 1] - (int)'0'; 
            if (numPadChars < 0 || numPadChars > 10)
                return null; 


            ///////////////////////////////////////////////////////////////////
            // Step 2: Create array to store the chars (not including the last char) 
            //          and the padding chars
            char[] base64Chars = new char[len - 1 + numPadChars]; 
 

            //////////////////////////////////////////////////////// 
            // Step 3: Copy in the chars. Transform the "-" to "+", and "*" to "/"
            for (int iter = 0; iter < len - 1; iter++)
            {
                char c = input[iter]; 

                switch (c) 
                { 
                    case '-':
                        base64Chars[iter] = '+'; 
                        break;

                    case '_':
                        base64Chars[iter] = '/'; 
                        break;
 
                    default: 
                        base64Chars[iter] = c;
                        break; 
                }
            }

            //////////////////////////////////////////////////////// 
            // Step 4: Add padding chars
            for (int iter = len - 1; iter < base64Chars.Length; iter++) 
            { 
                base64Chars[iter] = '=';
            } 

            // Do the actual conversion
            return Convert.FromBase64CharArray (base64Chars, 0, base64Chars.Length);
        } 
    }
 
 
    /// 
    ///  

    // 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) { 
            if (s == null)
                return null;

            // See if this string needs to be decoded at all.  If no 
            // ampersands are found, then no special HTML-encoded chars
            // are in the string. 
            if (s.IndexOf('&') < 0) 
                return s;
 
            StringBuilder builder = new StringBuilder();
            StringWriter writer = new StringWriter(builder);

            HtmlDecode(s, writer); 

            return builder.ToString(); 
        } 

 
        /// 
        ///    
        ///       HTML decode a string and send the result to a TextWriter output stream.
        ///     
        /// 
        private static char[] s_entityEndingChars = new char[] {';', '&'}; 
        public static void HtmlDecode(string s, TextWriter output) { 
            if (s == null)
                return; 

            if (s.IndexOf('&') < 0) {
                output.Write(s);        // good as is
                return; 
            }
 
            int l = s.Length; 
            for (int i = 0; i < l; i++) {
                char ch = s[i]; 

                if (ch == '&') {
                    // We found a '&'. Now look for the next ';' or '&'. The idea is that
                    // if we find another '&' before finding a ';', then this is not an entity, 
                    // and the next '&' might start a real entity (VSWhidbey 275184)
                    int index = s.IndexOfAny(s_entityEndingChars, i + 1); 
                    if (index > 0 && s[index] == ';') { 
                        string entity = s.Substring(i + 1, index - i - 1);
 
                        if (entity.Length > 1 && entity[0] == '#') {
                            try {
                                // The # syntax can be in decimal or hex, e.g.
                                //      å  --> decimal 
                                //      å  --> same char in hex
                                // See http://www.w3.org/TR/REC-html40/charset.html#entities 
                                if (entity[1] == 'x' || entity[1] == 'X') 
                                    ch = (char) Int32.Parse(entity.Substring(2), NumberStyles.AllowHexSpecifier);
                                else 
                                    ch = (char) Int32.Parse(entity.Substring(1));
                                i = index; // already looked at everything until semicolon
                            }
                            catch (System.FormatException) { 
                                i++;    //if the number isn't valid, ignore it
                            } 
                            catch (System.ArgumentException) { 
                                i++;    // if there is no number, ignore it.
                            } 
                        }
                        else {
                            i = index; // already looked at everything until semicolon
 
                            char entityChar = HtmlEntities.Lookup(entity);
                            if (entityChar != (char)0) { 
                                ch = entityChar; 
                            }
                            else { 
                                output.Write('&');
                                output.Write(entity);
                                output.Write(';');
                                continue; 
                            }
                        } 
 
                    }
                } 

                output.Write(ch);
            }
        } 

 
        ///  
        ///    
        ///       HTML encodes a string and returns the encoded string. 
        ///    
        /// 
        public static String HtmlEncode(String s) {
            if (s == null) 
                return null;
 
            int pos = IndexOfHtmlEncodingChars(s, 0); 
            if (pos == -1)
                return s; 

            StringBuilder builder = new StringBuilder(s.Length + 5);
            int cch = s.Length;
            int startPos = 0; 
            for (;;) {
                if (pos > startPos) { 
                    builder.Append(s, startPos, pos - startPos); 
                }
 
                char ch = s[pos];
                if (ch <= '>') {
                    switch (ch) {
                        case '<': 
                            builder.Append("<");
                            break; 
                        case '>': 
                            builder.Append(">");
                            break; 
                        case '"':
                            builder.Append(""");
                            break;
                        case '&': 
                            builder.Append("&");
                            break; 
                        default: 
                            Debug.Assert(false, "Unexpected value for ch, ch=" + ch);
                            break; 
                    }
                }
                else {
#if ENTITY_ENCODE_HIGH_ASCII_CHARS 
                    Debug.Assert(ch >= 160 && ch < 256, "ch >= 160 && ch < 256");
 
                    // The seemingly arbitrary 160 comes from RFC 
                    builder.Append("&#");
                    builder.Append(((int)ch).ToString(NumberFormatInfo.InvariantInfo)); 
                    builder.Append(';');
#else
                    Debug.Assert(false);
#endif // ENTITY_ENCODE_HIGH_ASCII_CHARS 
                }
 
                startPos = pos + 1; 
                if (startPos >= cch)
                    break; 

                pos = IndexOfHtmlEncodingChars(s, startPos);
                if (pos == -1) {
                    builder.Append(s, startPos, cch - startPos); 
                    break;
                } 
            } 

            return builder.ToString(); 
        }


        ///  
        ///    
        ///       HTML encodes a string and returns the output to a TextWriter stream of 
        ///       output. 
        ///    
        ///  
        public unsafe static void HtmlEncode(String s, TextWriter output) {
            if (s == null)
                return;
 
            int index = IndexOfHtmlEncodingChars(s, 0);
            if (index == -1) { 
                output.Write(s); 
                return;
            } 

            Debug.Assert(0 <= index && index <= s.Length, "0 <= index && index <= s.Length");

            int cch = s.Length - index; 
            fixed (char * str = s) {
                char *pch = str; 
                while (index-- > 0) { 
                    output.Write(*pch++);
                } 

                while (cch-- > 0) {
                    char ch = *pch++;
                    if (ch <= '>') { 
                        switch (ch) {
                            case '<': 
                                output.Write("<"); 
                                break;
                            case '>': 
                                output.Write(">");
                                break;
                            case '"':
                                output.Write("""); 
                                break;
                            case '&': 
                                output.Write("&"); 
                                break;
                            default: 
                                output.Write(ch);
                                break;
                        }
                    } 
#if ENTITY_ENCODE_HIGH_ASCII_CHARS
                    else if (ch >= 160 && ch < 256) { 
                        // The seemingly arbitrary 160 comes from RFC 
                        output.Write("&#");
                        output.Write(((int)ch).ToString(NumberFormatInfo.InvariantInfo)); 
                        output.Write(';');
                    }
#endif // ENTITY_ENCODE_HIGH_ASCII_CHARS
                    else { 
                        output.Write(ch);
                    } 
                } 
            }
        } 

        static unsafe int IndexOfHtmlEncodingChars(string s, int startPos) {
            Debug.Assert(0 <= startPos && startPos <= s.Length, "0 <= startPos && startPos <= s.Length");
 
            int cch = s.Length - startPos;
            fixed (char * str = s) { 
                for (char *pch = &str[startPos]; cch > 0; pch++, cch--) { 
                    char ch = *pch;
                    if (ch <= '>') { 
                        switch (ch) {
                            case '<':
                            case '>':
                            case '"': 
                            case '&':
                                return s.Length - cch; 
                        } 
                    }
#if ENTITY_ENCODE_HIGH_ASCII_CHARS 
                    else if (ch >= 160 && ch < 256) {
                        return s.Length - cch;
                    }
#endif // ENTITY_ENCODE_HIGH_ASCII_CHARS 
                }
            } 
 
            return -1;
        } 


        /// 
        ///     
        ///       Encodes a string to make it a valid HTML attribute and returns the encoded string.
        ///     
        ///  
        public static String HtmlAttributeEncode(String s) {
            if (s == null) 
                return null;

            int pos = IndexOfHtmlAttributeEncodingChars(s, 0);
            if (pos == -1) 
                return s;
 
            StringBuilder builder = new StringBuilder(s.Length + 5); 
            int cch = s.Length;
            int startPos = 0; 
            for (;;) {
                if (pos > startPos) {
                    builder.Append(s, startPos, pos - startPos);
                } 

                char ch = s[pos]; 
                switch (ch) { 
                    case '"':
                        builder.Append("""); 
                        break;
                    case '&':
                        builder.Append("&");
                        break; 
                    case '<':
                        // Whidbey 32404: The character '<' is not valid in an XML attribute value. 
                        // (See the W3C XML rec). 
                        builder.Append("<");
                        break; 

                    default:
                        Debug.Assert(false, "Unexpected value for ch, ch=" + ch);
                        break; 
                }
 
                startPos = pos + 1; 
                if (startPos >= cch)
                    break; 

                pos = IndexOfHtmlAttributeEncodingChars(s, startPos);
                if (pos == -1) {
                    builder.Append(s, startPos, cch - startPos); 
                    break;
                } 
            } 

            return builder.ToString(); 
        }

        internal static void HtmlAttributeEncodeInternal(String s, HttpWriter writer) {
            int pos = IndexOfHtmlAttributeEncodingChars(s, 0); 
            if (pos == -1) {
                writer.Write(s); 
                return; 
            }
 
            int cch = s.Length;
            int startPos = 0;
            for (;;) {
                if (pos > startPos) { 
                    writer.WriteString(s, startPos, pos - startPos);
                } 
 
                char ch = s[pos];
                switch (ch) { 
                    case '"':
                        writer.Write(""");
                        break;
                    case '&': 
                        writer.Write("&");
                        break; 
                    case '<': 
                        // Whidbey 32404: The character '<' is not valid in an XML attribute value.
                        // (See the W3C XML rec). 
                        writer.Write("<");
                        break;
                }
 
                startPos = pos + 1;
                if (startPos >= cch) 
                    break; 

                pos = IndexOfHtmlAttributeEncodingChars(s, startPos); 
                if (pos == -1) {
                    writer.WriteString(s, startPos, cch - startPos);
                    break;
                } 
            }
        } 
 

 
        /// 
        ///    
        ///       Encodes a string to make it a valid HTML attribute and returns the output
        ///       to a TextWriter stream of 
        ///       output.
        ///     
        ///  
        public unsafe static void HtmlAttributeEncode(String s, TextWriter output) {
            if (s == null) 
                return;

            int index = IndexOfHtmlAttributeEncodingChars(s, 0);
            if (index == -1) { 
                output.Write(s);
            } 
            else { 
                int cch = s.Length - index;
                fixed (char * str = s) { 
                    char *pch = str;
                    while (index-- > 0) {
                        output.Write(*pch++);
                    } 

                    while (cch-- > 0) { 
                        char ch = *pch++; 
                        if (ch <= '<') {
                            switch (ch) { 
                                case '<':
                                    output.Write("<");
                                    break;
                                case '"': 
                                    output.Write(""");
                                    break; 
                                case '&': 
                                    output.Write("&");
                                    break; 
                                default:
                                    output.Write(ch);
                                    break;
                            } 
                        }
                        else { 
                            output.Write(ch); 
                        }
                    } 
                }
            }
        }
 
        static unsafe int IndexOfHtmlAttributeEncodingChars(string s, int startPos) {
            Debug.Assert(0 <= startPos && startPos <= s.Length, "0 <= startPos && startPos <= s.Length"); 
            int cch = s.Length - startPos; 
            fixed (char * str = s) {
                for (char *pch = &str[startPos]; cch > 0; pch++, cch--) { 
                    char ch = *pch;
                    if (ch <= '<') {
                        switch (ch) {
                            case '<': 
                            case '"':
                            case '&': 
                                return s.Length - cch; 
                        }
                    } 
                }
            }

            return -1; 
        }
 
 
        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) { if (str == null) return null; // recurse in case there is a query string int i = str.IndexOf('?'); if (i >= 0) return UrlPathEncode(str.Substring(0, i)) + str.Substring(i); // encode DBCS characters and spaces only return UrlEncodeSpaces(UrlEncodeNonAscii(str, Encoding.UTF8)); } 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) { if (String.IsNullOrEmpty(str)) return str; if (e == null) e = Encoding.UTF8; byte[] bytes = e.GetBytes(str); bytes = UrlEncodeBytesToBytesInternalNonAscii(bytes, 0, bytes.Length, false); return Encoding.ASCII.GetString(bytes); } // Helper to encode spaces only internal static String UrlEncodeSpaces(string str) { if (str != null && str.IndexOf(' ') >= 0) str = str.Replace(" ", "%20"); return str; } /// /// [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 UrlEncodeBytesToBytesInternal(bytes, 0, bytes.Length, false); } /// /// [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) { if (bytes == null && count == 0) return null; if (bytes == null) { throw new ArgumentNullException("bytes"); } if (offset < 0 || offset > bytes.Length) { throw new ArgumentOutOfRangeException("offset"); } if (count < 0 || offset+count > bytes.Length) { throw new ArgumentOutOfRangeException("count"); } return UrlEncodeBytesToBytesInternal(bytes, offset, count, true); } /// /// [To be supplied.] /// public static string UrlEncodeUnicode(string str) { if (str == null) return null; return UrlEncodeUnicodeStringToStringInternal(str, false); } /// /// [To be supplied.] /// 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) { if (str == null) return null; return UrlDecodeStringFromStringInternal(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) { if (bytes == null && count == 0) return null; if (bytes == null) { throw new ArgumentNullException("bytes"); } if (offset < 0 || offset > bytes.Length) { throw new ArgumentOutOfRangeException("offset"); } if (count < 0 || offset+count > bytes.Length) { throw new ArgumentOutOfRangeException("count"); } return UrlDecodeStringFromBytesInternal(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) { if (bytes == null && count == 0) return null; if (bytes == null) { throw new ArgumentNullException("bytes"); } if (offset < 0 || offset > bytes.Length) { throw new ArgumentOutOfRangeException("offset"); } if (count < 0 || offset+count > bytes.Length) { throw new ArgumentOutOfRangeException("count"); } return UrlDecodeBytesFromBytesInternal(bytes, offset, count); } // // Implementation for encoding // private static byte[] UrlEncodeBytesToBytesInternal(byte[] bytes, int offset, int count, bool alwaysCreateReturnValue) { int cSpaces = 0; int cUnsafe = 0; // count them first for (int i = 0; i < count; i++) { char ch = (char)bytes[offset+i]; if (ch == ' ') cSpaces++; else if (!IsSafe(ch)) cUnsafe++; } // nothing to expand? if (!alwaysCreateReturnValue && cSpaces == 0 && cUnsafe == 0) return bytes; // expand not 'safe' characters into %XX, spaces to +s byte[] expandedBytes = new byte[count + cUnsafe*2]; int pos = 0; for (int i = 0; i < count; i++) { byte b = bytes[offset+i]; char ch = (char)b; if (IsSafe(ch)) { expandedBytes[pos++] = b; } else if (ch == ' ') { expandedBytes[pos++] = (byte)'+'; } else { expandedBytes[pos++] = (byte)'%'; expandedBytes[pos++] = (byte)IntToHex((b >> 4) & 0xf); expandedBytes[pos++] = (byte)IntToHex(b & 0x0f); } } return expandedBytes; } private static bool IsNonAsciiByte(byte b) { return ( b >= 0x7F || b < 0x20 ); } private static byte[] UrlEncodeBytesToBytesInternalNonAscii(byte[] bytes, int offset, int count, bool alwaysCreateReturnValue) { int cNonAscii = 0; // count them first for (int i = 0; i < count; i++) { if ( IsNonAsciiByte(bytes[offset+i]) ) cNonAscii++; } // nothing to expand? if (!alwaysCreateReturnValue && cNonAscii == 0) return bytes; // expand not 'safe' characters into %XX, spaces to +s byte[] expandedBytes = new byte[count + cNonAscii*2]; int pos = 0; for (int i = 0; i < count; i++) { byte b = bytes[offset+i]; if (IsNonAsciiByte(b)) { expandedBytes[pos++] = (byte)'%'; expandedBytes[pos++] = (byte)IntToHex((b >> 4) & 0xf); expandedBytes[pos++] = (byte)IntToHex(b & 0x0f); } else { expandedBytes[pos++] = b; } } return expandedBytes; } private static string UrlEncodeUnicodeStringToStringInternal(string s, bool ignoreAscii) { int l = s.Length; StringBuilder sb = new StringBuilder(l); for (int i = 0; i < l; i++) { char ch = s[i]; if ((ch & 0xff80) == 0) { // 7 bit? if (ignoreAscii || IsSafe(ch)) { sb.Append(ch); } else if (ch == ' ') { sb.Append('+'); } else { sb.Append('%'); sb.Append(IntToHex((ch >> 4) & 0xf)); sb.Append(IntToHex((ch ) & 0xf)); } } else { // arbitrary Unicode? sb.Append("%u"); sb.Append(IntToHex((ch >> 12) & 0xf)); sb.Append(IntToHex((ch >> 8) & 0xf)); sb.Append(IntToHex((ch >> 4) & 0xf)); sb.Append(IntToHex((ch ) & 0xf)); } } return sb.ToString(); } // // Implementation for decoding // // Internal class to facilitate URL decoding -- keeps char buffer and byte buffer, allows appending of either chars or bytes private class UrlDecoder { private int _bufferSize; // Accumulate characters in a special array private int _numChars; private char[] _charBuffer; // Accumulate bytes for decoding into characters in a special array private int _numBytes; private byte[] _byteBuffer; // Encoding to convert chars to bytes private Encoding _encoding; private void FlushBytes() { if (_numBytes > 0) { _numChars += _encoding.GetChars(_byteBuffer, 0, _numBytes, _charBuffer, _numChars); _numBytes = 0; } } internal UrlDecoder(int bufferSize, Encoding encoding) { _bufferSize = bufferSize; _encoding = encoding; _charBuffer = new char[bufferSize]; // byte buffer created on demand } internal void AddChar(char ch) { if (_numBytes > 0) FlushBytes(); _charBuffer[_numChars++] = ch; } internal void AddByte(byte b) { // if there are no pending bytes treat 7 bit bytes as characters // this optimization is temp disable as it doesn't work for some encodings /* if (_numBytes == 0 && ((b & 0x80) == 0)) { AddChar((char)b); } else */ { if (_byteBuffer == null) _byteBuffer = new byte[_bufferSize]; _byteBuffer[_numBytes++] = b; } } internal String GetString() { if (_numBytes > 0) FlushBytes(); if (_numChars > 0) return new String(_charBuffer, 0, _numChars); else return String.Empty; } } internal static string CollapsePercentUFromStringInternal(string s, Encoding e) { int count = s.Length; UrlDecoder helper = new UrlDecoder(count, e); // go thorugh the string's chars collapsing just %uXXXX and // appending each char as char int loc = s.IndexOf("%u", StringComparison.Ordinal); if(loc == -1) { return s; } for (int pos = 0; pos < count; pos++) { char ch = s[pos]; if (ch == '%' && pos < count-5) { if(s[pos+1] == 'u') { int h1 = HexToInt(s[pos+2]); int h2 = HexToInt(s[pos+3]); int h3 = HexToInt(s[pos+4]); int h4 = HexToInt(s[pos+5]); if (h1 >= 0 && h2 >= 0 && h3 >= 0 && h4 >= 0) { //valid 4 hex chars ch = (char)((h1 << 12) | (h2 << 8) | (h3 << 4) | h4); pos += 5; // add as char helper.AddChar(ch); continue; } } } if ((ch & 0xFF80) == 0) helper.AddByte((byte)ch); // 7 bit have to go as bytes because of Unicode else helper.AddChar(ch); } return helper.GetString(); } private static string UrlDecodeStringFromStringInternal(string s, Encoding e) { int count = s.Length; UrlDecoder helper = new UrlDecoder(count, e); // go through the string's chars collapsing %XX and %uXXXX and // appending each char as char, with exception of %XX constructs // that are appended as bytes for (int pos = 0; pos < count; pos++) { char ch = s[pos]; if (ch == '+') { ch = ' '; } else if (ch == '%' && pos < count-2) { if (s[pos+1] == 'u' && pos < count-5) { int h1 = HexToInt(s[pos+2]); int h2 = HexToInt(s[pos+3]); int h3 = HexToInt(s[pos+4]); int h4 = HexToInt(s[pos+5]); if (h1 >= 0 && h2 >= 0 && h3 >= 0 && h4 >= 0) { // valid 4 hex chars ch = (char)((h1 << 12) | (h2 << 8) | (h3 << 4) | h4); pos += 5; // only add as char helper.AddChar(ch); continue; } } else { int h1 = HexToInt(s[pos+1]); int h2 = HexToInt(s[pos+2]); if (h1 >= 0 && h2 >= 0) { // valid 2 hex chars byte b = (byte)((h1 << 4) | h2); pos += 2; // don't add as char helper.AddByte(b); continue; } } } if ((ch & 0xFF80) == 0) helper.AddByte((byte)ch); // 7 bit have to go as bytes because of Unicode else helper.AddChar(ch); } return helper.GetString(); } private static string UrlDecodeStringFromBytesInternal(byte[] buf, int offset, int count, Encoding e) { UrlDecoder helper = new UrlDecoder(count, e); // go through the bytes collapsing %XX and %uXXXX and appending // each byte as byte, with exception of %uXXXX constructs that // are appended as chars for (int i = 0; i < count; i++) { int pos = offset + i; byte b = buf[pos]; // The code assumes that + and % cannot be in multibyte sequence if (b == '+') { b = (byte)' '; } else if (b == '%' && i < count-2) { if (buf[pos+1] == 'u' && i < count-5) { int h1 = HexToInt((char)buf[pos+2]); int h2 = HexToInt((char)buf[pos+3]); int h3 = HexToInt((char)buf[pos+4]); int h4 = HexToInt((char)buf[pos+5]); if (h1 >= 0 && h2 >= 0 && h3 >= 0 && h4 >= 0) { // valid 4 hex chars char ch = (char)((h1 << 12) | (h2 << 8) | (h3 << 4) | h4); i += 5; // don't add as byte helper.AddChar(ch); continue; } } else { int h1 = HexToInt((char)buf[pos+1]); int h2 = HexToInt((char)buf[pos+2]); if (h1 >= 0 && h2 >= 0) { // valid 2 hex chars b = (byte)((h1 << 4) | h2); i += 2; } } } helper.AddByte(b); } return helper.GetString(); } private static byte[] UrlDecodeBytesFromBytesInternal(byte[] buf, int offset, int count) { int decodedBytesCount = 0; byte[] decodedBytes = new byte[count]; for (int i = 0; i < count; i++) { int pos = offset + i; byte b = buf[pos]; if (b == '+') { b = (byte)' '; } else if (b == '%' && i < count-2) { int h1 = HexToInt((char)buf[pos+1]); int h2 = HexToInt((char)buf[pos+2]); if (h1 >= 0 && h2 >= 0) { // valid 2 hex chars b = (byte)((h1 << 4) | h2); i += 2; } } decodedBytes[decodedBytesCount++] = b; } if (decodedBytesCount < decodedBytes.Length) { byte[] newDecodedBytes = new byte[decodedBytesCount]; Array.Copy(decodedBytes, newDecodedBytes, decodedBytesCount); decodedBytes = newDecodedBytes; } return decodedBytes; } // // Private helpers for URL encoding/decoding // private static int HexToInt(char h) { return( h >= '0' && h <= '9' ) ? h - '0' : ( h >= 'a' && h <= 'f' ) ? h - 'a' + 10 : ( h >= 'A' && h <= 'F' ) ? h - 'A' + 10 : -1; } internal static char IntToHex(int n) { Debug.Assert(n < 0x10); if (n <= 9) return(char)(n + (int)'0'); else return(char)(n - 10 + (int)'a'); } // Set of safe chars, from RFC 1738.4 minus '+' internal static bool IsSafe(char ch) { if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9') return true; switch (ch) { case '-': case '_': case '.': case '!': case '*': case '\'': case '(': case ')': return true; } return false; } ////////////////////////////////////////////////////////////////////////// // // 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); } } // helper class for lookup of HTML encoding entities internal class HtmlEntities { private static object _lookupLockObject = new object(); // The list is from http://www.w3.org/TR/REC-html40/sgml/entities.html private static String[] _entitiesList = new String[] { "\x0022-quot", "\x0026-amp", "\x003c-lt", "\x003e-gt", "\x00a0-nbsp", "\x00a1-iexcl", "\x00a2-cent", "\x00a3-pound", "\x00a4-curren", "\x00a5-yen", "\x00a6-brvbar", "\x00a7-sect", "\x00a8-uml", "\x00a9-copy", "\x00aa-ordf", "\x00ab-laquo", "\x00ac-not", "\x00ad-shy", "\x00ae-reg", "\x00af-macr", "\x00b0-deg", "\x00b1-plusmn", "\x00b2-sup2", "\x00b3-sup3", "\x00b4-acute", "\x00b5-micro", "\x00b6-para", "\x00b7-middot", "\x00b8-cedil", "\x00b9-sup1", "\x00ba-ordm", "\x00bb-raquo", "\x00bc-frac14", "\x00bd-frac12", "\x00be-frac34", "\x00bf-iquest", "\x00c0-Agrave", "\x00c1-Aacute", "\x00c2-Acirc", "\x00c3-Atilde", "\x00c4-Auml", "\x00c5-Aring", "\x00c6-AElig", "\x00c7-Ccedil", "\x00c8-Egrave", "\x00c9-Eacute", "\x00ca-Ecirc", "\x00cb-Euml", "\x00cc-Igrave", "\x00cd-Iacute", "\x00ce-Icirc", "\x00cf-Iuml", "\x00d0-ETH", "\x00d1-Ntilde", "\x00d2-Ograve", "\x00d3-Oacute", "\x00d4-Ocirc", "\x00d5-Otilde", "\x00d6-Ouml", "\x00d7-times", "\x00d8-Oslash", "\x00d9-Ugrave", "\x00da-Uacute", "\x00db-Ucirc", "\x00dc-Uuml", "\x00dd-Yacute", "\x00de-THORN", "\x00df-szlig", "\x00e0-agrave", "\x00e1-aacute", "\x00e2-acirc", "\x00e3-atilde", "\x00e4-auml", "\x00e5-aring", "\x00e6-aelig", "\x00e7-ccedil", "\x00e8-egrave", "\x00e9-eacute", "\x00ea-ecirc", "\x00eb-euml", "\x00ec-igrave", "\x00ed-iacute", "\x00ee-icirc", "\x00ef-iuml", "\x00f0-eth", "\x00f1-ntilde", "\x00f2-ograve", "\x00f3-oacute", "\x00f4-ocirc", "\x00f5-otilde", "\x00f6-ouml", "\x00f7-divide", "\x00f8-oslash", "\x00f9-ugrave", "\x00fa-uacute", "\x00fb-ucirc", "\x00fc-uuml", "\x00fd-yacute", "\x00fe-thorn", "\x00ff-yuml", "\x0152-OElig", "\x0153-oelig", "\x0160-Scaron", "\x0161-scaron", "\x0178-Yuml", "\x0192-fnof", "\x02c6-circ", "\x02dc-tilde", "\x0391-Alpha", "\x0392-Beta", "\x0393-Gamma", "\x0394-Delta", "\x0395-Epsilon", "\x0396-Zeta", "\x0397-Eta", "\x0398-Theta", "\x0399-Iota", "\x039a-Kappa", "\x039b-Lambda", "\x039c-Mu", "\x039d-Nu", "\x039e-Xi", "\x039f-Omicron", "\x03a0-Pi", "\x03a1-Rho", "\x03a3-Sigma", "\x03a4-Tau", "\x03a5-Upsilon", "\x03a6-Phi", "\x03a7-Chi", "\x03a8-Psi", "\x03a9-Omega", "\x03b1-alpha", "\x03b2-beta", "\x03b3-gamma", "\x03b4-delta", "\x03b5-epsilon", "\x03b6-zeta", "\x03b7-eta", "\x03b8-theta", "\x03b9-iota", "\x03ba-kappa", "\x03bb-lambda", "\x03bc-mu", "\x03bd-nu", "\x03be-xi", "\x03bf-omicron", "\x03c0-pi", "\x03c1-rho", "\x03c2-sigmaf", "\x03c3-sigma", "\x03c4-tau", "\x03c5-upsilon", "\x03c6-phi", "\x03c7-chi", "\x03c8-psi", "\x03c9-omega", "\x03d1-thetasym", "\x03d2-upsih", "\x03d6-piv", "\x2002-ensp", "\x2003-emsp", "\x2009-thinsp", "\x200c-zwnj", "\x200d-zwj", "\x200e-lrm", "\x200f-rlm", "\x2013-ndash", "\x2014-mdash", "\x2018-lsquo", "\x2019-rsquo", "\x201a-sbquo", "\x201c-ldquo", "\x201d-rdquo", "\x201e-bdquo", "\x2020-dagger", "\x2021-Dagger", "\x2022-bull", "\x2026-hellip", "\x2030-permil", "\x2032-prime", "\x2033-Prime", "\x2039-lsaquo", "\x203a-rsaquo", "\x203e-oline", "\x2044-frasl", "\x20ac-euro", "\x2111-image", "\x2118-weierp", "\x211c-real", "\x2122-trade", "\x2135-alefsym", "\x2190-larr", "\x2191-uarr", "\x2192-rarr", "\x2193-darr", "\x2194-harr", "\x21b5-crarr", "\x21d0-lArr", "\x21d1-uArr", "\x21d2-rArr", "\x21d3-dArr", "\x21d4-hArr", "\x2200-forall", "\x2202-part", "\x2203-exist", "\x2205-empty", "\x2207-nabla", "\x2208-isin", "\x2209-notin", "\x220b-ni", "\x220f-prod", "\x2211-sum", "\x2212-minus", "\x2217-lowast", "\x221a-radic", "\x221d-prop", "\x221e-infin", "\x2220-ang", "\x2227-and", "\x2228-or", "\x2229-cap", "\x222a-cup", "\x222b-int", "\x2234-there4", "\x223c-sim", "\x2245-cong", "\x2248-asymp", "\x2260-ne", "\x2261-equiv", "\x2264-le", "\x2265-ge", "\x2282-sub", "\x2283-sup", "\x2284-nsub", "\x2286-sube", "\x2287-supe", "\x2295-oplus", "\x2297-otimes", "\x22a5-perp", "\x22c5-sdot", "\x2308-lceil", "\x2309-rceil", "\x230a-lfloor", "\x230b-rfloor", "\x2329-lang", "\x232a-rang", "\x25ca-loz", "\x2660-spades", "\x2663-clubs", "\x2665-hearts", "\x2666-diams", }; private static Hashtable _entitiesLookupTable; private HtmlEntities() { } internal /*public*/ static char Lookup(String entity) { if (_entitiesLookupTable == null) { // populate hashtable on demand lock (_lookupLockObject) { if (_entitiesLookupTable == null) { Hashtable t = new Hashtable(); foreach (String s in _entitiesList) t[s.Substring(2)] = s[0]; // 1st char is the code, 2nd '-' _entitiesLookupTable = t; } } } Object obj = _entitiesLookupTable[entity]; if (obj != null) return (char)obj; else return (char)0; } } }

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK