Util.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / xsp / System / Web / UI / Util.cs / 1 / Util.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 * Implements various utility functions used by the template code 
 *
 * Copyright (c) 1998 Microsoft Corporation 
 */

namespace System.Web.UI {
 
using System;
using System.Collections; 
using System.Collections.Generic; 
using System.Collections.Specialized;
using System.ComponentModel; 
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO; 
using System.Reflection;
using System.Runtime.Serialization.Formatters; 
using System.Text; 
using System.Text.RegularExpressions;
using System.Web.Hosting; 
using System.Web.Configuration;
using System.Web.Compilation;
using System.Web.Security;
using System.Web.UI.WebControls; 
using System.Web.Util;
using System.Security; 
using System.Security.Permissions; 
using System.Web.Management;
using Microsoft.Win32; 
using Debug=System.Web.Util.Debug;

internal static class Util {
    private static Dictionary s_validCultureNames = null; 

    [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)] 
    internal static string SerializeWithAssert(IStateFormatter formatter, object stateGraph) { 
        return formatter.Serialize(stateGraph);
    } 

    [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)]
    internal static object DeserializeWithAssert(IStateFormatter formatter, string serializedState) {
        return formatter.Deserialize(serializedState); 
    }
 
    internal static bool CanConvertToFrom(TypeConverter converter, Type type) { 
        return (converter != null && converter.CanConvertTo(type) &&
                converter.CanConvertFrom(type) && !(converter is ReferenceConverter)); 
    }

    internal static void CopyBaseAttributesToInnerControl(WebControl control, WebControl child) {
        short oldTab = control.TabIndex; 
        string oldAccess = control.AccessKey;
        try { 
            control.AccessKey = String.Empty; 
            control.TabIndex = 0;
            child.CopyBaseAttributes(control); 
        }
        finally {
            control.TabIndex = oldTab;
            control.AccessKey = oldAccess; 
        }
    } 
 
    internal static long GetRecompilationHash(PagesSection ps)
    { 
        HashCodeCombiner recompilationHash = new HashCodeCombiner();
        NamespaceCollection namespaces;
        TagPrefixCollection controls;
        TagMapCollection tagMapping; 

        // Combine items from Pages section 
        recompilationHash.AddObject(ps.Buffer); 
        recompilationHash.AddObject(ps.EnableViewState);
        recompilationHash.AddObject(ps.EnableViewStateMac); 
        recompilationHash.AddObject(ps.EnableEventValidation);
        recompilationHash.AddObject(ps.SmartNavigation);
        recompilationHash.AddObject(ps.ValidateRequest);
        recompilationHash.AddObject(ps.AutoEventWireup); 
        if (ps.PageBaseTypeInternal != null) {
            recompilationHash.AddObject(ps.PageBaseTypeInternal.FullName); 
        } 
        if (ps.UserControlBaseTypeInternal != null) {
            recompilationHash.AddObject(ps.UserControlBaseTypeInternal.FullName); 
        }
        if (ps.PageParserFilterTypeInternal != null) {
            recompilationHash.AddObject(ps.PageParserFilterTypeInternal.FullName);
        } 
        recompilationHash.AddObject(ps.MasterPageFile);
        recompilationHash.AddObject(ps.Theme); 
        recompilationHash.AddObject(ps.StyleSheetTheme); 
        recompilationHash.AddObject(ps.EnableSessionState);
        recompilationHash.AddObject(ps.CompilationMode); 
        recompilationHash.AddObject(ps.MaxPageStateFieldLength);
        recompilationHash.AddObject(ps.ViewStateEncryptionMode);
        recompilationHash.AddObject(ps.MaintainScrollPositionOnPostBack);
 
        // Combine items from Namespaces collection
        namespaces = ps.Namespaces; 
 
        recompilationHash.AddObject(namespaces.AutoImportVBNamespace);
        if (namespaces.Count == 0) { 
            recompilationHash.AddObject("__clearnamespaces");
        }
        else {
            foreach (NamespaceInfo ni in namespaces) { 
                recompilationHash.AddObject(ni.Namespace);
            } 
        } 

        // Combine items from the Controls collection 
        controls = ps.Controls;

        if (controls.Count == 0) {
            recompilationHash.AddObject("__clearcontrols"); 
        }
        else { 
            foreach (TagPrefixInfo tpi in controls) { 
                recompilationHash.AddObject(tpi.TagPrefix);
 
                if (tpi.TagName != null && tpi.TagName.Length != 0) {
                    recompilationHash.AddObject(tpi.TagName);
                    recompilationHash.AddObject(tpi.Source);
                } 
                else {
                    recompilationHash.AddObject(tpi.Namespace); 
                    recompilationHash.AddObject(tpi.Assembly); 
                }
            } 
        }

        // Combine items from the TagMapping Collection
        tagMapping = ps.TagMapping; 

        if (tagMapping.Count == 0) { 
            recompilationHash.AddObject("__cleartagmapping"); 
        }
        else { 
            foreach (TagMapInfo tmi in tagMapping) {
                recompilationHash.AddObject(tmi.TagType);
                recompilationHash.AddObject(tmi.MappedTagType);
            } 
        }
 
        return recompilationHash.CombinedHash; 
    }
 

#if UNUSED
    /*
     *  Return a String which holds the contents of a TextReader 
     */
    public static String StringFromReader(TextReader input) { 
        char[] buffer = new char[4096]; 
        int bufferpos = 0;
        int delta; 

        for (;;) {
            delta = input.Read(buffer, bufferpos, buffer.Length - bufferpos);
 
            if (delta == 0)
                break; 
 
            bufferpos += delta;
 
            if (bufferpos == buffer.Length) {
                char[] newbuf = new char[buffer.Length * 2];
                System.Array.Copy(buffer, 0, newbuf, 0, buffer.Length);
                buffer = newbuf; 
            }
        } 
 
        return new String(buffer, 0, bufferpos);
    } 
#endif

    internal static Encoding GetEncodingFromConfigPath(VirtualPath configPath) {
 
        Debug.Assert(configPath != null, "configPath != null");
 
        // Check if a file encoding is specified in the config 
        Encoding fileEncoding = null;
        GlobalizationSection globConfig = RuntimeConfig.GetConfig(configPath).Globalization; 
        fileEncoding = globConfig.FileEncoding;

        // If not, use the default encoding
        if (fileEncoding == null) 
            fileEncoding = Encoding.Default;
 
        return fileEncoding; 
    }
 
    /*
     * Return a reader which holds the contents of a file.  If a configPath is passed
     * in, try to get an encoding for it
     */ 
    internal /*public*/ static StreamReader ReaderFromFile(string filename, VirtualPath configPath) {
 
        StreamReader reader; 

        // Check if a file encoding is specified in the config 
        Encoding fileEncoding = Encoding.Default;
        if (configPath != null) fileEncoding = GetEncodingFromConfigPath(configPath);

        try { 
            // Create a reader on the file, using the encoding
            // Throws an exception if the file can't be opened. 
            reader = new StreamReader(filename, fileEncoding, 
                true /*detectEncodingFromByteOrderMarks*/, 4096);
        } 
        catch (UnauthorizedAccessException) {
            // AccessException might mean two very different things: it could be a real
            // access problem, or it could be that it's actually a directory.
 
            // It's a directory: give a specific error.
            if (FileUtil.DirectoryExists(filename)) { 
                throw new HttpException( 
                    SR.GetString(SR.Unexpected_Directory, HttpRuntime.GetSafePath(filename)));
            } 

            // It's a real access problem, so just rethrow it
            throw;
        } 

        return reader; 
    } 

    /* 
     * Attempt to delete a file, but don't throw if it can't be done
     */
    internal static void DeleteFileNoException(string path) {
        Debug.Assert(File.Exists(path)); 
        try {
            File.Delete(path); 
        } 
        catch { } // Ignore all exceptions
    } 

    internal static void DeleteFileIfExistsNoException(string path) {
        if (File.Exists(path))
            DeleteFileNoException(path); 
    }
 
    /* 
     * Return true if the directory exists and is not empty.
     */ 
    internal static bool IsNonEmptyDirectory(string dir) {

        // Does it exist
        if (!Directory.Exists(dir)) 
            return false;
 
        // It exists, but maybe it's empty 
        try {
            string[] entries = Directory.GetFileSystemEntries(dir); 
            return entries.Length > 0;
        }
        catch {
            // If it throws, assume it's non-empty 
            return true;
        } 
    } 

    /* 
     * Return true if string is a valid simple file name (with no path or wild cards)
     */
    private static char[] invalidFileNameChars = new char[] { '/', '\\', '?', '*', ':' } ;
    internal static bool IsValidFileName(string fileName) { 

        // Check for the special names "." and ".." 
        if (fileName == "." || fileName == "..") 
            return false;
 
        // Check for invalid characters
        if (fileName.IndexOfAny(invalidFileNameChars) >= 0)
            return false;
 
        return true;
    } 
 
    /*
     * Replace all invalid chars in a filename by underscores. 
     */
    internal static string MakeValidFileName(string fileName) {

        // If it's already valid, nothing to do 
        if (IsValidFileName(fileName))
            return fileName; 
 
        // Replace all the invalid chars by '_'
        for (int i = 0; i < invalidFileNameChars.Length; ++i)  { 
            fileName = fileName.Replace(invalidFileNameChars[i], '_');
        }

        // Shoud always be valid now 
        Debug.Assert(IsValidFileName(fileName));
 
        return fileName; 
    }
 
    /*
     * Return true if the current user has write access to the directory
     */
    internal static bool HasWriteAccessToDirectory(string dir) { 

        // If it doesn't even exist (or we can't determine that it does), return false 
        if (!Directory.Exists(dir)) 
            return false;
 
        // Get the path to a dummy file in that directory
        string dummyFile = Path.Combine(dir, "~AspAccessCheck_" +
            HostingEnvironment.AppDomainUniqueInteger.ToString(
                "x", CultureInfo.InvariantCulture) + ".tmp"); 
        FileStream fs = null;
 
        bool success = false; 
        try {
            // Attempt to create the file 
            fs = new FileStream(dummyFile, FileMode.Create);
        }
        catch {
        } 
        finally {
            if (fs != null) { 
                // If successfully created, close and delete it 
                fs.Close();
                File.Delete(dummyFile); 
                success = true;
            }
        }
 
        return success;
 
// 
#if UNUSED
        FileSecurityDescriptorWrapper oSecDesc = new FileSecurityDescriptorWrapper(dir); 
        bool fAllowed = oSecDesc.IsAccessAllowed(WindowsIdentity.GetCurrent().Token, 0x3 /*R/W*/);
        return fAllowed;
#endif
    } 

    internal static VirtualPath GetScriptLocation() { 
        // prepare script include 
        string location = (string) RuntimeConfig.GetRootWebConfig().WebControls["clientScriptsLocation"];
 
        // If there is a formatter, as there will be for the default machine.config, insert the assembly name and version.
        if (location.IndexOf("{0}", StringComparison.Ordinal) >= 0) {
            string assembly = "system_web";
 
            // QFE number is not included in client path
            string version = VersionInfo.EngineVersion.Substring(0, VersionInfo.EngineVersion.LastIndexOf('.')).Replace('.', '_'); 
            location = String.Format(CultureInfo.InvariantCulture, location, assembly, version); 
        }
 
        return VirtualPath.Create(location);
    }

    /* 
     * Return a reader which holds the contents of a file.  If a configPath is passed
     * in, try to get a encoding for it 
     */ 
    internal /*public*/ static StreamReader ReaderFromStream(Stream stream, VirtualPath configPath) {
 
        // Check if a file encoding is specified in the config
        Encoding fileEncoding = GetEncodingFromConfigPath(configPath);

        // Create a reader on the file, using the encoding 
        return new StreamReader(stream, fileEncoding,
            true /*detectEncodingFromByteOrderMarks*/, 4096); 
    } 

    /* 
     * Return a String which holds the contents of a file
     */
    internal /*public*/ static String StringFromVirtualPath(VirtualPath virtualPath) {
 
        using (Stream stream = virtualPath.OpenFile()) {
            // Create a reader on the file, and read the whole thing 
            TextReader reader = Util.ReaderFromStream(stream, virtualPath); 
            return reader.ReadToEnd();
        } 
    }

    /*
     * Return a String which holds the contents of a file 
     */
    internal /*public*/ static String StringFromFile(string path) { 
        Encoding encoding = Encoding.Default; 
        return StringFromFile(path, ref encoding);
    } 

    /*
     * Return a String which holds the contents of a file with specific encoding.
     */ 
    internal /*public*/ static String StringFromFile(string path, ref Encoding encoding) {
 
        // Create a reader on the file. 
        // Generates an exception if the file can't be opened.
        StreamReader reader = new StreamReader(path, encoding, true /*detectEncodingFromByteOrderMarks*/); 

        try {
            string content = reader.ReadToEnd();
            encoding = reader.CurrentEncoding; 

            return content; 
        } 
        finally {
            // Make sure we always close the stream 
            if (reader != null)
                reader.Close();
        }
    } 

    /* 
     * Return a String which holds the contents of a file, or null if the file 
     * doesn't exist.
     */ 
    internal /*public*/ static String StringFromFileIfExists(string path) {

        if (!File.Exists(path)) return null;
 
        return StringFromFile(path);
    } 
 
    /*
     * If the file doesn't exist, do nothing.  If it does try to delete it if possible. 
     * If that fails, rename it with by appending a .delete extension to it
     */
    internal static void RemoveOrRenameFile(string filename) {
        FileInfo fi = new FileInfo(filename); 
        RemoveOrRenameFile(fi);
    } 
 
    /*
     * If the file doesn't exist, do nothing.  If it does try to delete it if possible. 
     * If that fails, rename it with by appending a .delete extension to it
     */
    internal static bool RemoveOrRenameFile(FileInfo f) {
        try { 
            // First, just try to delete the file
            f.Delete(); 
 
            // It was successfully deleted, so return true
            return true; 
        }
        catch {

            try { 
                // If the delete failed, rename it to ".delete"
                // Don't do that if it already has the delete extension 
                if (f.Extension != ".delete") { 

                    // include a unique token as part of the new name, to avoid 
                    // conflicts with previous renames (VSWhidbey 79996)
                    string uniqueToken = DateTime.Now.Ticks.GetHashCode().ToString("x", CultureInfo.InvariantCulture);
                    string newName = f.FullName + "." + uniqueToken + ".delete";
                    f.MoveTo(newName); 
                }
            } 
            catch { 
                // Ignore all exceptions
            } 
        }

        // Return false because we couldn't delete it, and had to rename it
        return false; 
    }
 
    /* 
     * Clears a file's readonly attribute if it has one
     */ 
    internal static void ClearReadOnlyAttribute(string path) {

        FileAttributes attribs = File.GetAttributes(path);
        if ((attribs & FileAttributes.ReadOnly) != 0) { 
            File.SetAttributes(path, attribs & ~FileAttributes.ReadOnly);
        } 
    } 

    internal static void CheckVirtualFileExists(VirtualPath virtualPath) { 
        if (!virtualPath.FileExists()) {
            throw new HttpException(
                HttpStatus.NotFound,
                SR.GetString(SR.FileName_does_not_exist, 
                    virtualPath.VirtualPathString));
        } 
    } 

    internal static bool VirtualFileExistsWithAssert(VirtualPath virtualPath) { 
        string physicalDir = virtualPath.MapPathInternal();

        if (physicalDir != null) {
            (InternalSecurityPermissions.PathDiscovery(physicalDir)).Assert(); 
        }
 
        return virtualPath.FileExists(); 
    }
 
    internal static void CheckThemeAttribute(string themeName) {
        if (themeName.Length > 0) {
            if (!FileUtil.IsValidDirectoryName(themeName)) {
                throw new HttpException(SR.GetString(SR.Page_theme_invalid_name, themeName)); 
            }
 
            if (!ThemeExists(themeName)) { 
                throw new HttpException(SR.GetString(SR.Page_theme_not_found, themeName));
            } 
        }
    }

    internal static bool ThemeExists(string themeName) { 
        VirtualPath virtualDir = ThemeDirectoryCompiler.GetAppThemeVirtualDir(themeName);
        if (!VirtualDirectoryExistsWithAssert(virtualDir)) { 
            virtualDir = ThemeDirectoryCompiler.GetGlobalThemeVirtualDir(themeName); 
            if (!VirtualDirectoryExistsWithAssert(virtualDir)) {
                return false; 
            }
        }

        return true; 
    }
 
    private static bool VirtualDirectoryExistsWithAssert(VirtualPath virtualDir) { 
        try {
            String physicalDir = virtualDir.MapPathInternal(); 
            if (physicalDir != null) {
                new FileIOPermission(FileIOPermissionAccess.Read, physicalDir).Assert();
            }
 
            return virtualDir.DirectoryExists();
        } 
        catch { 
            return false;
        } 
    }

    internal static void CheckAssignableType(Type baseType, Type type) {
        if (!baseType.IsAssignableFrom(type)) { 
            throw new HttpException(
                SR.GetString(SR.Type_doesnt_inherit_from_type, 
                    type.FullName, baseType.FullName)); 
        }
    } 

    internal /*public*/ static int LineCount(string text, int offset, int newoffset) {

        Debug.Assert(offset <= newoffset); 

        int linecount = 0; 
 
        while (offset < newoffset) {
            if (text[offset] == '\r' || (text[offset] == '\n' && (offset == 0 || text[offset - 1] != '\r'))) 
                linecount++;
            offset++;
        }
 
        return linecount;
    } 
 
    /*
     * Calls Invoke on a MethodInfo.  If an exception happens during the 
     * method call, catch it and throw it back.
     */
    internal static object InvokeMethod(
                                       MethodInfo methodInfo, 
                                       object obj,
                                       object[] parameters) { 
        try { 
            return methodInfo.Invoke(obj, parameters);
        } 
        catch (TargetInvocationException e) {
            throw e.InnerException;
        }
    } 

    /* 
     * If the passed in Type has a non-private field with the passed in name, 
     * return the field's Type.
     */ 
    internal static Type GetNonPrivateFieldType(Type classType, string fieldName) {
        FieldInfo fieldInfo = classType.GetField(fieldName,
            BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
 
        if (fieldInfo == null || fieldInfo.IsPrivate)
            return null; 
 
        return fieldInfo.FieldType;
    } 

    /*
     * If the passed in Type has a non-private property with the passed in name,
     * return the property's Type. 
     */
    internal static Type GetNonPrivatePropertyType(Type classType, string propName) { 
        PropertyInfo propInfo = null; 

        BindingFlags flags = BindingFlags.Public | BindingFlags.Instance 
            | BindingFlags.IgnoreCase | BindingFlags.NonPublic;

        try {
            propInfo = classType.GetProperty(propName, flags); 
        }
        catch (AmbiguousMatchException) { 
 
            // We could get an AmbiguousMatchException if the property exists on two
            // different ancestor classes (VSWhidbey 216957).  When that happens, attempt 
            // a lookup on the Type itself, ignoring its ancestors.

            flags |= BindingFlags.DeclaredOnly;
            propInfo = classType.GetProperty(propName, flags); 
        }
 
        if (propInfo == null) 
            return null;
 
        // If it doesn't have a setter, ot if it's private, fail
        MethodInfo methodInfo = propInfo.GetSetMethod(true /*nonPublic*/);
        if (methodInfo == null || methodInfo.IsPrivate)
            return null; 

        return propInfo.PropertyType; 
    } 

    /* 
     * Return the first key of the dictionary as a string.  Throws if it's
     * empty or if the key is not a string.
     */
    private static string FirstDictionaryKey(IDictionary dict) { 
        IDictionaryEnumerator e = dict.GetEnumerator();
        e.MoveNext(); 
        return (string)e.Key; 
    }
 
    /*
     * Get a value from a dictionary, and remove it from the dictionary if
     * it exists.
     */ 
    private static string GetAndRemove(IDictionary dict, string key) {
        string val = (string) dict[key]; 
        if (val != null) { 
            dict.Remove(key);
            val = val.Trim(); 
        }
        return val;
    }
 
    /*
     * Get a value from a dictionary, and remove it from the dictionary if 
     * it exists.  Throw an exception if the value is a whitespace string. 
     * However, don't complain about null, which simply means the value is not
     * in the dictionary. 
     */
    internal static string GetAndRemoveNonEmptyAttribute(IDictionary directives, string key, bool required) {
        string val = Util.GetAndRemove(directives, key);
 
        if (val == null) {
            if (required) 
                throw new HttpException(SR.GetString(SR.Missing_attr, key)); 

            return null; 
        }

        return GetNonEmptyAttribute(key, val);
    } 

    // Return the value, after checking that it's not empty 
    internal static string GetNonEmptyAttribute(string name, string value) { 

        value = value.Trim(); 

        if (value.Length == 0) {
            throw new HttpException(
                SR.GetString(SR.Empty_attribute, name)); 
        }
 
        return value; 
    }
 
    // Return the value, after checking that it doesn't contain spaces
    internal static string GetNoSpaceAttribute(string name, string value) {
        if (Util.ContainsWhiteSpace(value)) {
            throw new HttpException( 
                SR.GetString(SR.Space_attribute, name));
        } 
 
        return value;
    } 

    internal static string GetAndRemoveNonEmptyAttribute(IDictionary directives, string key) {
        return GetAndRemoveNonEmptyAttribute(directives, key, false /*required*/);
    } 

    internal static VirtualPath GetAndRemoveVirtualPathAttribute(IDictionary directives, string key) { 
        return GetAndRemoveVirtualPathAttribute(directives, key, false /*required*/); 
    }
 
    internal static VirtualPath GetAndRemoveVirtualPathAttribute(IDictionary directives, string key, bool required) {

        string val = GetAndRemoveNonEmptyAttribute(directives, key, required);
        if (val == null) 
            return null;
 
        return VirtualPath.Create(val); 
    }
 
    /*
     * Parse a DeviceName:AttribName string into its components
     */
    internal const char DeviceFilterSeparator = ':'; 
    internal const string XmlnsAttribute = "xmlns:";
    public static string ParsePropertyDeviceFilter(string input, out string propName) { 
        string deviceName = String.Empty; 

        // If the string has no device filter, the whole string is the property name 
        if (input.IndexOf(DeviceFilterSeparator) < 0) {
            propName = input;
        }
        // Don't treat xmlns as filters, this needs to be treated differently. 
        // VSWhidbey 495125
        else if (StringUtil.StringStartsWithIgnoreCase(input, XmlnsAttribute)) { 
            propName = input; 
        }
        else { 
            // There is a filter: parse it out
            string[] tmp = input.Split(DeviceFilterSeparator);

            if (tmp.Length > 2) { 
                throw new HttpException(
                    SR.GetString(SR.Too_many_filters, input)); 
            } 

            deviceName = tmp[0]; 
            propName = tmp[1];
        }

        return deviceName; 
    }
 
    ///  
    /// Combines the filter and name
    ///  
    public static string CreateFilteredName(string deviceName, string name) {
        if (deviceName.Length > 0) {
            return deviceName + DeviceFilterSeparator + name;
        } 
        return name;
    } 
 
    internal static string GetAndRemoveRequiredAttribute(IDictionary directives, string key) {
        return GetAndRemoveNonEmptyAttribute(directives, key, true /*required*/); 
    }

#if UNUSED
    /* 
     * Same as GetAndRemove, but make sure the value does not contain any whitespace characters.
     */ 
    internal static string GetAndRemoveNoSpaceAttribute(IDictionary directives, 
        string key) {
 
        string val = Util.GetAndRemove(directives, key);

        if (val == null)
            return null; 

        return GetNoSpaceAttribute(key, val); 
    } 
#endif
 
    /*
     * Same as GetAndRemoveNonEmptyAttribute, but make sure the value does not
     * contain any whitespace characters.
     */ 
    internal static string GetAndRemoveNonEmptyNoSpaceAttribute(IDictionary directives,
        string key, bool required) { 
 
        string val = Util.GetAndRemoveNonEmptyAttribute(directives, key, required);
 
        if (val == null)
            return null;

        return GetNonEmptyNoSpaceAttribute(key, val); 
    }
 
    internal static string GetAndRemoveNonEmptyNoSpaceAttribute(IDictionary directives, 
        string key) {
        return GetAndRemoveNonEmptyNoSpaceAttribute(directives, key, false /*required*/); 
    }

    // Return the value, after checking that it's not empty and has no spaces
    internal static string GetNonEmptyNoSpaceAttribute(string name, string value) { 
        value = GetNonEmptyAttribute(name, value);
        return GetNoSpaceAttribute(name, value); 
    } 

    /* 
     * Same as GetAndRemoveNonEmptyNoSpaceAttribute, but make sure the value is a
     * valid language identifier
     */
    internal static string GetAndRemoveNonEmptyIdentifierAttribute(IDictionary directives, 
        string key, bool required) {
 
        string val = Util.GetAndRemoveNonEmptyNoSpaceAttribute(directives, key, required); 

        if (val == null) 
            return null;

        return GetNonEmptyIdentifierAttribute(key, val);
    } 

    // Return the value, after checking that it's a valid id 
    internal static string GetNonEmptyIdentifierAttribute(string name, string value) { 
        value = GetNonEmptyNoSpaceAttribute(name, value);
 
        if (!System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(value)) {
            throw new HttpException(
                SR.GetString(SR.Invalid_attribute_value, value, name));
        } 

        return value; 
    } 

    // Return the class and the namespace 
    internal static string GetNonEmptyFullClassNameAttribute(string name, string value,
        ref string ns) {

        value = GetNonEmptyNoSpaceAttribute(name, value); 

        // The value can be of the form NS1.NS2.MyClassName.  Split it into its parts. 
        string[] parts = value.Split('.'); 

        // Check that all the parts are valid identifiers 
        foreach (string part in parts) {
            if (!System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(part)) {
                throw new HttpException(
                    SR.GetString(SR.Invalid_attribute_value, value, name)); 
            }
        } 
 
        // If there is a namespace, return it
        if (parts.Length > 1) 
            ns = String.Join(".", parts, 0, parts.Length-1);

        // Return the class name (which is the last part)
        return parts[parts.Length-1]; 
    }
 
    internal static void CheckUnknownDirectiveAttributes(string directiveName, IDictionary directive) { 

        CheckUnknownDirectiveAttributes(directiveName, directive, SR.Attr_not_supported_in_directive); 
    }

    internal static void CheckUnknownDirectiveAttributes(string directiveName, IDictionary directive,
        string resourceKey) { 

        // If there are some attributes left, fail 
        if (directive.Count > 0) { 
            throw new HttpException(
                SR.GetString(resourceKey, 
                    Util.FirstDictionaryKey(directive), directiveName));
        }
    }
 
    /*
     * Get a string value from a dictionary, and convert it to bool.  Throw an 
     * exception if it's not a valid bool string. 
     * However, don't complain about null, which simply means the value is not
     * in the dictionary. 
     * The value is returned through a REF param (unchanged if null)
     * Return value: true if attrib exists, false otherwise
     */
    internal static bool GetAndRemoveBooleanAttribute(IDictionary directives, 
                                                      string key, ref bool val) {
        string s = Util.GetAndRemove(directives, key); 
 
        if (s == null)
            return false; 

        val = GetBooleanAttribute(key, s);
        return true;
    } 

    // Parse a string attribute into a bool 
    internal static bool GetBooleanAttribute(string name, string value) { 
        try {
            return bool.Parse(value); 
        }
        catch {
            throw new HttpException(
                SR.GetString(SR.Invalid_boolean_attribute, name)); 
        }
    } 
 
    /*
     * Get a string value from a dictionary, and convert it to integer.  Throw an 
     * exception if it's not a valid positive integer string.
     * However, don't complain about null, which simply means the value is not
     * in the dictionary.
     * The value is returned through a REF param (unchanged if null) 
     * Return value: true if attrib exists, false otherwise
     */ 
    internal static bool GetAndRemoveNonNegativeIntegerAttribute(IDictionary directives, 
                                                              string key, ref int val) {
        string s = Util.GetAndRemove(directives, key); 

        if (s == null)
            return false;
 
        val = GetNonNegativeIntegerAttribute(key, s);
 
        return true; 
    }
 
    // Parse a string attribute into a non-negative integer
    internal static int GetNonNegativeIntegerAttribute(string name, string value) {

        int ret; 

        try { 
            ret = int.Parse(value, CultureInfo.InvariantCulture); 
        }
        catch { 
            throw new HttpException(
                SR.GetString(SR.Invalid_nonnegative_integer_attribute, name));
        }
 
        // Make sure it's not negative
        if (ret < 0) { 
            throw new HttpException( 
                SR.GetString(SR.Invalid_nonnegative_integer_attribute, name));
        } 

        return ret;
    }
 
    internal static bool GetAndRemovePositiveIntegerAttribute(IDictionary directives,
                                                              string key, ref int val) { 
        string s = Util.GetAndRemove(directives, key); 

        if (s == null) 
            return false;

        try {
            val = int.Parse(s, CultureInfo.InvariantCulture); 
        }
        catch { 
            throw new HttpException( 
                SR.GetString(SR.Invalid_positive_integer_attribute, key));
        } 

        // Make sure it's positive
        if (val <= 0) {
            throw new HttpException( 
                SR.GetString(SR.Invalid_positive_integer_attribute, key));
        } 
 
        return true;
    } 

    internal static object GetAndRemoveEnumAttribute(IDictionary directives, Type enumType,
                                                   string key) {
        string s = Util.GetAndRemove(directives, key); 

        if (s == null) 
            return null; 

        return GetEnumAttribute(key, s, enumType); 
    }

    internal static object GetEnumAttribute(string name, string value, Type enumType) {
        return GetEnumAttribute(name, value, enumType, false); 
    }
 
    internal static object GetEnumAttribute(string name, string value, Type enumType, bool allowMultiple) { 
        object val;
 
        try {
            // Don't allow numbers to be specified (ASURT 71851)
            // Also, don't allow several values (e.g. "red,blue")
            if (Char.IsDigit(value[0]) || value[0] == '-' || ((!allowMultiple) && (value.IndexOf(',') >= 0))) 
                throw new FormatException(SR.GetString(SR.EnumAttributeInvalidString, value, name, enumType.FullName));
 
            val = Enum.Parse(enumType, value, true /*ignoreCase*/); 
        }
        catch { 
            string names = null;
            foreach (string n in Enum.GetNames(enumType)) {
                if (names == null)
                    names = n; 
                else
                    names += ", " + n; 
            } 
            throw new HttpException(
                SR.GetString(SR.Invalid_enum_attribute, name, names)); 
        }

        return val;
    } 

#if UNUSED 
    /* 
     * Return a string array from a Hashtable that only contains string values
     */ 
    internal static string[] StringArrayFromHashtable(Hashtable h)
    {
        if (h == null) return null;
        string[] ret = new string[h.Count]; 
        h.Values.CopyTo(ret, 0);
        return ret; 
    } 

    /* 
     * Return a ArrayList which contains all the strings from a string array
     */
    internal static ArrayList ArrayListFromStringArray(string[] arr)
    { 
        ArrayList al = new ArrayList();
        for (int i=0; i=0; i--) { 
            if (Char.IsWhiteSpace(s[i])) 
                return true;
        } 

        return false;
    }
 
    /*
     * Return the index of the first non whitespace char.  -1 if none found. 
     */ 
    internal static int FirstNonWhiteSpaceIndex(string s) {
        for (int i=0; i= 1);
 
        if (IsWhiteSpaceString(chunks[chunkCount-1])) {
            throw new HttpException(SR.GetString( 
                SR.Unsupported_filename, filename)); 
        }
 
        typeName = MakeValidTypeNameFromString(chunks[chunkCount-1]);

        // Turn all the relevant chunks into valid namespace chunks
        for (int i=0; i ValidCultureNames { 
        get {
            if (s_validCultureNames == null) { 
                Dictionary names = new Dictionary(StringComparer.OrdinalIgnoreCase); 
                CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
                foreach (CultureInfo culture in cultures) { 
                    names.Add(culture.Name, true);
                }
                s_validCultureNames = names;
            } 
            return s_validCultureNames;
        } 
    } 

    /* 
     * Return the culture name for a file (e.g. "fr" or "fr-fr").
     * If no culture applies, return null.
     */
    internal static string GetCultureName(string virtualPath) { 

        if (virtualPath == null) return null; 
 
        // By default, extract the culture name from the file name (e.g. "foo.fr-fr.resx")
 
        string fileNameNoExt = Path.GetFileNameWithoutExtension(virtualPath);

        // If virtualPath is not a file, ie. above statement returns null, simply return null;
        if (fileNameNoExt == null) 
            return null;
 
        // If there a dot left 
        int dotIndex = fileNameNoExt.LastIndexOf('.');
 
        if (dotIndex < 0) return null;

        string cultureName = fileNameNoExt.Substring(dotIndex+1);
 
        // If it doesn't look like a culture name (e.g. "fr" or "fr-fr"), return null
        if (!IsCultureName(cultureName)) 
            return null; 

        return cultureName; 
    }


    /* 
     * Returns true if the type string contains an assembly specification
     */ 
    internal static bool TypeNameContainsAssembly(string typeName) { 
        return CommaIndexInTypeName(typeName) > 0;
    } 

    /*
     * Returns the index of the comma separating the type from the assembly, or
     * -1 of there is no assembly 
     */
    internal static int CommaIndexInTypeName(string typeName) { 
 
        // Look for the last comma
        int commaIndex = typeName.LastIndexOf(','); 

        // If it doesn't have one, there is no assembly
        if (commaIndex < 0)
            return -1; 

        // It has a comma, we need to account for the generics syntax. 
        // E.g. it could be "SomeType[int,string] 

        // Check for a ] 
        int rightBracketIndex = typeName.LastIndexOf(']');

        // If it has one, and it's after the last comma, there is no assembly
        if (rightBracketIndex > commaIndex) 
            return -1;
 
        // The comma that we want is the first one after the last ']' 
        commaIndex = typeName.IndexOf(',', rightBracketIndex + 1);
 
        // There is an assembly
        return commaIndex;
    }
 
    /*
     * Return the full path (non shadow copied) to the assembly that 
     * the given type lives in. 
     */
    internal static string GetAssemblyPathFromType(Type t) { 
        return Util.FilePathFromFileUrl(t.Assembly.EscapedCodeBase);
    }

    /* 
     * Same as GetAssemblyPathFromType, but with path safety check
     */ 
    internal static string GetAssemblySafePathFromType(Type t) { 
        return HttpRuntime.GetSafePath(GetAssemblyPathFromType(t));
    } 

    internal static string GetAssemblyQualifiedTypeName(Type t) {
        if (t.Assembly.GlobalAssemblyCache)
            return t.AssemblyQualifiedName; 

        // For non-GAC types, t.AssemblyQualifiedName still returns a big ugly type string, 
        // so return a simpler one instead with just "typename, assemblyName". 
        return t.FullName + ", " + t.Assembly.GetName().Name;
    } 

    internal static string GetAssemblyShortName(Assembly a) {

        // Getting the short name is always safe, so Assert to get it (VSWhidbey 491895) 
        InternalSecurityPermissions.Unrestricted.Assert();
 
        return a.GetName().Name; 
    }
 
    /*
     * Check if the passed in type is for a late bound COM object.  This
     * is what we would get when calling Type.GetTypeFromProgID() on a progid
     * that has not been tlbimp'ed. 
     */
    internal static bool IsLateBoundComClassicType(Type t) { 
        // 
        return (String.Compare(t.FullName, "System.__ComObject", StringComparison.Ordinal) == 0);
    } 

    /*
     * Get the path to the (shadow copied) DLL behind an assembly
     */ 
    internal static string GetAssemblyCodeBase(Assembly assembly) {
 
        string location = assembly.Location; 
        if (String.IsNullOrEmpty(location))
            return null; 

        // Get the path to the assembly (from the cache if it got shadow copied)
        return location;
    } 

    /* 
     * Add the full path to the assembly to the string collection if it's not already there. 
     */
    internal static void AddAssemblyToStringCollection(Assembly assembly, StringCollection toList) { 

        // Get the full path to the assembly
        string assemblyPath = Util.GetAssemblyCodeBase(assembly);
        Debug.Assert(!String.IsNullOrEmpty(assemblyPath)); 

        // Unless it's already in the list, add it 
        if (!toList.Contains(assemblyPath)) { 
            toList.Add(assemblyPath);
        } 
    }

    /*
     * Add the full path to all the assemblies to the string collection if they're not already there. 
     */
    internal static void AddAssembliesToStringCollection(ICollection fromList, StringCollection toList) { 
 
        // Nothing to do if either is null
        if (fromList == null || toList == null) 
            return;

        foreach (Assembly assembly in fromList) {
            AddAssemblyToStringCollection(assembly, toList); 
        }
    } 
 
    /*
     * Return an AssemblySet which contains all the assemblies that 
     * are referenced by the input assembly
     */
    internal static AssemblySet GetReferencedAssemblies(Assembly a) {
 
        AssemblySet referencedAssemblies = new AssemblySet();
        AssemblyName[] refs = a.GetReferencedAssemblies(); 
 
        foreach (AssemblyName aname in refs) {
            Assembly referencedAssembly = Assembly.Load(aname); 

            // Ignore mscorlib
            if (referencedAssembly == typeof(string).Assembly)
                continue; 

            referencedAssemblies.Add(referencedAssembly); 
        } 

        return referencedAssemblies; 
    }

    /*
     * Return an assembly name from the name of an assembly dll. 
     * Basically, it strips the extension.
     */ 
    internal static string GetAssemblyNameFromFileName(string fileName) { 
        // Strip the .dll extension if any
        if (StringUtil.EqualsIgnoreCase(Path.GetExtension(fileName), ".dll")) 
            return fileName.Substring(0, fileName.Length-4);

        return fileName;
    } 

    /* 
     * Look for a type by name in a collection of assemblies.  If it exists in multiple assemblies, 
     * throw an error.
     */ 
    // Assert reflection in order to call assembly.GetType()
    [ReflectionPermission(SecurityAction.Assert, Flags=ReflectionPermissionFlag.MemberAccess)]
    internal static Type GetTypeFromAssemblies(ICollection assemblies, string typeName, bool ignoreCase) {
        if (assemblies == null) 
            return null;
 
        Type type = null; 

        foreach (Assembly assembly in assemblies) { 
            Type t = assembly.GetType(typeName, false /*throwOnError*/, ignoreCase);

            if (t == null)
                continue; 

            // If we had already found a different one, it's an ambiguous type reference 
            if (type != null && t != type) { 
                throw new HttpException(SR.GetString(
                    SR.Ambiguous_type, typeName, 
                    GetAssemblySafePathFromType(type), GetAssemblySafePathFromType(t)));
            }

            // Keep track of it 
            type = t;
        } 
 
        return type;
    } 

    internal static string GetCurrentAccountName() {
        try {
            return System.Security.Principal.WindowsIdentity.GetCurrent().Name; 
        }
        catch { 
            // WindowsIdentity.GetCurrent() can throw.  Return "?" when that happens 
            return "?";
        } 
    }

    internal static string QuoteJScriptString(string value) {
        return QuoteJScriptString(value, false); 
    }
 
    internal static string QuoteJScriptString(string value, bool forUrl) { 
        StringBuilder b = null;
 
        if (String.IsNullOrEmpty(value)) {
            return String.Empty;
        }
 
        int startIndex = 0;
        int count = 0; 
        for (int i=0; i 0) {
                        b.Append(value, startIndex, count); 
                    } 

                    b.Append("\\r"); 

                    startIndex = i + 1;
                    count = 0;
                    break; 
                case '\t':
                    if (b == null) { 
                        b = new StringBuilder(value.Length+5); 
                    }
 
                    if (count > 0) {
                        b.Append(value, startIndex, count);
                    }
 
                    b.Append("\\t");
 
                    startIndex = i + 1; 
                    count = 0;
                    break; 
                case '\"':
                    if (b == null) {
                        b = new StringBuilder(value.Length+5);
                    } 

                    if (count > 0) { 
                        b.Append(value, startIndex, count); 
                    }
 
                    b.Append("\\\"");

                    startIndex = i + 1;
                    count = 0; 
                    break;
                case '\'': 
                    if (b == null) { 
                        b = new StringBuilder(value.Length+5);
                    } 

                    if (count > 0) {
                        b.Append(value, startIndex, count);
                    } 

                    b.Append("\\\'"); 
 
                    startIndex = i + 1;
                    count = 0; 
                    break;
                case '\\':
                    if (b == null) {
                        b = new StringBuilder(value.Length+5); 
                    }
 
                    if (count > 0) { 
                        b.Append(value, startIndex, count);
                    } 

                    b.Append("\\\\");

                    startIndex = i + 1; 
                    count = 0;
                    break; 
                case '\n': 
                    if (b == null) {
                        b = new StringBuilder(value.Length+5); 
                    }

                    if (count > 0) {
                        b.Append(value, startIndex, count); 
                    }
 
                    b.Append("\\n"); 

                    startIndex = i + 1; 
                    count = 0;
                    break;
                case '%':
                    if (forUrl) { 
                        if (b == null) {
                            b = new StringBuilder(value.Length + 6); 
                        } 
                        if (count > 0) {
                            b.Append(value, startIndex, count); 
                        }
                        b.Append("%25");

                        startIndex = i + 1; 
                        count = 0;
                        break; 
                    } 
                    goto default;
                default: 
                    count++;
                    break;
            }
        } 

        if (b == null) { 
            return value; 
        }
 
        if (count > 0) {
            b.Append(value, startIndex, count);
        }
 
        return b.ToString();
    } 
 
    private static ArrayList GetSpecificCultures(string shortName) {
        CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures); 
        ArrayList list = new ArrayList();

        for (int i=0; i 0 && value[length - 1] != ';') { 
                return (value + ";");
            } 
        }
        return value;
    }
 
    internal static string MergeScript(string firstScript, string secondScript) {
        Debug.Assert(!String.IsNullOrEmpty(secondScript)); 
 
        if (!String.IsNullOrEmpty(firstScript)) {
            // 
            return firstScript + secondScript;
        }
        else {
            if (secondScript.TrimStart().StartsWith(ClientScriptManager.JscriptPrefix, StringComparison.Ordinal)) { 
                return secondScript;
            } 
            return ClientScriptManager.JscriptPrefix + secondScript; 
        }
    } 

    internal static bool IsUserAllowedToPath(HttpContext context, VirtualPath virtualPath) {
        // Check FileAuthorizationModule if it's a windows identity
        if (FileAuthorizationModule.IsWindowsIdentity(context)) { 
            if (HttpRuntime.IsFullTrust) {
                if (!IsUserAllowedToPathWithNoAssert(context, virtualPath)) { 
                    return false; 
                }
            } 
            else {
                if (!IsUserAllowedToPathWithAssert(context, virtualPath)) {
                    return false;
                } 
            }
        } 
 
        // Always check UrlAuthorizationModule
        return UrlAuthorizationModule.IsUserAllowedToPath(context, virtualPath); 
    }

    // Need to assert here in order to MapPath in the FileAuthorizationModule.
    [FileIOPermission(SecurityAction.Assert, Unrestricted = true)] 
    private static bool IsUserAllowedToPathWithAssert(HttpContext context, VirtualPath virtualPath) {
        return IsUserAllowedToPathWithNoAssert(context, virtualPath); 
    } 

    private static bool IsUserAllowedToPathWithNoAssert(HttpContext context, VirtualPath virtualPath) { 
        return FileAuthorizationModule.IsUserAllowedToPath(context, virtualPath);
    }

#if DBG 
    internal static void DumpDictionary(string tag, IDictionary d) {
        if (d == null) return; 
 
        Debug.Trace(tag, "Dumping IDictionary with " + d.Count + " entries:");
 
        for (IDictionaryEnumerator en = (IDictionaryEnumerator)d.GetEnumerator(); en.MoveNext();) {
            if (en.Value == null)
                Debug.Trace(tag, "Key='" + en.Key.ToString() + "' value=null");
            else 
                Debug.Trace(tag, "Key='" + en.Key.ToString() + "' value='" + en.Value.ToString() + "'");
        } 
    } 

    internal static void DumpArrayList(string tag, ArrayList al) { 
        if (al == null) return;

        Debug.Trace(tag, "Dumping ArrayList with " + al.Count + " entries:");
 
        foreach (object o in al) {
            if (o == null) 
                Debug.Trace(tag, "value=null"); 
            else
                Debug.Trace(tag, "value='" + o.ToString() + "'"); 
        }
    }

    internal static void DumpString(string tag, string s) { 
        Debug.Trace(tag, "Dumping string  '" + s + "':");
 
        StringBuilder sb = new StringBuilder(); 
        for (int i = 0; i < s.Length; ++i) {
            sb.Append(((int)s[i]).ToString("x", CultureInfo.InvariantCulture)); 
            sb.Append(" ");
        }
        Debug.Trace(tag, sb.ToString());
    } 

#endif // DBG 
 
}
 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 * Implements various utility functions used by the template code 
 *
 * Copyright (c) 1998 Microsoft Corporation 
 */

namespace System.Web.UI {
 
using System;
using System.Collections; 
using System.Collections.Generic; 
using System.Collections.Specialized;
using System.ComponentModel; 
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO; 
using System.Reflection;
using System.Runtime.Serialization.Formatters; 
using System.Text; 
using System.Text.RegularExpressions;
using System.Web.Hosting; 
using System.Web.Configuration;
using System.Web.Compilation;
using System.Web.Security;
using System.Web.UI.WebControls; 
using System.Web.Util;
using System.Security; 
using System.Security.Permissions; 
using System.Web.Management;
using Microsoft.Win32; 
using Debug=System.Web.Util.Debug;

internal static class Util {
    private static Dictionary s_validCultureNames = null; 

    [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)] 
    internal static string SerializeWithAssert(IStateFormatter formatter, object stateGraph) { 
        return formatter.Serialize(stateGraph);
    } 

    [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)]
    internal static object DeserializeWithAssert(IStateFormatter formatter, string serializedState) {
        return formatter.Deserialize(serializedState); 
    }
 
    internal static bool CanConvertToFrom(TypeConverter converter, Type type) { 
        return (converter != null && converter.CanConvertTo(type) &&
                converter.CanConvertFrom(type) && !(converter is ReferenceConverter)); 
    }

    internal static void CopyBaseAttributesToInnerControl(WebControl control, WebControl child) {
        short oldTab = control.TabIndex; 
        string oldAccess = control.AccessKey;
        try { 
            control.AccessKey = String.Empty; 
            control.TabIndex = 0;
            child.CopyBaseAttributes(control); 
        }
        finally {
            control.TabIndex = oldTab;
            control.AccessKey = oldAccess; 
        }
    } 
 
    internal static long GetRecompilationHash(PagesSection ps)
    { 
        HashCodeCombiner recompilationHash = new HashCodeCombiner();
        NamespaceCollection namespaces;
        TagPrefixCollection controls;
        TagMapCollection tagMapping; 

        // Combine items from Pages section 
        recompilationHash.AddObject(ps.Buffer); 
        recompilationHash.AddObject(ps.EnableViewState);
        recompilationHash.AddObject(ps.EnableViewStateMac); 
        recompilationHash.AddObject(ps.EnableEventValidation);
        recompilationHash.AddObject(ps.SmartNavigation);
        recompilationHash.AddObject(ps.ValidateRequest);
        recompilationHash.AddObject(ps.AutoEventWireup); 
        if (ps.PageBaseTypeInternal != null) {
            recompilationHash.AddObject(ps.PageBaseTypeInternal.FullName); 
        } 
        if (ps.UserControlBaseTypeInternal != null) {
            recompilationHash.AddObject(ps.UserControlBaseTypeInternal.FullName); 
        }
        if (ps.PageParserFilterTypeInternal != null) {
            recompilationHash.AddObject(ps.PageParserFilterTypeInternal.FullName);
        } 
        recompilationHash.AddObject(ps.MasterPageFile);
        recompilationHash.AddObject(ps.Theme); 
        recompilationHash.AddObject(ps.StyleSheetTheme); 
        recompilationHash.AddObject(ps.EnableSessionState);
        recompilationHash.AddObject(ps.CompilationMode); 
        recompilationHash.AddObject(ps.MaxPageStateFieldLength);
        recompilationHash.AddObject(ps.ViewStateEncryptionMode);
        recompilationHash.AddObject(ps.MaintainScrollPositionOnPostBack);
 
        // Combine items from Namespaces collection
        namespaces = ps.Namespaces; 
 
        recompilationHash.AddObject(namespaces.AutoImportVBNamespace);
        if (namespaces.Count == 0) { 
            recompilationHash.AddObject("__clearnamespaces");
        }
        else {
            foreach (NamespaceInfo ni in namespaces) { 
                recompilationHash.AddObject(ni.Namespace);
            } 
        } 

        // Combine items from the Controls collection 
        controls = ps.Controls;

        if (controls.Count == 0) {
            recompilationHash.AddObject("__clearcontrols"); 
        }
        else { 
            foreach (TagPrefixInfo tpi in controls) { 
                recompilationHash.AddObject(tpi.TagPrefix);
 
                if (tpi.TagName != null && tpi.TagName.Length != 0) {
                    recompilationHash.AddObject(tpi.TagName);
                    recompilationHash.AddObject(tpi.Source);
                } 
                else {
                    recompilationHash.AddObject(tpi.Namespace); 
                    recompilationHash.AddObject(tpi.Assembly); 
                }
            } 
        }

        // Combine items from the TagMapping Collection
        tagMapping = ps.TagMapping; 

        if (tagMapping.Count == 0) { 
            recompilationHash.AddObject("__cleartagmapping"); 
        }
        else { 
            foreach (TagMapInfo tmi in tagMapping) {
                recompilationHash.AddObject(tmi.TagType);
                recompilationHash.AddObject(tmi.MappedTagType);
            } 
        }
 
        return recompilationHash.CombinedHash; 
    }
 

#if UNUSED
    /*
     *  Return a String which holds the contents of a TextReader 
     */
    public static String StringFromReader(TextReader input) { 
        char[] buffer = new char[4096]; 
        int bufferpos = 0;
        int delta; 

        for (;;) {
            delta = input.Read(buffer, bufferpos, buffer.Length - bufferpos);
 
            if (delta == 0)
                break; 
 
            bufferpos += delta;
 
            if (bufferpos == buffer.Length) {
                char[] newbuf = new char[buffer.Length * 2];
                System.Array.Copy(buffer, 0, newbuf, 0, buffer.Length);
                buffer = newbuf; 
            }
        } 
 
        return new String(buffer, 0, bufferpos);
    } 
#endif

    internal static Encoding GetEncodingFromConfigPath(VirtualPath configPath) {
 
        Debug.Assert(configPath != null, "configPath != null");
 
        // Check if a file encoding is specified in the config 
        Encoding fileEncoding = null;
        GlobalizationSection globConfig = RuntimeConfig.GetConfig(configPath).Globalization; 
        fileEncoding = globConfig.FileEncoding;

        // If not, use the default encoding
        if (fileEncoding == null) 
            fileEncoding = Encoding.Default;
 
        return fileEncoding; 
    }
 
    /*
     * Return a reader which holds the contents of a file.  If a configPath is passed
     * in, try to get an encoding for it
     */ 
    internal /*public*/ static StreamReader ReaderFromFile(string filename, VirtualPath configPath) {
 
        StreamReader reader; 

        // Check if a file encoding is specified in the config 
        Encoding fileEncoding = Encoding.Default;
        if (configPath != null) fileEncoding = GetEncodingFromConfigPath(configPath);

        try { 
            // Create a reader on the file, using the encoding
            // Throws an exception if the file can't be opened. 
            reader = new StreamReader(filename, fileEncoding, 
                true /*detectEncodingFromByteOrderMarks*/, 4096);
        } 
        catch (UnauthorizedAccessException) {
            // AccessException might mean two very different things: it could be a real
            // access problem, or it could be that it's actually a directory.
 
            // It's a directory: give a specific error.
            if (FileUtil.DirectoryExists(filename)) { 
                throw new HttpException( 
                    SR.GetString(SR.Unexpected_Directory, HttpRuntime.GetSafePath(filename)));
            } 

            // It's a real access problem, so just rethrow it
            throw;
        } 

        return reader; 
    } 

    /* 
     * Attempt to delete a file, but don't throw if it can't be done
     */
    internal static void DeleteFileNoException(string path) {
        Debug.Assert(File.Exists(path)); 
        try {
            File.Delete(path); 
        } 
        catch { } // Ignore all exceptions
    } 

    internal static void DeleteFileIfExistsNoException(string path) {
        if (File.Exists(path))
            DeleteFileNoException(path); 
    }
 
    /* 
     * Return true if the directory exists and is not empty.
     */ 
    internal static bool IsNonEmptyDirectory(string dir) {

        // Does it exist
        if (!Directory.Exists(dir)) 
            return false;
 
        // It exists, but maybe it's empty 
        try {
            string[] entries = Directory.GetFileSystemEntries(dir); 
            return entries.Length > 0;
        }
        catch {
            // If it throws, assume it's non-empty 
            return true;
        } 
    } 

    /* 
     * Return true if string is a valid simple file name (with no path or wild cards)
     */
    private static char[] invalidFileNameChars = new char[] { '/', '\\', '?', '*', ':' } ;
    internal static bool IsValidFileName(string fileName) { 

        // Check for the special names "." and ".." 
        if (fileName == "." || fileName == "..") 
            return false;
 
        // Check for invalid characters
        if (fileName.IndexOfAny(invalidFileNameChars) >= 0)
            return false;
 
        return true;
    } 
 
    /*
     * Replace all invalid chars in a filename by underscores. 
     */
    internal static string MakeValidFileName(string fileName) {

        // If it's already valid, nothing to do 
        if (IsValidFileName(fileName))
            return fileName; 
 
        // Replace all the invalid chars by '_'
        for (int i = 0; i < invalidFileNameChars.Length; ++i)  { 
            fileName = fileName.Replace(invalidFileNameChars[i], '_');
        }

        // Shoud always be valid now 
        Debug.Assert(IsValidFileName(fileName));
 
        return fileName; 
    }
 
    /*
     * Return true if the current user has write access to the directory
     */
    internal static bool HasWriteAccessToDirectory(string dir) { 

        // If it doesn't even exist (or we can't determine that it does), return false 
        if (!Directory.Exists(dir)) 
            return false;
 
        // Get the path to a dummy file in that directory
        string dummyFile = Path.Combine(dir, "~AspAccessCheck_" +
            HostingEnvironment.AppDomainUniqueInteger.ToString(
                "x", CultureInfo.InvariantCulture) + ".tmp"); 
        FileStream fs = null;
 
        bool success = false; 
        try {
            // Attempt to create the file 
            fs = new FileStream(dummyFile, FileMode.Create);
        }
        catch {
        } 
        finally {
            if (fs != null) { 
                // If successfully created, close and delete it 
                fs.Close();
                File.Delete(dummyFile); 
                success = true;
            }
        }
 
        return success;
 
// 
#if UNUSED
        FileSecurityDescriptorWrapper oSecDesc = new FileSecurityDescriptorWrapper(dir); 
        bool fAllowed = oSecDesc.IsAccessAllowed(WindowsIdentity.GetCurrent().Token, 0x3 /*R/W*/);
        return fAllowed;
#endif
    } 

    internal static VirtualPath GetScriptLocation() { 
        // prepare script include 
        string location = (string) RuntimeConfig.GetRootWebConfig().WebControls["clientScriptsLocation"];
 
        // If there is a formatter, as there will be for the default machine.config, insert the assembly name and version.
        if (location.IndexOf("{0}", StringComparison.Ordinal) >= 0) {
            string assembly = "system_web";
 
            // QFE number is not included in client path
            string version = VersionInfo.EngineVersion.Substring(0, VersionInfo.EngineVersion.LastIndexOf('.')).Replace('.', '_'); 
            location = String.Format(CultureInfo.InvariantCulture, location, assembly, version); 
        }
 
        return VirtualPath.Create(location);
    }

    /* 
     * Return a reader which holds the contents of a file.  If a configPath is passed
     * in, try to get a encoding for it 
     */ 
    internal /*public*/ static StreamReader ReaderFromStream(Stream stream, VirtualPath configPath) {
 
        // Check if a file encoding is specified in the config
        Encoding fileEncoding = GetEncodingFromConfigPath(configPath);

        // Create a reader on the file, using the encoding 
        return new StreamReader(stream, fileEncoding,
            true /*detectEncodingFromByteOrderMarks*/, 4096); 
    } 

    /* 
     * Return a String which holds the contents of a file
     */
    internal /*public*/ static String StringFromVirtualPath(VirtualPath virtualPath) {
 
        using (Stream stream = virtualPath.OpenFile()) {
            // Create a reader on the file, and read the whole thing 
            TextReader reader = Util.ReaderFromStream(stream, virtualPath); 
            return reader.ReadToEnd();
        } 
    }

    /*
     * Return a String which holds the contents of a file 
     */
    internal /*public*/ static String StringFromFile(string path) { 
        Encoding encoding = Encoding.Default; 
        return StringFromFile(path, ref encoding);
    } 

    /*
     * Return a String which holds the contents of a file with specific encoding.
     */ 
    internal /*public*/ static String StringFromFile(string path, ref Encoding encoding) {
 
        // Create a reader on the file. 
        // Generates an exception if the file can't be opened.
        StreamReader reader = new StreamReader(path, encoding, true /*detectEncodingFromByteOrderMarks*/); 

        try {
            string content = reader.ReadToEnd();
            encoding = reader.CurrentEncoding; 

            return content; 
        } 
        finally {
            // Make sure we always close the stream 
            if (reader != null)
                reader.Close();
        }
    } 

    /* 
     * Return a String which holds the contents of a file, or null if the file 
     * doesn't exist.
     */ 
    internal /*public*/ static String StringFromFileIfExists(string path) {

        if (!File.Exists(path)) return null;
 
        return StringFromFile(path);
    } 
 
    /*
     * If the file doesn't exist, do nothing.  If it does try to delete it if possible. 
     * If that fails, rename it with by appending a .delete extension to it
     */
    internal static void RemoveOrRenameFile(string filename) {
        FileInfo fi = new FileInfo(filename); 
        RemoveOrRenameFile(fi);
    } 
 
    /*
     * If the file doesn't exist, do nothing.  If it does try to delete it if possible. 
     * If that fails, rename it with by appending a .delete extension to it
     */
    internal static bool RemoveOrRenameFile(FileInfo f) {
        try { 
            // First, just try to delete the file
            f.Delete(); 
 
            // It was successfully deleted, so return true
            return true; 
        }
        catch {

            try { 
                // If the delete failed, rename it to ".delete"
                // Don't do that if it already has the delete extension 
                if (f.Extension != ".delete") { 

                    // include a unique token as part of the new name, to avoid 
                    // conflicts with previous renames (VSWhidbey 79996)
                    string uniqueToken = DateTime.Now.Ticks.GetHashCode().ToString("x", CultureInfo.InvariantCulture);
                    string newName = f.FullName + "." + uniqueToken + ".delete";
                    f.MoveTo(newName); 
                }
            } 
            catch { 
                // Ignore all exceptions
            } 
        }

        // Return false because we couldn't delete it, and had to rename it
        return false; 
    }
 
    /* 
     * Clears a file's readonly attribute if it has one
     */ 
    internal static void ClearReadOnlyAttribute(string path) {

        FileAttributes attribs = File.GetAttributes(path);
        if ((attribs & FileAttributes.ReadOnly) != 0) { 
            File.SetAttributes(path, attribs & ~FileAttributes.ReadOnly);
        } 
    } 

    internal static void CheckVirtualFileExists(VirtualPath virtualPath) { 
        if (!virtualPath.FileExists()) {
            throw new HttpException(
                HttpStatus.NotFound,
                SR.GetString(SR.FileName_does_not_exist, 
                    virtualPath.VirtualPathString));
        } 
    } 

    internal static bool VirtualFileExistsWithAssert(VirtualPath virtualPath) { 
        string physicalDir = virtualPath.MapPathInternal();

        if (physicalDir != null) {
            (InternalSecurityPermissions.PathDiscovery(physicalDir)).Assert(); 
        }
 
        return virtualPath.FileExists(); 
    }
 
    internal static void CheckThemeAttribute(string themeName) {
        if (themeName.Length > 0) {
            if (!FileUtil.IsValidDirectoryName(themeName)) {
                throw new HttpException(SR.GetString(SR.Page_theme_invalid_name, themeName)); 
            }
 
            if (!ThemeExists(themeName)) { 
                throw new HttpException(SR.GetString(SR.Page_theme_not_found, themeName));
            } 
        }
    }

    internal static bool ThemeExists(string themeName) { 
        VirtualPath virtualDir = ThemeDirectoryCompiler.GetAppThemeVirtualDir(themeName);
        if (!VirtualDirectoryExistsWithAssert(virtualDir)) { 
            virtualDir = ThemeDirectoryCompiler.GetGlobalThemeVirtualDir(themeName); 
            if (!VirtualDirectoryExistsWithAssert(virtualDir)) {
                return false; 
            }
        }

        return true; 
    }
 
    private static bool VirtualDirectoryExistsWithAssert(VirtualPath virtualDir) { 
        try {
            String physicalDir = virtualDir.MapPathInternal(); 
            if (physicalDir != null) {
                new FileIOPermission(FileIOPermissionAccess.Read, physicalDir).Assert();
            }
 
            return virtualDir.DirectoryExists();
        } 
        catch { 
            return false;
        } 
    }

    internal static void CheckAssignableType(Type baseType, Type type) {
        if (!baseType.IsAssignableFrom(type)) { 
            throw new HttpException(
                SR.GetString(SR.Type_doesnt_inherit_from_type, 
                    type.FullName, baseType.FullName)); 
        }
    } 

    internal /*public*/ static int LineCount(string text, int offset, int newoffset) {

        Debug.Assert(offset <= newoffset); 

        int linecount = 0; 
 
        while (offset < newoffset) {
            if (text[offset] == '\r' || (text[offset] == '\n' && (offset == 0 || text[offset - 1] != '\r'))) 
                linecount++;
            offset++;
        }
 
        return linecount;
    } 
 
    /*
     * Calls Invoke on a MethodInfo.  If an exception happens during the 
     * method call, catch it and throw it back.
     */
    internal static object InvokeMethod(
                                       MethodInfo methodInfo, 
                                       object obj,
                                       object[] parameters) { 
        try { 
            return methodInfo.Invoke(obj, parameters);
        } 
        catch (TargetInvocationException e) {
            throw e.InnerException;
        }
    } 

    /* 
     * If the passed in Type has a non-private field with the passed in name, 
     * return the field's Type.
     */ 
    internal static Type GetNonPrivateFieldType(Type classType, string fieldName) {
        FieldInfo fieldInfo = classType.GetField(fieldName,
            BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
 
        if (fieldInfo == null || fieldInfo.IsPrivate)
            return null; 
 
        return fieldInfo.FieldType;
    } 

    /*
     * If the passed in Type has a non-private property with the passed in name,
     * return the property's Type. 
     */
    internal static Type GetNonPrivatePropertyType(Type classType, string propName) { 
        PropertyInfo propInfo = null; 

        BindingFlags flags = BindingFlags.Public | BindingFlags.Instance 
            | BindingFlags.IgnoreCase | BindingFlags.NonPublic;

        try {
            propInfo = classType.GetProperty(propName, flags); 
        }
        catch (AmbiguousMatchException) { 
 
            // We could get an AmbiguousMatchException if the property exists on two
            // different ancestor classes (VSWhidbey 216957).  When that happens, attempt 
            // a lookup on the Type itself, ignoring its ancestors.

            flags |= BindingFlags.DeclaredOnly;
            propInfo = classType.GetProperty(propName, flags); 
        }
 
        if (propInfo == null) 
            return null;
 
        // If it doesn't have a setter, ot if it's private, fail
        MethodInfo methodInfo = propInfo.GetSetMethod(true /*nonPublic*/);
        if (methodInfo == null || methodInfo.IsPrivate)
            return null; 

        return propInfo.PropertyType; 
    } 

    /* 
     * Return the first key of the dictionary as a string.  Throws if it's
     * empty or if the key is not a string.
     */
    private static string FirstDictionaryKey(IDictionary dict) { 
        IDictionaryEnumerator e = dict.GetEnumerator();
        e.MoveNext(); 
        return (string)e.Key; 
    }
 
    /*
     * Get a value from a dictionary, and remove it from the dictionary if
     * it exists.
     */ 
    private static string GetAndRemove(IDictionary dict, string key) {
        string val = (string) dict[key]; 
        if (val != null) { 
            dict.Remove(key);
            val = val.Trim(); 
        }
        return val;
    }
 
    /*
     * Get a value from a dictionary, and remove it from the dictionary if 
     * it exists.  Throw an exception if the value is a whitespace string. 
     * However, don't complain about null, which simply means the value is not
     * in the dictionary. 
     */
    internal static string GetAndRemoveNonEmptyAttribute(IDictionary directives, string key, bool required) {
        string val = Util.GetAndRemove(directives, key);
 
        if (val == null) {
            if (required) 
                throw new HttpException(SR.GetString(SR.Missing_attr, key)); 

            return null; 
        }

        return GetNonEmptyAttribute(key, val);
    } 

    // Return the value, after checking that it's not empty 
    internal static string GetNonEmptyAttribute(string name, string value) { 

        value = value.Trim(); 

        if (value.Length == 0) {
            throw new HttpException(
                SR.GetString(SR.Empty_attribute, name)); 
        }
 
        return value; 
    }
 
    // Return the value, after checking that it doesn't contain spaces
    internal static string GetNoSpaceAttribute(string name, string value) {
        if (Util.ContainsWhiteSpace(value)) {
            throw new HttpException( 
                SR.GetString(SR.Space_attribute, name));
        } 
 
        return value;
    } 

    internal static string GetAndRemoveNonEmptyAttribute(IDictionary directives, string key) {
        return GetAndRemoveNonEmptyAttribute(directives, key, false /*required*/);
    } 

    internal static VirtualPath GetAndRemoveVirtualPathAttribute(IDictionary directives, string key) { 
        return GetAndRemoveVirtualPathAttribute(directives, key, false /*required*/); 
    }
 
    internal static VirtualPath GetAndRemoveVirtualPathAttribute(IDictionary directives, string key, bool required) {

        string val = GetAndRemoveNonEmptyAttribute(directives, key, required);
        if (val == null) 
            return null;
 
        return VirtualPath.Create(val); 
    }
 
    /*
     * Parse a DeviceName:AttribName string into its components
     */
    internal const char DeviceFilterSeparator = ':'; 
    internal const string XmlnsAttribute = "xmlns:";
    public static string ParsePropertyDeviceFilter(string input, out string propName) { 
        string deviceName = String.Empty; 

        // If the string has no device filter, the whole string is the property name 
        if (input.IndexOf(DeviceFilterSeparator) < 0) {
            propName = input;
        }
        // Don't treat xmlns as filters, this needs to be treated differently. 
        // VSWhidbey 495125
        else if (StringUtil.StringStartsWithIgnoreCase(input, XmlnsAttribute)) { 
            propName = input; 
        }
        else { 
            // There is a filter: parse it out
            string[] tmp = input.Split(DeviceFilterSeparator);

            if (tmp.Length > 2) { 
                throw new HttpException(
                    SR.GetString(SR.Too_many_filters, input)); 
            } 

            deviceName = tmp[0]; 
            propName = tmp[1];
        }

        return deviceName; 
    }
 
    ///  
    /// Combines the filter and name
    ///  
    public static string CreateFilteredName(string deviceName, string name) {
        if (deviceName.Length > 0) {
            return deviceName + DeviceFilterSeparator + name;
        } 
        return name;
    } 
 
    internal static string GetAndRemoveRequiredAttribute(IDictionary directives, string key) {
        return GetAndRemoveNonEmptyAttribute(directives, key, true /*required*/); 
    }

#if UNUSED
    /* 
     * Same as GetAndRemove, but make sure the value does not contain any whitespace characters.
     */ 
    internal static string GetAndRemoveNoSpaceAttribute(IDictionary directives, 
        string key) {
 
        string val = Util.GetAndRemove(directives, key);

        if (val == null)
            return null; 

        return GetNoSpaceAttribute(key, val); 
    } 
#endif
 
    /*
     * Same as GetAndRemoveNonEmptyAttribute, but make sure the value does not
     * contain any whitespace characters.
     */ 
    internal static string GetAndRemoveNonEmptyNoSpaceAttribute(IDictionary directives,
        string key, bool required) { 
 
        string val = Util.GetAndRemoveNonEmptyAttribute(directives, key, required);
 
        if (val == null)
            return null;

        return GetNonEmptyNoSpaceAttribute(key, val); 
    }
 
    internal static string GetAndRemoveNonEmptyNoSpaceAttribute(IDictionary directives, 
        string key) {
        return GetAndRemoveNonEmptyNoSpaceAttribute(directives, key, false /*required*/); 
    }

    // Return the value, after checking that it's not empty and has no spaces
    internal static string GetNonEmptyNoSpaceAttribute(string name, string value) { 
        value = GetNonEmptyAttribute(name, value);
        return GetNoSpaceAttribute(name, value); 
    } 

    /* 
     * Same as GetAndRemoveNonEmptyNoSpaceAttribute, but make sure the value is a
     * valid language identifier
     */
    internal static string GetAndRemoveNonEmptyIdentifierAttribute(IDictionary directives, 
        string key, bool required) {
 
        string val = Util.GetAndRemoveNonEmptyNoSpaceAttribute(directives, key, required); 

        if (val == null) 
            return null;

        return GetNonEmptyIdentifierAttribute(key, val);
    } 

    // Return the value, after checking that it's a valid id 
    internal static string GetNonEmptyIdentifierAttribute(string name, string value) { 
        value = GetNonEmptyNoSpaceAttribute(name, value);
 
        if (!System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(value)) {
            throw new HttpException(
                SR.GetString(SR.Invalid_attribute_value, value, name));
        } 

        return value; 
    } 

    // Return the class and the namespace 
    internal static string GetNonEmptyFullClassNameAttribute(string name, string value,
        ref string ns) {

        value = GetNonEmptyNoSpaceAttribute(name, value); 

        // The value can be of the form NS1.NS2.MyClassName.  Split it into its parts. 
        string[] parts = value.Split('.'); 

        // Check that all the parts are valid identifiers 
        foreach (string part in parts) {
            if (!System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(part)) {
                throw new HttpException(
                    SR.GetString(SR.Invalid_attribute_value, value, name)); 
            }
        } 
 
        // If there is a namespace, return it
        if (parts.Length > 1) 
            ns = String.Join(".", parts, 0, parts.Length-1);

        // Return the class name (which is the last part)
        return parts[parts.Length-1]; 
    }
 
    internal static void CheckUnknownDirectiveAttributes(string directiveName, IDictionary directive) { 

        CheckUnknownDirectiveAttributes(directiveName, directive, SR.Attr_not_supported_in_directive); 
    }

    internal static void CheckUnknownDirectiveAttributes(string directiveName, IDictionary directive,
        string resourceKey) { 

        // If there are some attributes left, fail 
        if (directive.Count > 0) { 
            throw new HttpException(
                SR.GetString(resourceKey, 
                    Util.FirstDictionaryKey(directive), directiveName));
        }
    }
 
    /*
     * Get a string value from a dictionary, and convert it to bool.  Throw an 
     * exception if it's not a valid bool string. 
     * However, don't complain about null, which simply means the value is not
     * in the dictionary. 
     * The value is returned through a REF param (unchanged if null)
     * Return value: true if attrib exists, false otherwise
     */
    internal static bool GetAndRemoveBooleanAttribute(IDictionary directives, 
                                                      string key, ref bool val) {
        string s = Util.GetAndRemove(directives, key); 
 
        if (s == null)
            return false; 

        val = GetBooleanAttribute(key, s);
        return true;
    } 

    // Parse a string attribute into a bool 
    internal static bool GetBooleanAttribute(string name, string value) { 
        try {
            return bool.Parse(value); 
        }
        catch {
            throw new HttpException(
                SR.GetString(SR.Invalid_boolean_attribute, name)); 
        }
    } 
 
    /*
     * Get a string value from a dictionary, and convert it to integer.  Throw an 
     * exception if it's not a valid positive integer string.
     * However, don't complain about null, which simply means the value is not
     * in the dictionary.
     * The value is returned through a REF param (unchanged if null) 
     * Return value: true if attrib exists, false otherwise
     */ 
    internal static bool GetAndRemoveNonNegativeIntegerAttribute(IDictionary directives, 
                                                              string key, ref int val) {
        string s = Util.GetAndRemove(directives, key); 

        if (s == null)
            return false;
 
        val = GetNonNegativeIntegerAttribute(key, s);
 
        return true; 
    }
 
    // Parse a string attribute into a non-negative integer
    internal static int GetNonNegativeIntegerAttribute(string name, string value) {

        int ret; 

        try { 
            ret = int.Parse(value, CultureInfo.InvariantCulture); 
        }
        catch { 
            throw new HttpException(
                SR.GetString(SR.Invalid_nonnegative_integer_attribute, name));
        }
 
        // Make sure it's not negative
        if (ret < 0) { 
            throw new HttpException( 
                SR.GetString(SR.Invalid_nonnegative_integer_attribute, name));
        } 

        return ret;
    }
 
    internal static bool GetAndRemovePositiveIntegerAttribute(IDictionary directives,
                                                              string key, ref int val) { 
        string s = Util.GetAndRemove(directives, key); 

        if (s == null) 
            return false;

        try {
            val = int.Parse(s, CultureInfo.InvariantCulture); 
        }
        catch { 
            throw new HttpException( 
                SR.GetString(SR.Invalid_positive_integer_attribute, key));
        } 

        // Make sure it's positive
        if (val <= 0) {
            throw new HttpException( 
                SR.GetString(SR.Invalid_positive_integer_attribute, key));
        } 
 
        return true;
    } 

    internal static object GetAndRemoveEnumAttribute(IDictionary directives, Type enumType,
                                                   string key) {
        string s = Util.GetAndRemove(directives, key); 

        if (s == null) 
            return null; 

        return GetEnumAttribute(key, s, enumType); 
    }

    internal static object GetEnumAttribute(string name, string value, Type enumType) {
        return GetEnumAttribute(name, value, enumType, false); 
    }
 
    internal static object GetEnumAttribute(string name, string value, Type enumType, bool allowMultiple) { 
        object val;
 
        try {
            // Don't allow numbers to be specified (ASURT 71851)
            // Also, don't allow several values (e.g. "red,blue")
            if (Char.IsDigit(value[0]) || value[0] == '-' || ((!allowMultiple) && (value.IndexOf(',') >= 0))) 
                throw new FormatException(SR.GetString(SR.EnumAttributeInvalidString, value, name, enumType.FullName));
 
            val = Enum.Parse(enumType, value, true /*ignoreCase*/); 
        }
        catch { 
            string names = null;
            foreach (string n in Enum.GetNames(enumType)) {
                if (names == null)
                    names = n; 
                else
                    names += ", " + n; 
            } 
            throw new HttpException(
                SR.GetString(SR.Invalid_enum_attribute, name, names)); 
        }

        return val;
    } 

#if UNUSED 
    /* 
     * Return a string array from a Hashtable that only contains string values
     */ 
    internal static string[] StringArrayFromHashtable(Hashtable h)
    {
        if (h == null) return null;
        string[] ret = new string[h.Count]; 
        h.Values.CopyTo(ret, 0);
        return ret; 
    } 

    /* 
     * Return a ArrayList which contains all the strings from a string array
     */
    internal static ArrayList ArrayListFromStringArray(string[] arr)
    { 
        ArrayList al = new ArrayList();
        for (int i=0; i=0; i--) { 
            if (Char.IsWhiteSpace(s[i])) 
                return true;
        } 

        return false;
    }
 
    /*
     * Return the index of the first non whitespace char.  -1 if none found. 
     */ 
    internal static int FirstNonWhiteSpaceIndex(string s) {
        for (int i=0; i= 1);
 
        if (IsWhiteSpaceString(chunks[chunkCount-1])) {
            throw new HttpException(SR.GetString( 
                SR.Unsupported_filename, filename)); 
        }
 
        typeName = MakeValidTypeNameFromString(chunks[chunkCount-1]);

        // Turn all the relevant chunks into valid namespace chunks
        for (int i=0; i ValidCultureNames { 
        get {
            if (s_validCultureNames == null) { 
                Dictionary names = new Dictionary(StringComparer.OrdinalIgnoreCase); 
                CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
                foreach (CultureInfo culture in cultures) { 
                    names.Add(culture.Name, true);
                }
                s_validCultureNames = names;
            } 
            return s_validCultureNames;
        } 
    } 

    /* 
     * Return the culture name for a file (e.g. "fr" or "fr-fr").
     * If no culture applies, return null.
     */
    internal static string GetCultureName(string virtualPath) { 

        if (virtualPath == null) return null; 
 
        // By default, extract the culture name from the file name (e.g. "foo.fr-fr.resx")
 
        string fileNameNoExt = Path.GetFileNameWithoutExtension(virtualPath);

        // If virtualPath is not a file, ie. above statement returns null, simply return null;
        if (fileNameNoExt == null) 
            return null;
 
        // If there a dot left 
        int dotIndex = fileNameNoExt.LastIndexOf('.');
 
        if (dotIndex < 0) return null;

        string cultureName = fileNameNoExt.Substring(dotIndex+1);
 
        // If it doesn't look like a culture name (e.g. "fr" or "fr-fr"), return null
        if (!IsCultureName(cultureName)) 
            return null; 

        return cultureName; 
    }


    /* 
     * Returns true if the type string contains an assembly specification
     */ 
    internal static bool TypeNameContainsAssembly(string typeName) { 
        return CommaIndexInTypeName(typeName) > 0;
    } 

    /*
     * Returns the index of the comma separating the type from the assembly, or
     * -1 of there is no assembly 
     */
    internal static int CommaIndexInTypeName(string typeName) { 
 
        // Look for the last comma
        int commaIndex = typeName.LastIndexOf(','); 

        // If it doesn't have one, there is no assembly
        if (commaIndex < 0)
            return -1; 

        // It has a comma, we need to account for the generics syntax. 
        // E.g. it could be "SomeType[int,string] 

        // Check for a ] 
        int rightBracketIndex = typeName.LastIndexOf(']');

        // If it has one, and it's after the last comma, there is no assembly
        if (rightBracketIndex > commaIndex) 
            return -1;
 
        // The comma that we want is the first one after the last ']' 
        commaIndex = typeName.IndexOf(',', rightBracketIndex + 1);
 
        // There is an assembly
        return commaIndex;
    }
 
    /*
     * Return the full path (non shadow copied) to the assembly that 
     * the given type lives in. 
     */
    internal static string GetAssemblyPathFromType(Type t) { 
        return Util.FilePathFromFileUrl(t.Assembly.EscapedCodeBase);
    }

    /* 
     * Same as GetAssemblyPathFromType, but with path safety check
     */ 
    internal static string GetAssemblySafePathFromType(Type t) { 
        return HttpRuntime.GetSafePath(GetAssemblyPathFromType(t));
    } 

    internal static string GetAssemblyQualifiedTypeName(Type t) {
        if (t.Assembly.GlobalAssemblyCache)
            return t.AssemblyQualifiedName; 

        // For non-GAC types, t.AssemblyQualifiedName still returns a big ugly type string, 
        // so return a simpler one instead with just "typename, assemblyName". 
        return t.FullName + ", " + t.Assembly.GetName().Name;
    } 

    internal static string GetAssemblyShortName(Assembly a) {

        // Getting the short name is always safe, so Assert to get it (VSWhidbey 491895) 
        InternalSecurityPermissions.Unrestricted.Assert();
 
        return a.GetName().Name; 
    }
 
    /*
     * Check if the passed in type is for a late bound COM object.  This
     * is what we would get when calling Type.GetTypeFromProgID() on a progid
     * that has not been tlbimp'ed. 
     */
    internal static bool IsLateBoundComClassicType(Type t) { 
        // 
        return (String.Compare(t.FullName, "System.__ComObject", StringComparison.Ordinal) == 0);
    } 

    /*
     * Get the path to the (shadow copied) DLL behind an assembly
     */ 
    internal static string GetAssemblyCodeBase(Assembly assembly) {
 
        string location = assembly.Location; 
        if (String.IsNullOrEmpty(location))
            return null; 

        // Get the path to the assembly (from the cache if it got shadow copied)
        return location;
    } 

    /* 
     * Add the full path to the assembly to the string collection if it's not already there. 
     */
    internal static void AddAssemblyToStringCollection(Assembly assembly, StringCollection toList) { 

        // Get the full path to the assembly
        string assemblyPath = Util.GetAssemblyCodeBase(assembly);
        Debug.Assert(!String.IsNullOrEmpty(assemblyPath)); 

        // Unless it's already in the list, add it 
        if (!toList.Contains(assemblyPath)) { 
            toList.Add(assemblyPath);
        } 
    }

    /*
     * Add the full path to all the assemblies to the string collection if they're not already there. 
     */
    internal static void AddAssembliesToStringCollection(ICollection fromList, StringCollection toList) { 
 
        // Nothing to do if either is null
        if (fromList == null || toList == null) 
            return;

        foreach (Assembly assembly in fromList) {
            AddAssemblyToStringCollection(assembly, toList); 
        }
    } 
 
    /*
     * Return an AssemblySet which contains all the assemblies that 
     * are referenced by the input assembly
     */
    internal static AssemblySet GetReferencedAssemblies(Assembly a) {
 
        AssemblySet referencedAssemblies = new AssemblySet();
        AssemblyName[] refs = a.GetReferencedAssemblies(); 
 
        foreach (AssemblyName aname in refs) {
            Assembly referencedAssembly = Assembly.Load(aname); 

            // Ignore mscorlib
            if (referencedAssembly == typeof(string).Assembly)
                continue; 

            referencedAssemblies.Add(referencedAssembly); 
        } 

        return referencedAssemblies; 
    }

    /*
     * Return an assembly name from the name of an assembly dll. 
     * Basically, it strips the extension.
     */ 
    internal static string GetAssemblyNameFromFileName(string fileName) { 
        // Strip the .dll extension if any
        if (StringUtil.EqualsIgnoreCase(Path.GetExtension(fileName), ".dll")) 
            return fileName.Substring(0, fileName.Length-4);

        return fileName;
    } 

    /* 
     * Look for a type by name in a collection of assemblies.  If it exists in multiple assemblies, 
     * throw an error.
     */ 
    // Assert reflection in order to call assembly.GetType()
    [ReflectionPermission(SecurityAction.Assert, Flags=ReflectionPermissionFlag.MemberAccess)]
    internal static Type GetTypeFromAssemblies(ICollection assemblies, string typeName, bool ignoreCase) {
        if (assemblies == null) 
            return null;
 
        Type type = null; 

        foreach (Assembly assembly in assemblies) { 
            Type t = assembly.GetType(typeName, false /*throwOnError*/, ignoreCase);

            if (t == null)
                continue; 

            // If we had already found a different one, it's an ambiguous type reference 
            if (type != null && t != type) { 
                throw new HttpException(SR.GetString(
                    SR.Ambiguous_type, typeName, 
                    GetAssemblySafePathFromType(type), GetAssemblySafePathFromType(t)));
            }

            // Keep track of it 
            type = t;
        } 
 
        return type;
    } 

    internal static string GetCurrentAccountName() {
        try {
            return System.Security.Principal.WindowsIdentity.GetCurrent().Name; 
        }
        catch { 
            // WindowsIdentity.GetCurrent() can throw.  Return "?" when that happens 
            return "?";
        } 
    }

    internal static string QuoteJScriptString(string value) {
        return QuoteJScriptString(value, false); 
    }
 
    internal static string QuoteJScriptString(string value, bool forUrl) { 
        StringBuilder b = null;
 
        if (String.IsNullOrEmpty(value)) {
            return String.Empty;
        }
 
        int startIndex = 0;
        int count = 0; 
        for (int i=0; i 0) {
                        b.Append(value, startIndex, count); 
                    } 

                    b.Append("\\r"); 

                    startIndex = i + 1;
                    count = 0;
                    break; 
                case '\t':
                    if (b == null) { 
                        b = new StringBuilder(value.Length+5); 
                    }
 
                    if (count > 0) {
                        b.Append(value, startIndex, count);
                    }
 
                    b.Append("\\t");
 
                    startIndex = i + 1; 
                    count = 0;
                    break; 
                case '\"':
                    if (b == null) {
                        b = new StringBuilder(value.Length+5);
                    } 

                    if (count > 0) { 
                        b.Append(value, startIndex, count); 
                    }
 
                    b.Append("\\\"");

                    startIndex = i + 1;
                    count = 0; 
                    break;
                case '\'': 
                    if (b == null) { 
                        b = new StringBuilder(value.Length+5);
                    } 

                    if (count > 0) {
                        b.Append(value, startIndex, count);
                    } 

                    b.Append("\\\'"); 
 
                    startIndex = i + 1;
                    count = 0; 
                    break;
                case '\\':
                    if (b == null) {
                        b = new StringBuilder(value.Length+5); 
                    }
 
                    if (count > 0) { 
                        b.Append(value, startIndex, count);
                    } 

                    b.Append("\\\\");

                    startIndex = i + 1; 
                    count = 0;
                    break; 
                case '\n': 
                    if (b == null) {
                        b = new StringBuilder(value.Length+5); 
                    }

                    if (count > 0) {
                        b.Append(value, startIndex, count); 
                    }
 
                    b.Append("\\n"); 

                    startIndex = i + 1; 
                    count = 0;
                    break;
                case '%':
                    if (forUrl) { 
                        if (b == null) {
                            b = new StringBuilder(value.Length + 6); 
                        } 
                        if (count > 0) {
                            b.Append(value, startIndex, count); 
                        }
                        b.Append("%25");

                        startIndex = i + 1; 
                        count = 0;
                        break; 
                    } 
                    goto default;
                default: 
                    count++;
                    break;
            }
        } 

        if (b == null) { 
            return value; 
        }
 
        if (count > 0) {
            b.Append(value, startIndex, count);
        }
 
        return b.ToString();
    } 
 
    private static ArrayList GetSpecificCultures(string shortName) {
        CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures); 
        ArrayList list = new ArrayList();

        for (int i=0; i 0 && value[length - 1] != ';') { 
                return (value + ";");
            } 
        }
        return value;
    }
 
    internal static string MergeScript(string firstScript, string secondScript) {
        Debug.Assert(!String.IsNullOrEmpty(secondScript)); 
 
        if (!String.IsNullOrEmpty(firstScript)) {
            // 
            return firstScript + secondScript;
        }
        else {
            if (secondScript.TrimStart().StartsWith(ClientScriptManager.JscriptPrefix, StringComparison.Ordinal)) { 
                return secondScript;
            } 
            return ClientScriptManager.JscriptPrefix + secondScript; 
        }
    } 

    internal static bool IsUserAllowedToPath(HttpContext context, VirtualPath virtualPath) {
        // Check FileAuthorizationModule if it's a windows identity
        if (FileAuthorizationModule.IsWindowsIdentity(context)) { 
            if (HttpRuntime.IsFullTrust) {
                if (!IsUserAllowedToPathWithNoAssert(context, virtualPath)) { 
                    return false; 
                }
            } 
            else {
                if (!IsUserAllowedToPathWithAssert(context, virtualPath)) {
                    return false;
                } 
            }
        } 
 
        // Always check UrlAuthorizationModule
        return UrlAuthorizationModule.IsUserAllowedToPath(context, virtualPath); 
    }

    // Need to assert here in order to MapPath in the FileAuthorizationModule.
    [FileIOPermission(SecurityAction.Assert, Unrestricted = true)] 
    private static bool IsUserAllowedToPathWithAssert(HttpContext context, VirtualPath virtualPath) {
        return IsUserAllowedToPathWithNoAssert(context, virtualPath); 
    } 

    private static bool IsUserAllowedToPathWithNoAssert(HttpContext context, VirtualPath virtualPath) { 
        return FileAuthorizationModule.IsUserAllowedToPath(context, virtualPath);
    }

#if DBG 
    internal static void DumpDictionary(string tag, IDictionary d) {
        if (d == null) return; 
 
        Debug.Trace(tag, "Dumping IDictionary with " + d.Count + " entries:");
 
        for (IDictionaryEnumerator en = (IDictionaryEnumerator)d.GetEnumerator(); en.MoveNext();) {
            if (en.Value == null)
                Debug.Trace(tag, "Key='" + en.Key.ToString() + "' value=null");
            else 
                Debug.Trace(tag, "Key='" + en.Key.ToString() + "' value='" + en.Value.ToString() + "'");
        } 
    } 

    internal static void DumpArrayList(string tag, ArrayList al) { 
        if (al == null) return;

        Debug.Trace(tag, "Dumping ArrayList with " + al.Count + " entries:");
 
        foreach (object o in al) {
            if (o == null) 
                Debug.Trace(tag, "value=null"); 
            else
                Debug.Trace(tag, "value='" + o.ToString() + "'"); 
        }
    }

    internal static void DumpString(string tag, string s) { 
        Debug.Trace(tag, "Dumping string  '" + s + "':");
 
        StringBuilder sb = new StringBuilder(); 
        for (int i = 0; i < s.Length; ++i) {
            sb.Append(((int)s[i]).ToString("x", CultureInfo.InvariantCulture)); 
            sb.Append(" ");
        }
        Debug.Trace(tag, sb.ToString());
    } 

#endif // DBG 
 
}
 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

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