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
- TraceContext.cs
- MatrixAnimationBase.cs
- DataControlPagerLinkButton.cs
- SqlWriter.cs
- ButtonBaseAutomationPeer.cs
- ZoneLinkButton.cs
- errorpatternmatcher.cs
- BrowserCapabilitiesCompiler.cs
- XmlSchemaValidationException.cs
- TreeNodeConverter.cs
- Itemizer.cs
- GridErrorDlg.cs
- RootBuilder.cs
- _NegoState.cs
- DrawingBrush.cs
- UInt64Storage.cs
- FastPropertyAccessor.cs
- ExcludePathInfo.cs
- ThreadStaticAttribute.cs
- QilDataSource.cs
- WebBrowserDocumentCompletedEventHandler.cs
- SizeAnimation.cs
- FixedFlowMap.cs
- LineVisual.cs
- DataBindingExpressionBuilder.cs
- SByte.cs
- ComplexPropertyEntry.cs
- PseudoWebRequest.cs
- EditingCoordinator.cs
- DetailsViewPagerRow.cs
- SymmetricKeyWrap.cs
- ZipIOBlockManager.cs
- LongValidatorAttribute.cs
- UndoEngine.cs
- RelatedImageListAttribute.cs
- CodeGroup.cs
- TCEAdapterGenerator.cs
- InheritanceRules.cs
- FtpWebRequest.cs
- TextTreeExtractElementUndoUnit.cs
- XsdBuildProvider.cs
- FixedDSBuilder.cs
- ToggleButton.cs
- MaskedTextBox.cs
- XmlEnumAttribute.cs
- MD5Cng.cs
- Maps.cs
- CornerRadius.cs
- CommonXSendMessage.cs
- ReliableChannelBinder.cs
- Brush.cs
- SettingsBindableAttribute.cs
- Number.cs
- SqlMethodCallConverter.cs
- PropertyItem.cs
- KeyProperty.cs
- SqlVersion.cs
- ClientBuildManagerCallback.cs
- IncrementalHitTester.cs
- XmlSchemaCollection.cs
- AesCryptoServiceProvider.cs
- precedingquery.cs
- ValidationErrorEventArgs.cs
- SqlConnectionPoolGroupProviderInfo.cs
- DesignerAdRotatorAdapter.cs
- StorageEntitySetMapping.cs
- PropertyDescriptorGridEntry.cs
- SqlConnectionHelper.cs
- PkcsMisc.cs
- OleDbEnumerator.cs
- RegisteredDisposeScript.cs
- SafeArrayRankMismatchException.cs
- TrailingSpaceComparer.cs
- TrackingProfileCache.cs
- RectKeyFrameCollection.cs
- DockingAttribute.cs
- CommandConverter.cs
- ValueType.cs
- MethodBody.cs
- KeyBinding.cs
- XmlStreamStore.cs
- FrameworkContentElement.cs
- SignedPkcs7.cs
- InputReport.cs
- NTAccount.cs
- ResetableIterator.cs
- DayRenderEvent.cs
- DatePickerDateValidationErrorEventArgs.cs
- WeakEventTable.cs
- LinkButton.cs
- Transform3D.cs
- HttpCookiesSection.cs
- ProfileSettingsCollection.cs
- NamespaceInfo.cs
- SmtpReplyReader.cs
- DispatcherProcessingDisabled.cs
- CategoriesDocument.cs
- ColumnMapCopier.cs
- QueueProcessor.cs
- ToggleProviderWrapper.cs