Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / Sys / System / Configuration / LocalFileSettingsProvider.cs / 1 / LocalFileSettingsProvider.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- using System.Diagnostics.CodeAnalysis; namespace System.Configuration { using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Configuration; using System.Configuration.Provider; using System.Diagnostics; using System.Globalization; using System.IO; using System.Security; using System.Security.Permissions; using System.Xml; using System.Xml.Serialization; using System.Runtime.Versioning; ////// [ PermissionSet(SecurityAction.LinkDemand, Name="FullTrust"), PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust") ] public class LocalFileSettingsProvider : SettingsProvider, IApplicationSettingsProvider { private string _appName = String.Empty; private ClientSettingsStore _store = null; private string _prevLocalConfigFileName = null; private string _prevRoamingConfigFileName = null; private XmlEscaper _escaper = null; ////// This is a provider used to store configuration settings locally for client applications. /// ////// Abstract SettingsProvider property. /// public override string ApplicationName { get { return _appName; } set { _appName = value; } } private XmlEscaper Escaper { get { if (_escaper == null) { _escaper = new XmlEscaper(); } return _escaper; } } ////// We maintain a single instance of the ClientSettingsStore per instance of provider. /// private ClientSettingsStore Store { get { if (_store == null) { _store = new ClientSettingsStore(); } return _store; } } ////// Abstract ProviderBase method. /// public override void Initialize(string name, NameValueCollection values) { if (String.IsNullOrEmpty(name)) { name = "LocalFileSettingsProvider"; } base.Initialize(name, values); } ////// Abstract SettingsProvider method /// public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection properties) { SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); string sectionName = GetSectionName(context); //<--Look for this section in both applicationSettingsGroup and userSettingsGroup--> IDictionary appSettings = Store.ReadSettings(sectionName, false); IDictionary userSettings = Store.ReadSettings(sectionName, true); ConnectionStringSettingsCollection connStrings = Store.ReadConnectionStrings(); //<--Now map each SettingProperty to the right StoredSetting and deserialize the value if found.--> foreach (SettingsProperty setting in properties) { string settingName = setting.Name; SettingsPropertyValue value = new SettingsPropertyValue(setting); // First look for and handle "special" settings SpecialSettingAttribute attr = setting.Attributes[typeof(SpecialSettingAttribute)] as SpecialSettingAttribute; bool isConnString = (attr != null) ? (attr.SpecialSetting == SpecialSetting.ConnectionString) : false; if (isConnString) { string connStringName = sectionName + "." + settingName; if (connStrings != null && connStrings[connStringName] != null) { value.PropertyValue = connStrings[connStringName].ConnectionString; } else if (setting.DefaultValue != null && setting.DefaultValue is string) { value.PropertyValue = setting.DefaultValue; } else { //No value found and no default specified value.PropertyValue = String.Empty; } value.IsDirty = false; //reset IsDirty so that it is correct when SetPropertyValues is called values.Add(value); continue; } // Not a "special" setting bool isUserSetting = IsUserSetting(setting); if (isUserSetting && !ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) { // We encountered a user setting, but the current configuration system does not support // user settings. throw new ConfigurationErrorsException(SR.GetString(SR.UserSettingsNotSupported)); } IDictionary settings = isUserSetting ? userSettings : appSettings; if (settings.Contains(settingName)) { StoredSetting ss = (StoredSetting) settings[settingName]; string valueString = ss.Value.InnerXml; // We need to un-escape string serialized values if (ss.SerializeAs == SettingsSerializeAs.String) { valueString = Escaper.Unescape(valueString); } value.SerializedValue = valueString; } else if (setting.DefaultValue != null) { value.SerializedValue = setting.DefaultValue; } else { //No value found and no default specified value.PropertyValue = null; } value.IsDirty = false; //reset IsDirty so that it is correct when SetPropertyValues is called values.Add(value); } return values; } ////// Abstract SettingsProvider method /// public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection values) { string sectionName = GetSectionName(context); IDictionary roamingUserSettings = new Hashtable(); IDictionary localUserSettings = new Hashtable(); foreach (SettingsPropertyValue value in values) { SettingsProperty setting = value.Property; bool isUserSetting = IsUserSetting(setting); if (value.IsDirty) { if (isUserSetting) { bool isRoaming = IsRoamingSetting(setting); StoredSetting ss = new StoredSetting(setting.SerializeAs, SerializeToXmlElement(setting, value)); if (isRoaming) { roamingUserSettings[setting.Name] = ss; } else { localUserSettings[setting.Name] = ss; } value.IsDirty = false; //reset IsDirty } else { // This is an app-scoped or connection string setting that has been written to. // We don't support saving these. } } } // Semi-hack: If there are roamable settings, let's write them before local settings so if a handler // declaration is necessary, it goes in the roaming config file in preference to the local config file. if (roamingUserSettings.Count > 0) { Store.WriteSettings(sectionName, true, roamingUserSettings); } if (localUserSettings.Count > 0) { Store.WriteSettings(sectionName, false, localUserSettings); } } ////// Implementation of IClientSettingsProvider.Reset. Resets user scoped settings to the values /// in app.exe.config, does nothing for app scoped settings. /// public void Reset(SettingsContext context) { string sectionName = GetSectionName(context); // First revert roaming, then local Store.RevertToParent(sectionName, true); Store.RevertToParent(sectionName, false); } ////// Implementation of IClientSettingsProvider.Upgrade. /// Tries to locate a previous version of the user.config file. If found, it migrates matching settings. /// If not, it does nothing. /// public void Upgrade(SettingsContext context, SettingsPropertyCollection properties) { // Separate the local and roaming settings and upgrade them separately. SettingsPropertyCollection local = new SettingsPropertyCollection(); SettingsPropertyCollection roaming = new SettingsPropertyCollection(); foreach (SettingsProperty sp in properties) { bool isRoaming = IsRoamingSetting(sp); if (isRoaming) { roaming.Add(sp); } else { local.Add(sp); } } if (roaming.Count > 0) { Upgrade(context, roaming, true); } if (local.Count > 0) { Upgrade(context, local, false); } } ////// Encapsulates the Version constructor so that we can return null when an exception is thrown. /// private Version CreateVersion(string name) { Version ver = null; try { ver = new Version(name); } catch (ArgumentException) { ver = null; } catch (OverflowException) { ver = null; } catch (FormatException) { ver = null; } return ver; } ////// Implementation of IClientSettingsProvider.GetPreviousVersion. /// // Security Note: Like Upgrade, GetPreviousVersion involves finding a previous version user.config file and // reading settings from it. To support this in partial trust, we need to assert file i/o here. We believe // this to be safe, since the user does not have a way to specify the file or control where we look for it. // So it is no different than reading from the default user.config file, which we already allow in partial trust. // BTW, the Link/Inheritance demand pair here is just a copy of what's at the class level, and is needed since // we are overriding security at method level. [ FileIOPermission(SecurityAction.Assert, AllFiles=FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read), PermissionSet(SecurityAction.LinkDemand, Name="FullTrust"), PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust") ] public SettingsPropertyValue GetPreviousVersion(SettingsContext context, SettingsProperty property) { bool isRoaming = IsRoamingSetting(property); string prevConfig = GetPreviousConfigFileName(isRoaming); if (!String.IsNullOrEmpty(prevConfig)) { SettingsPropertyCollection properties = new SettingsPropertyCollection(); properties.Add(property); SettingsPropertyValueCollection values = GetSettingValuesFromFile(prevConfig, GetSectionName(context), true, properties); return values[property.Name]; } else { SettingsPropertyValue value = new SettingsPropertyValue(property); value.PropertyValue = null; return value; } } ////// Locates the previous version of user.config, if present. The previous version is determined /// by walking up one directory level in the *UserConfigPath and searching for the highest version /// number less than the current version. /// SECURITY NOTE: Config path information is privileged - do not directly pass this on to untrusted callers. /// Note this is meant to be used at installation time to help migrate /// config settings from a previous version of the app. /// [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private string GetPreviousConfigFileName(bool isRoaming) { if (!ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) { throw new ConfigurationErrorsException(SR.GetString(SR.UserSettingsNotSupported)); } string prevConfigFile = isRoaming ? _prevRoamingConfigFileName : _prevLocalConfigFileName; if (String.IsNullOrEmpty(prevConfigFile)) { string userConfigPath = isRoaming ? ConfigurationManagerInternalFactory.Instance.ExeRoamingConfigDirectory : ConfigurationManagerInternalFactory.Instance.ExeLocalConfigDirectory; Version curVer = CreateVersion(ConfigurationManagerInternalFactory.Instance.ExeProductVersion); Version prevVer = null; DirectoryInfo prevDir = null; string file = null; if (curVer == null) { return null; } DirectoryInfo parentDir = Directory.GetParent(userConfigPath); if (parentDir.Exists) { foreach (DirectoryInfo dir in parentDir.GetDirectories()) { Version tempVer = CreateVersion(dir.Name); if (tempVer != null && tempVer < curVer) { if (prevVer == null) { prevVer = tempVer; prevDir = dir; } else if (tempVer > prevVer) { prevVer = tempVer; prevDir = dir; } } } if (prevDir != null) { file = Path.Combine(prevDir.FullName, ConfigurationManagerInternalFactory.Instance.UserConfigFilename); } if (File.Exists(file)) { prevConfigFile = file; } } //Cache for future use. if (isRoaming) { _prevRoamingConfigFileName = prevConfigFile; } else { _prevLocalConfigFileName = prevConfigFile; } } return prevConfigFile; } ////// Gleans information from the SettingsContext and determines the name of the config section. /// private string GetSectionName(SettingsContext context) { string groupName = (string) context["GroupName"]; string key = (string) context["SettingsKey"]; Debug.Assert(groupName != null, "SettingsContext did not have a GroupName!"); string sectionName = groupName; if (!String.IsNullOrEmpty(key)) { sectionName = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", sectionName, key); } return XmlConvert.EncodeLocalName(sectionName); } ////// Retrieves the values of settings from the given config file (as opposed to using /// the configuration for the current context) /// private SettingsPropertyValueCollection GetSettingValuesFromFile(string configFileName, string sectionName, bool userScoped, SettingsPropertyCollection properties) { SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); IDictionary settings = ClientSettingsStore.ReadSettingsFromFile(configFileName, sectionName, userScoped); // Map each SettingProperty to the right StoredSetting and deserialize the value if found. foreach (SettingsProperty setting in properties) { string settingName = setting.Name; SettingsPropertyValue value = new SettingsPropertyValue(setting); if (settings.Contains(settingName)) { StoredSetting ss = (StoredSetting) settings[settingName]; string valueString = ss.Value.InnerXml; // We need to un-escape string serialized values if (ss.SerializeAs == SettingsSerializeAs.String) { valueString = Escaper.Unescape(valueString); } value.SerializedValue = valueString; value.IsDirty = true; values.Add(value); } } return values; } ////// Indicates whether a setting is roaming or not. /// private static bool IsRoamingSetting(SettingsProperty setting) { // Roaming is not supported in Clickonce deployed apps, since they don't have roaming config files. bool roamingSupported = !ApplicationSettingsBase.IsClickOnceDeployed(AppDomain.CurrentDomain); bool isRoaming = false; if (roamingSupported) { SettingsManageabilityAttribute manageAttr = setting.Attributes[typeof(SettingsManageabilityAttribute)] as SettingsManageabilityAttribute; isRoaming = manageAttr != null && ((manageAttr.Manageability & SettingsManageability.Roaming) == SettingsManageability.Roaming); } return isRoaming; } ////// This provider needs settings to be marked with either the UserScopedSettingAttribute or the /// ApplicationScopedSettingAttribute. This method determines whether this setting is user-scoped /// or not. It will throw if none or both of the attributes are present. /// private bool IsUserSetting(SettingsProperty setting) { bool isUser = setting.Attributes[typeof(UserScopedSettingAttribute)] is UserScopedSettingAttribute; bool isApp = setting.Attributes[typeof(ApplicationScopedSettingAttribute)] is ApplicationScopedSettingAttribute; if (isUser && isApp) { throw new ConfigurationErrorsException(SR.GetString(SR.BothScopeAttributes)); } else if (!(isUser || isApp)) { throw new ConfigurationErrorsException(SR.GetString(SR.NoScopeAttributes)); } return isUser; } private XmlNode SerializeToXmlElement(SettingsProperty setting, SettingsPropertyValue value) { XmlDocument doc = new XmlDocument(); XmlElement valueXml = doc.CreateElement("value"); string serializedValue = value.SerializedValue as string; if (serializedValue == null && setting.SerializeAs == SettingsSerializeAs.Binary) { // SettingsPropertyValue returns a byte[] in the binary serialization case. We need to // encode this - we use base64 since SettingsPropertyValue understands it and we won't have // to special case while deserializing. byte[] buf = value.SerializedValue as byte[]; if (buf != null) { serializedValue = Convert.ToBase64String(buf); } } if (serializedValue == null) { serializedValue = String.Empty; } // We need to escape string serialized values if (setting.SerializeAs == SettingsSerializeAs.String) { serializedValue = Escaper.Escape(serializedValue); } valueXml.InnerXml = serializedValue; // Hack to remove the XmlDeclaration that the XmlSerializer adds. XmlNode unwanted = null; foreach (XmlNode child in valueXml.ChildNodes) { if (child.NodeType == XmlNodeType.XmlDeclaration) { unwanted = child; break; } } if (unwanted != null) { valueXml.RemoveChild(unwanted); } return valueXml; } ////// Private version of upgrade that uses isRoaming to determine which config file to use. /// // Security Note: Upgrade involves finding a previous version user.config file and reading settings from it. To // support this in partial trust, we need to assert file i/o here. We believe this to be safe, since the user // does not have a way to specify the file or control where we look for it. As such, it is no different than // reading from the default user.config file, which we already allow in partial trust. // The following suppress is okay, since the Link/Inheritance demand pair at the class level are not needed for // this method, since it is private. [SuppressMessage("Microsoft.Security", "CA2114:MethodSecurityShouldBeASupersetOfType")] [FileIOPermission(SecurityAction.Assert, AllFiles=FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read)] private void Upgrade(SettingsContext context, SettingsPropertyCollection properties, bool isRoaming) { string prevConfig = GetPreviousConfigFileName(isRoaming); if (!String.IsNullOrEmpty(prevConfig)) { //Filter the settings properties to exclude those that have a NoSettingsVersionUpgradeAttribute on them. SettingsPropertyCollection upgradeProperties = new SettingsPropertyCollection(); foreach (SettingsProperty sp in properties) { if (!(sp.Attributes[typeof(NoSettingsVersionUpgradeAttribute)] is NoSettingsVersionUpgradeAttribute)) { upgradeProperties.Add(sp); } } SettingsPropertyValueCollection values = GetSettingValuesFromFile(prevConfig, GetSectionName(context), true, upgradeProperties); SetPropertyValues(context, values); } } private class XmlEscaper { private XmlDocument doc; private XmlElement temp; internal XmlEscaper() { doc = new XmlDocument(); temp = doc.CreateElement("temp"); } internal string Escape(string xmlString) { if (String.IsNullOrEmpty(xmlString)) { return xmlString; } temp.InnerText = xmlString; return temp.InnerXml; } internal string Unescape(string escapedString) { if (String.IsNullOrEmpty(escapedString)) { return escapedString; } temp.InnerXml = escapedString; return temp.InnerText; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- using System.Diagnostics.CodeAnalysis; namespace System.Configuration { using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Configuration; using System.Configuration.Provider; using System.Diagnostics; using System.Globalization; using System.IO; using System.Security; using System.Security.Permissions; using System.Xml; using System.Xml.Serialization; using System.Runtime.Versioning; ////// [ PermissionSet(SecurityAction.LinkDemand, Name="FullTrust"), PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust") ] public class LocalFileSettingsProvider : SettingsProvider, IApplicationSettingsProvider { private string _appName = String.Empty; private ClientSettingsStore _store = null; private string _prevLocalConfigFileName = null; private string _prevRoamingConfigFileName = null; private XmlEscaper _escaper = null; ////// This is a provider used to store configuration settings locally for client applications. /// ////// Abstract SettingsProvider property. /// public override string ApplicationName { get { return _appName; } set { _appName = value; } } private XmlEscaper Escaper { get { if (_escaper == null) { _escaper = new XmlEscaper(); } return _escaper; } } ////// We maintain a single instance of the ClientSettingsStore per instance of provider. /// private ClientSettingsStore Store { get { if (_store == null) { _store = new ClientSettingsStore(); } return _store; } } ////// Abstract ProviderBase method. /// public override void Initialize(string name, NameValueCollection values) { if (String.IsNullOrEmpty(name)) { name = "LocalFileSettingsProvider"; } base.Initialize(name, values); } ////// Abstract SettingsProvider method /// public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection properties) { SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); string sectionName = GetSectionName(context); //<--Look for this section in both applicationSettingsGroup and userSettingsGroup--> IDictionary appSettings = Store.ReadSettings(sectionName, false); IDictionary userSettings = Store.ReadSettings(sectionName, true); ConnectionStringSettingsCollection connStrings = Store.ReadConnectionStrings(); //<--Now map each SettingProperty to the right StoredSetting and deserialize the value if found.--> foreach (SettingsProperty setting in properties) { string settingName = setting.Name; SettingsPropertyValue value = new SettingsPropertyValue(setting); // First look for and handle "special" settings SpecialSettingAttribute attr = setting.Attributes[typeof(SpecialSettingAttribute)] as SpecialSettingAttribute; bool isConnString = (attr != null) ? (attr.SpecialSetting == SpecialSetting.ConnectionString) : false; if (isConnString) { string connStringName = sectionName + "." + settingName; if (connStrings != null && connStrings[connStringName] != null) { value.PropertyValue = connStrings[connStringName].ConnectionString; } else if (setting.DefaultValue != null && setting.DefaultValue is string) { value.PropertyValue = setting.DefaultValue; } else { //No value found and no default specified value.PropertyValue = String.Empty; } value.IsDirty = false; //reset IsDirty so that it is correct when SetPropertyValues is called values.Add(value); continue; } // Not a "special" setting bool isUserSetting = IsUserSetting(setting); if (isUserSetting && !ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) { // We encountered a user setting, but the current configuration system does not support // user settings. throw new ConfigurationErrorsException(SR.GetString(SR.UserSettingsNotSupported)); } IDictionary settings = isUserSetting ? userSettings : appSettings; if (settings.Contains(settingName)) { StoredSetting ss = (StoredSetting) settings[settingName]; string valueString = ss.Value.InnerXml; // We need to un-escape string serialized values if (ss.SerializeAs == SettingsSerializeAs.String) { valueString = Escaper.Unescape(valueString); } value.SerializedValue = valueString; } else if (setting.DefaultValue != null) { value.SerializedValue = setting.DefaultValue; } else { //No value found and no default specified value.PropertyValue = null; } value.IsDirty = false; //reset IsDirty so that it is correct when SetPropertyValues is called values.Add(value); } return values; } ////// Abstract SettingsProvider method /// public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection values) { string sectionName = GetSectionName(context); IDictionary roamingUserSettings = new Hashtable(); IDictionary localUserSettings = new Hashtable(); foreach (SettingsPropertyValue value in values) { SettingsProperty setting = value.Property; bool isUserSetting = IsUserSetting(setting); if (value.IsDirty) { if (isUserSetting) { bool isRoaming = IsRoamingSetting(setting); StoredSetting ss = new StoredSetting(setting.SerializeAs, SerializeToXmlElement(setting, value)); if (isRoaming) { roamingUserSettings[setting.Name] = ss; } else { localUserSettings[setting.Name] = ss; } value.IsDirty = false; //reset IsDirty } else { // This is an app-scoped or connection string setting that has been written to. // We don't support saving these. } } } // Semi-hack: If there are roamable settings, let's write them before local settings so if a handler // declaration is necessary, it goes in the roaming config file in preference to the local config file. if (roamingUserSettings.Count > 0) { Store.WriteSettings(sectionName, true, roamingUserSettings); } if (localUserSettings.Count > 0) { Store.WriteSettings(sectionName, false, localUserSettings); } } ////// Implementation of IClientSettingsProvider.Reset. Resets user scoped settings to the values /// in app.exe.config, does nothing for app scoped settings. /// public void Reset(SettingsContext context) { string sectionName = GetSectionName(context); // First revert roaming, then local Store.RevertToParent(sectionName, true); Store.RevertToParent(sectionName, false); } ////// Implementation of IClientSettingsProvider.Upgrade. /// Tries to locate a previous version of the user.config file. If found, it migrates matching settings. /// If not, it does nothing. /// public void Upgrade(SettingsContext context, SettingsPropertyCollection properties) { // Separate the local and roaming settings and upgrade them separately. SettingsPropertyCollection local = new SettingsPropertyCollection(); SettingsPropertyCollection roaming = new SettingsPropertyCollection(); foreach (SettingsProperty sp in properties) { bool isRoaming = IsRoamingSetting(sp); if (isRoaming) { roaming.Add(sp); } else { local.Add(sp); } } if (roaming.Count > 0) { Upgrade(context, roaming, true); } if (local.Count > 0) { Upgrade(context, local, false); } } ////// Encapsulates the Version constructor so that we can return null when an exception is thrown. /// private Version CreateVersion(string name) { Version ver = null; try { ver = new Version(name); } catch (ArgumentException) { ver = null; } catch (OverflowException) { ver = null; } catch (FormatException) { ver = null; } return ver; } ////// Implementation of IClientSettingsProvider.GetPreviousVersion. /// // Security Note: Like Upgrade, GetPreviousVersion involves finding a previous version user.config file and // reading settings from it. To support this in partial trust, we need to assert file i/o here. We believe // this to be safe, since the user does not have a way to specify the file or control where we look for it. // So it is no different than reading from the default user.config file, which we already allow in partial trust. // BTW, the Link/Inheritance demand pair here is just a copy of what's at the class level, and is needed since // we are overriding security at method level. [ FileIOPermission(SecurityAction.Assert, AllFiles=FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read), PermissionSet(SecurityAction.LinkDemand, Name="FullTrust"), PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust") ] public SettingsPropertyValue GetPreviousVersion(SettingsContext context, SettingsProperty property) { bool isRoaming = IsRoamingSetting(property); string prevConfig = GetPreviousConfigFileName(isRoaming); if (!String.IsNullOrEmpty(prevConfig)) { SettingsPropertyCollection properties = new SettingsPropertyCollection(); properties.Add(property); SettingsPropertyValueCollection values = GetSettingValuesFromFile(prevConfig, GetSectionName(context), true, properties); return values[property.Name]; } else { SettingsPropertyValue value = new SettingsPropertyValue(property); value.PropertyValue = null; return value; } } ////// Locates the previous version of user.config, if present. The previous version is determined /// by walking up one directory level in the *UserConfigPath and searching for the highest version /// number less than the current version. /// SECURITY NOTE: Config path information is privileged - do not directly pass this on to untrusted callers. /// Note this is meant to be used at installation time to help migrate /// config settings from a previous version of the app. /// [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private string GetPreviousConfigFileName(bool isRoaming) { if (!ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) { throw new ConfigurationErrorsException(SR.GetString(SR.UserSettingsNotSupported)); } string prevConfigFile = isRoaming ? _prevRoamingConfigFileName : _prevLocalConfigFileName; if (String.IsNullOrEmpty(prevConfigFile)) { string userConfigPath = isRoaming ? ConfigurationManagerInternalFactory.Instance.ExeRoamingConfigDirectory : ConfigurationManagerInternalFactory.Instance.ExeLocalConfigDirectory; Version curVer = CreateVersion(ConfigurationManagerInternalFactory.Instance.ExeProductVersion); Version prevVer = null; DirectoryInfo prevDir = null; string file = null; if (curVer == null) { return null; } DirectoryInfo parentDir = Directory.GetParent(userConfigPath); if (parentDir.Exists) { foreach (DirectoryInfo dir in parentDir.GetDirectories()) { Version tempVer = CreateVersion(dir.Name); if (tempVer != null && tempVer < curVer) { if (prevVer == null) { prevVer = tempVer; prevDir = dir; } else if (tempVer > prevVer) { prevVer = tempVer; prevDir = dir; } } } if (prevDir != null) { file = Path.Combine(prevDir.FullName, ConfigurationManagerInternalFactory.Instance.UserConfigFilename); } if (File.Exists(file)) { prevConfigFile = file; } } //Cache for future use. if (isRoaming) { _prevRoamingConfigFileName = prevConfigFile; } else { _prevLocalConfigFileName = prevConfigFile; } } return prevConfigFile; } ////// Gleans information from the SettingsContext and determines the name of the config section. /// private string GetSectionName(SettingsContext context) { string groupName = (string) context["GroupName"]; string key = (string) context["SettingsKey"]; Debug.Assert(groupName != null, "SettingsContext did not have a GroupName!"); string sectionName = groupName; if (!String.IsNullOrEmpty(key)) { sectionName = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", sectionName, key); } return XmlConvert.EncodeLocalName(sectionName); } ////// Retrieves the values of settings from the given config file (as opposed to using /// the configuration for the current context) /// private SettingsPropertyValueCollection GetSettingValuesFromFile(string configFileName, string sectionName, bool userScoped, SettingsPropertyCollection properties) { SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); IDictionary settings = ClientSettingsStore.ReadSettingsFromFile(configFileName, sectionName, userScoped); // Map each SettingProperty to the right StoredSetting and deserialize the value if found. foreach (SettingsProperty setting in properties) { string settingName = setting.Name; SettingsPropertyValue value = new SettingsPropertyValue(setting); if (settings.Contains(settingName)) { StoredSetting ss = (StoredSetting) settings[settingName]; string valueString = ss.Value.InnerXml; // We need to un-escape string serialized values if (ss.SerializeAs == SettingsSerializeAs.String) { valueString = Escaper.Unescape(valueString); } value.SerializedValue = valueString; value.IsDirty = true; values.Add(value); } } return values; } ////// Indicates whether a setting is roaming or not. /// private static bool IsRoamingSetting(SettingsProperty setting) { // Roaming is not supported in Clickonce deployed apps, since they don't have roaming config files. bool roamingSupported = !ApplicationSettingsBase.IsClickOnceDeployed(AppDomain.CurrentDomain); bool isRoaming = false; if (roamingSupported) { SettingsManageabilityAttribute manageAttr = setting.Attributes[typeof(SettingsManageabilityAttribute)] as SettingsManageabilityAttribute; isRoaming = manageAttr != null && ((manageAttr.Manageability & SettingsManageability.Roaming) == SettingsManageability.Roaming); } return isRoaming; } ////// This provider needs settings to be marked with either the UserScopedSettingAttribute or the /// ApplicationScopedSettingAttribute. This method determines whether this setting is user-scoped /// or not. It will throw if none or both of the attributes are present. /// private bool IsUserSetting(SettingsProperty setting) { bool isUser = setting.Attributes[typeof(UserScopedSettingAttribute)] is UserScopedSettingAttribute; bool isApp = setting.Attributes[typeof(ApplicationScopedSettingAttribute)] is ApplicationScopedSettingAttribute; if (isUser && isApp) { throw new ConfigurationErrorsException(SR.GetString(SR.BothScopeAttributes)); } else if (!(isUser || isApp)) { throw new ConfigurationErrorsException(SR.GetString(SR.NoScopeAttributes)); } return isUser; } private XmlNode SerializeToXmlElement(SettingsProperty setting, SettingsPropertyValue value) { XmlDocument doc = new XmlDocument(); XmlElement valueXml = doc.CreateElement("value"); string serializedValue = value.SerializedValue as string; if (serializedValue == null && setting.SerializeAs == SettingsSerializeAs.Binary) { // SettingsPropertyValue returns a byte[] in the binary serialization case. We need to // encode this - we use base64 since SettingsPropertyValue understands it and we won't have // to special case while deserializing. byte[] buf = value.SerializedValue as byte[]; if (buf != null) { serializedValue = Convert.ToBase64String(buf); } } if (serializedValue == null) { serializedValue = String.Empty; } // We need to escape string serialized values if (setting.SerializeAs == SettingsSerializeAs.String) { serializedValue = Escaper.Escape(serializedValue); } valueXml.InnerXml = serializedValue; // Hack to remove the XmlDeclaration that the XmlSerializer adds. XmlNode unwanted = null; foreach (XmlNode child in valueXml.ChildNodes) { if (child.NodeType == XmlNodeType.XmlDeclaration) { unwanted = child; break; } } if (unwanted != null) { valueXml.RemoveChild(unwanted); } return valueXml; } ////// Private version of upgrade that uses isRoaming to determine which config file to use. /// // Security Note: Upgrade involves finding a previous version user.config file and reading settings from it. To // support this in partial trust, we need to assert file i/o here. We believe this to be safe, since the user // does not have a way to specify the file or control where we look for it. As such, it is no different than // reading from the default user.config file, which we already allow in partial trust. // The following suppress is okay, since the Link/Inheritance demand pair at the class level are not needed for // this method, since it is private. [SuppressMessage("Microsoft.Security", "CA2114:MethodSecurityShouldBeASupersetOfType")] [FileIOPermission(SecurityAction.Assert, AllFiles=FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read)] private void Upgrade(SettingsContext context, SettingsPropertyCollection properties, bool isRoaming) { string prevConfig = GetPreviousConfigFileName(isRoaming); if (!String.IsNullOrEmpty(prevConfig)) { //Filter the settings properties to exclude those that have a NoSettingsVersionUpgradeAttribute on them. SettingsPropertyCollection upgradeProperties = new SettingsPropertyCollection(); foreach (SettingsProperty sp in properties) { if (!(sp.Attributes[typeof(NoSettingsVersionUpgradeAttribute)] is NoSettingsVersionUpgradeAttribute)) { upgradeProperties.Add(sp); } } SettingsPropertyValueCollection values = GetSettingValuesFromFile(prevConfig, GetSectionName(context), true, upgradeProperties); SetPropertyValues(context, values); } } private class XmlEscaper { private XmlDocument doc; private XmlElement temp; internal XmlEscaper() { doc = new XmlDocument(); temp = doc.CreateElement("temp"); } internal string Escape(string xmlString) { if (String.IsNullOrEmpty(xmlString)) { return xmlString; } temp.InnerText = xmlString; return temp.InnerXml; } internal string Unescape(string escapedString) { if (String.IsNullOrEmpty(escapedString)) { return escapedString; } temp.InnerXml = escapedString; return temp.InnerText; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ClassHandlersStore.cs
- SrgsElementList.cs
- MouseEvent.cs
- RotateTransform.cs
- ExceptionUtil.cs
- ResourceKey.cs
- WebPartHelpVerb.cs
- TreeNodeBinding.cs
- WorkflowMessageEventHandler.cs
- NullEntityWrapper.cs
- DurationConverter.cs
- CompensatableTransactionScopeActivity.cs
- ApplicationServiceManager.cs
- PeerNameRecord.cs
- FigureParaClient.cs
- Setter.cs
- GenericAuthenticationEventArgs.cs
- BindingContext.cs
- WebPartConnectionsCloseVerb.cs
- ChameleonKey.cs
- SortAction.cs
- UnionCodeGroup.cs
- EncryptRequest.cs
- SecurityKeyIdentifierClause.cs
- Base64Encoder.cs
- XPathDocumentBuilder.cs
- DecimalAnimationUsingKeyFrames.cs
- TextDecorationLocationValidation.cs
- SubtreeProcessor.cs
- SiteMapNodeItemEventArgs.cs
- Connector.xaml.cs
- RoutedEventValueSerializer.cs
- PeerTransportListenAddressValidatorAttribute.cs
- Error.cs
- FormCollection.cs
- CharConverter.cs
- ServiceProviders.cs
- BufferedOutputStream.cs
- InstanceHandleConflictException.cs
- CheckBoxFlatAdapter.cs
- ConnectionsZone.cs
- HashMembershipCondition.cs
- StrokeCollectionConverter.cs
- HtmlValidatorAdapter.cs
- ToolStripDropDownDesigner.cs
- HtmlFormWrapper.cs
- _FtpDataStream.cs
- RowCache.cs
- ViewBase.cs
- DataGridClipboardHelper.cs
- HMACSHA512.cs
- DesignerRegion.cs
- PopupControlService.cs
- RootBrowserWindowProxy.cs
- WebConfigurationManager.cs
- PipelineModuleStepContainer.cs
- SqlDataSourceCommandEventArgs.cs
- DataFormats.cs
- AnnotationStore.cs
- XmlEncodedRawTextWriter.cs
- SecurityImpersonationBehavior.cs
- DrawToolTipEventArgs.cs
- OleDbEnumerator.cs
- Pick.cs
- ObjectQuery_EntitySqlExtensions.cs
- SerializationInfoEnumerator.cs
- ChannelCacheDefaults.cs
- ExpressionReplacer.cs
- EncodingInfo.cs
- SafeFreeMibTable.cs
- EUCJPEncoding.cs
- MarkupExtensionReturnTypeAttribute.cs
- Panel.cs
- WebPartHelpVerb.cs
- TableLayoutRowStyleCollection.cs
- BaseTemplateParser.cs
- X509RawDataKeyIdentifierClause.cs
- UriExt.cs
- DataRowCollection.cs
- XmlNodeChangedEventManager.cs
- XPathConvert.cs
- ListViewGroupCollectionEditor.cs
- OleDbCommand.cs
- ListViewItem.cs
- ContextMenu.cs
- ItemCheckedEvent.cs
- ModuleBuilderData.cs
- PrivilegedConfigurationManager.cs
- FixedSOMTable.cs
- Soap.cs
- OutputCacheSettings.cs
- BrowserInteropHelper.cs
- DataTemplateKey.cs
- glyphs.cs
- CTreeGenerator.cs
- Model3DGroup.cs
- ArgIterator.cs
- ChooseAction.cs
- DbProviderFactoriesConfigurationHandler.cs
- TextureBrush.cs