We need you! We're working hard on the next version of Developer Fusion - Let us know what you think we should be up to!

The Labs \ Source Viewer \ SSCLI \ System.Configuration \ BaseConfigurationRecord

  1. //------------------------------------------------------------------------------
  2. // <copyright file="BaseConfigurationRecord.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Configuration
  16. {
  17.     using System.Configuration.Internal;
  18.     using System.Collections;
  19.     using System.Collections.Generic;
  20.     using System.Collections.Specialized;
  21.     using System.Configuration;
  22.     using System.Globalization;
  23.     using System.IO;
  24.     using System.Reflection;
  25.     using System.Runtime.InteropServices;
  26.     using System.Security.Permissions;
  27.     using System.Security;
  28.     using System.Text;
  29.     using System.Xml;
  30.    
  31.     //
  32.     // This object represents the configuration for a request path, and is cached per-path.
  33.     //
  34.     internal abstract class BaseConfigurationRecord : IInternalConfigRecord
  35.     {
  36.         protected const string NL = "\r\n";
  37.         protected const string KEYWORD_TRUE = "true";
  38.         protected const string KEYWORD_FALSE = "false";
  39.         protected const string KEYWORD_CONFIGURATION = "configuration";
  40.         protected const string KEYWORD_CONFIGURATION_NAMESPACE = "http://schemas.microsoft.com/.NetConfiguration/v2.0";
  41.         protected const string KEYWORD_CONFIGSECTIONS = "configSections";
  42.         protected const string KEYWORD_SECTION = "section";
  43.         protected const string KEYWORD_SECTION_NAME = "name";
  44.         protected const string KEYWORD_SECTION_TYPE = "type";
  45.         protected const string KEYWORD_SECTION_ALLOWLOCATION = "allowLocation";
  46.         protected const string KEYWORD_SECTION_ALLOWDEFINITION = "allowDefinition";
  47.         protected const string KEYWORD_SECTION_ALLOWDEFINITION_EVERYWHERE = "Everywhere";
  48.         protected const string KEYWORD_SECTION_ALLOWDEFINITION_MACHINEONLY = "MachineOnly";
  49.         protected const string KEYWORD_SECTION_ALLOWDEFINITION_MACHINETOAPPLICATION = "MachineToApplication";
  50.         protected const string KEYWORD_SECTION_ALLOWDEFINITION_MACHINETOWEBROOT = "MachineToWebRoot";
  51.         protected const string KEYWORD_SECTION_ALLOWEXEDEFINITION = "allowExeDefinition";
  52.         protected const string KEYWORD_SECTION_ALLOWEXEDEFINITION_MACHTOROAMING = "MachineToRoamingUser";
  53.         protected const string KEYWORD_SECTION_ALLOWEXEDEFINITION_MACHTOLOCAL = "MachineToLocalUser";
  54.         protected const string KEYWORD_SECTION_RESTARTONEXTERNALCHANGES = "restartOnExternalChanges";
  55.         protected const string KEYWORD_SECTION_REQUIREPERMISSION = "requirePermission";
  56.         protected const string KEYWORD_SECTIONGROUP = "sectionGroup";
  57.         protected const string KEYWORD_SECTIONGROUP_NAME = "name";
  58.         protected const string KEYWORD_SECTIONGROUP_TYPE = "type";
  59.         protected const string KEYWORD_REMOVE = "remove";
  60.         protected const string KEYWORD_CLEAR = "clear";
  61.         protected const string KEYWORD_LOCATION = "location";
  62.         protected const string KEYWORD_LOCATION_PATH = "path";
  63.         protected const string KEYWORD_LOCATION_ALLOWOVERRIDE = "allowOverride";
  64.         protected const string KEYWORD_LOCATION_INHERITINCHILDAPPLICATIONS = "inheritInChildApplications";
  65.         protected const string KEYWORD_CONFIGSOURCE = "configSource";
  66.         protected const string KEYWORD_XMLNS = "xmlns";
  67.         internal const string KEYWORD_PROTECTION_PROVIDER = "configProtectionProvider";
  68.        
  69.         protected const string FORMAT_NEWCONFIGFILE = "<?xml version=\"1.0\" encoding=\"{0}\"?>\r\n";
  70.         protected const string FORMAT_CONFIGURATION = "<configuration>\r\n";
  71.         protected const string FORMAT_CONFIGURATION_NAMESPACE = "<configuration xmlns=\"{0}\">\r\n";
  72.         protected const string FORMAT_CONFIGURATION_ENDELEMENT = "</configuration>";
  73.        
  74.         protected const string FORMAT_LOCATION_NOPATH = "<location allowOverride=\"{0}\" inheritInChildApplications=\"{1}\">\r\n";
  75.         protected const string FORMAT_LOCATION_PATH = "<location path=\"{2}\" allowOverride=\"{0}\" inheritInChildApplications=\"{1}\">\r\n";
  76.         protected const string FORMAT_LOCATION_ENDELEMENT = "</location>";
  77.        
  78.         protected const string FORMAT_SECTION_CONFIGSOURCE = "<{0} configSource=\"{1}\" />";
  79.         protected const string FORMAT_CONFIGSOURCE_FILE = "<?xml version=\"1.0\" encoding=\"{0}\"?>\r\n";
  80.        
  81.         protected const string FORMAT_SECTIONGROUP_ENDELEMENT = "</sectionGroup>";
  82.        
  83.         // Class flags should only be used with the ClassFlags property.
  84.         protected const int ClassSupportsChangeNotifications = 1;
  85.         protected const int ClassSupportsRefresh = 2;
  86.         protected const int ClassSupportsImpersonation = 4;
  87.         protected const int ClassSupportsRestrictedPermissions = 8;
  88.         protected const int ClassSupportsKeepInputs = 16;
  89.         protected const int ClassSupportsDelayedInit = 32;
  90.         protected const int ClassIgnoreLocalErrors = 64;
  91.        
  92.         // Flags to use with the _flags field.
  93.         protected const int ProtectedDataInitialized = 1;
  94.         protected const int Closed = 2;
  95.         protected const int PrefetchAll = 8;
  96.         protected const int IsAboveApplication = 32;
  97.         private const int ContextEvaluated = 128;
  98.         private const int IsLocationListResolved = 256;
  99.         protected const int NamespacePresentInFile = 512;
  100.        
  101.        
  102.         private const int RestrictedPermissionsResolved = 2048;
  103.        
  104.         protected const int IsTrusted = 8192;
  105.        
  106.         protected const int SupportsChangeNotifications = 65536;
  107.         protected const int SupportsRefresh = 131072;
  108.         protected const int SupportsPath = 262144;
  109.         protected const int SupportsKeepInputs = 524288;
  110.         protected const int SupportsLocation = 1048576;
  111.        
  112.         // Flags for Mgmt Configuration Record
  113.         protected const int ForceLocationWritten = 16777216;
  114.         protected const int SuggestLocationRemoval = 33554432;
  115.         protected const int NamespacePresentCurrent = 67108864;
  116.        
  117.         internal const char ConfigPathSeparatorChar = '/';
  118.         internal const string ConfigPathSeparatorString = "/";
  119.         static internal readonly char[] ConfigPathSeparatorParams = new char[] {ConfigPathSeparatorChar};
  120.        
  121.         private static ConfigurationPermission s_unrestrictedConfigPermission;
  122.         // cached ConfigurationPermission
  123.         protected SafeBitVector32 _flags;
  124.         // state
  125.         protected BaseConfigurationRecord _parent;
  126.         // parent record
  127.         protected Hashtable _children;
  128.         // configName -> record
  129.         protected InternalConfigRoot _configRoot;
  130.         // root of configuration
  131.         protected string _configName;
  132.         // the last part of the config path
  133.         protected string _configPath;
  134.         // the full config path
  135.         protected string _locationSubPath;
  136.         // subPath for the config record when editing a location configuration
  137.         private ConfigRecordStreamInfo _configStreamInfo;
  138.         // stream info for the config record
  139.         private object _configContext;
  140.         // Context for config level
  141.         private ProtectedConfigurationSection _protectedConfig;
  142.         // section containing the encryption providers
  143.         private PermissionSet _restrictedPermissions;
  144.         // cached restricted permission set
  145.         private ConfigurationSchemaErrors _initErrors;
  146.         // errors encountered during the parse of the configuration file
  147.         private BaseConfigurationRecord _initDelayedRoot;
  148.         // root of delayed initialization
  149.         // Records information about <configSections> present in this web.config file.
  150.         // config key -> FactoryRecord
  151.         protected Hashtable _factoryRecords;
  152.        
  153.         // Records information about sections that apply to this path,
  154.         // which may be found in this web.config file, in a parent through
  155.         // inheritance, or in a parent through <location>
  156.         // config key -> SectionRecord
  157.         protected Hashtable _sectionRecords;
  158.        
  159.         // Records information about sections in a <location> directive
  160.         // that do not apply to this configPath (sections where path != ".")
  161.         protected ArrayList _locationSections;
  162.        
  163.        
  164.         internal BaseConfigurationRecord()
  165.         {
  166.             // not strictly necessary, but compiler spits out a warning without this initiailization
  167.             _flags = new SafeBitVector32();
  168.         }
  169.        
  170.         // Class flags
  171.         protected abstract SimpleBitVector32 ClassFlags {
  172.             get;
  173.         }
  174.        
  175.         // Create the factory that will evaluate configuration
  176.         protected abstract object CreateSectionFactory(FactoryRecord factoryRecord);
  177.        
  178.         // Create the configuration object
  179.         protected abstract object CreateSection(bool inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader);
  180.        
  181.         // Use the parent result in creating the child
  182.         protected abstract object UseParentResult(string configKey, object parentResult, SectionRecord sectionRecord);
  183.        
  184.         // Return the runtime object from GetSection
  185.         protected abstract object GetRuntimeObject(object result);
  186.        
  187.         //
  188.         // IInternalConfigRecord methods
  189.         //
  190.        
  191.         public string ConfigPath {
  192.             get { return _configPath; }
  193.         }
  194.        
  195.         public string StreamName {
  196.             get { return ConfigStreamInfo.StreamName; }
  197.         }
  198.        
  199.         public bool HasInitErrors {
  200.             get { return _initErrors.HasErrors(ClassFlags[ClassIgnoreLocalErrors]); }
  201.         }
  202.        
  203.         public void ThrowIfInitErrors()
  204.         {
  205.             ThrowIfParseErrors(_initErrors);
  206.         }
  207.        
  208.         public object GetSection(string configKey)
  209.         {
  210.             #if DBG
  211.             // On debug builds, the config system depends on system.diagnostics,
  212.             // so we must always return a valid result and never throw.
  213.             if (configKey == "system.diagnostics" && !ClassFlags[ClassIgnoreLocalErrors]) {
  214.                 return GetSection(configKey, true, true);
  215.             }
  216.             else {
  217.                 return GetSection(configKey, false, true);
  218.             }
  219.             #else
  220.            
  221.             return GetSection(configKey, false, true);
  222.             #endif
  223.         }
  224.        
  225.         public object GetLkgSection(string configKey)
  226.         {
  227.             return GetSection(configKey, true, true);
  228.         }
  229.        
  230.         public void RefreshSection(string configKey)
  231.         {
  232.             _configRoot.ClearResult(this, configKey, true);
  233.         }
  234.        
  235.         public void Remove()
  236.         {
  237.             _configRoot.RemoveConfigRecord(this);
  238.         }
  239.        
  240.         //
  241.         // end of IInternalConfigRecord methods
  242.         //
  243.        
  244.         internal bool HasStream {
  245.             get { return ConfigStreamInfo.HasStream; }
  246.         }
  247.        
  248.         // Determine which sections should be prefetched during the first scan.
  249.         private bool ShouldPrefetchRawXml(FactoryRecord factoryRecord)
  250.         {
  251.             if (_flags[PrefetchAll])
  252.                 return true;
  253.            
  254.             switch (factoryRecord.ConfigKey) {
  255.                 case BaseConfigurationRecord.RESERVED_SECTION_PROTECTED_CONFIGURATION:
  256.                 case "system.diagnostics":
  257.                 case "appSettings":
  258.                 case "connectionStrings":
  259.                     return true;
  260.             }
  261.            
  262.             return Host.PrefetchSection(factoryRecord.Group, factoryRecord.Name);
  263.         }
  264.        
  265.         protected IDisposable Impersonate()
  266.         {
  267.             IDisposable context = null;
  268.             if (ClassFlags[ClassSupportsImpersonation]) {
  269.                 context = Host.Impersonate();
  270.             }
  271.            
  272.             if (context == null) {
  273.                 context = EmptyImpersonationContext.GetStaticInstance();
  274.             }
  275.            
  276.             return context;
  277.         }
  278.        
  279.         internal PermissionSet GetRestrictedPermissions()
  280.         {
  281.             if (!_flags[RestrictedPermissionsResolved]) {
  282.                 PermissionSet restrictedPermissions;
  283.                 bool isHostReady;
  284.                
  285.                 Host.GetRestrictedPermissions(this, out restrictedPermissions, out isHostReady);
  286.                 if (isHostReady) {
  287.                     _restrictedPermissions = restrictedPermissions;
  288.                     _flags[RestrictedPermissionsResolved] = true;
  289.                 }
  290.             }
  291.            
  292.             return _restrictedPermissions;
  293.         }
  294.        
  295.         internal void Init(IInternalConfigRoot configRoot, BaseConfigurationRecord parent, string configPath, string locationSubPath)
  296.         {
  297.            
  298.             _initErrors = new ConfigurationSchemaErrors();
  299.            
  300.             //
  301.             // try/catch here is only for unexpected exceptions due to errors in
  302.             // our own code, as we always want the configuration record to be
  303.             // usable
  304.             //
  305.             try {
  306.                 _configRoot = (InternalConfigRoot)configRoot;
  307.                 _parent = parent;
  308.                 _configPath = configPath;
  309.                 _locationSubPath = locationSubPath;
  310.                 _configName = ConfigPathUtility.GetName(configPath);
  311.                
  312.                 if (IsLocationConfig) {
  313.                     _configStreamInfo = _parent.ConfigStreamInfo;
  314.                 }
  315.                 else {
  316.                 &nb