Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Sys / System / Configuration / LocalFileSettingsProvider.cs / 1305376 / 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
- smtpconnection.cs
- WindowsSpinner.cs
- TextDecorationLocationValidation.cs
- AmbientProperties.cs
- BitmapDecoder.cs
- RegexReplacement.cs
- DynamicResourceExtension.cs
- updatecommandorderer.cs
- Binding.cs
- MenuCommandService.cs
- PhysicalOps.cs
- CounterSample.cs
- FontCollection.cs
- Vector3DCollection.cs
- Activator.cs
- DesignerForm.cs
- SiteMap.cs
- ListViewItem.cs
- SharedConnectionWorkflowTransactionService.cs
- MetadataElement.cs
- _UriSyntax.cs
- DesignRelation.cs
- ExponentialEase.cs
- RubberbandSelector.cs
- ValidatingReaderNodeData.cs
- Int32KeyFrameCollection.cs
- __ComObject.cs
- TextTrailingWordEllipsis.cs
- PageHandlerFactory.cs
- RowVisual.cs
- ConfigDefinitionUpdates.cs
- ResourceSetExpression.cs
- PageStatePersister.cs
- EditableRegion.cs
- JapaneseLunisolarCalendar.cs
- serverconfig.cs
- FormatException.cs
- ActivityInfo.cs
- FormViewUpdateEventArgs.cs
- WorkflowServiceNamespace.cs
- TypeExtension.cs
- ParentUndoUnit.cs
- BlockUIContainer.cs
- ProcessHostServerConfig.cs
- Glyph.cs
- ProfileProvider.cs
- IsolatedStorageException.cs
- DataServiceQueryOfT.cs
- RSACryptoServiceProvider.cs
- AuthorizationRule.cs
- StateBag.cs
- ResolveDuplexCD1AsyncResult.cs
- ISessionStateStore.cs
- DataGridViewToolTip.cs
- BoolExpression.cs
- MsmqHostedTransportConfiguration.cs
- Currency.cs
- PauseStoryboard.cs
- CodeCommentStatement.cs
- Stream.cs
- SecureStringHasher.cs
- Buffer.cs
- ConfigXmlDocument.cs
- CalendarDayButton.cs
- EmptyStringExpandableObjectConverter.cs
- DataGridViewColumnStateChangedEventArgs.cs
- DatagridviewDisplayedBandsData.cs
- HwndSourceKeyboardInputSite.cs
- SmtpReplyReaderFactory.cs
- PrinterResolution.cs
- FormsAuthenticationEventArgs.cs
- DataTableReader.cs
- PropertyValueChangedEvent.cs
- Typography.cs
- ToggleProviderWrapper.cs
- DocumentOutline.cs
- ConnectionManagementSection.cs
- MSAAWinEventWrap.cs
- ApplicationTrust.cs
- CachedCompositeFamily.cs
- ButtonStandardAdapter.cs
- TextSelectionHelper.cs
- SolidColorBrush.cs
- TableStyle.cs
- MsmqAppDomainProtocolHandler.cs
- HttpConfigurationSystem.cs
- SurrogateEncoder.cs
- CheckBoxList.cs
- UnmanagedBitmapWrapper.cs
- TextPointerBase.cs
- Screen.cs
- TextTreePropertyUndoUnit.cs
- EntityObject.cs
- NetCodeGroup.cs
- TrackBar.cs
- StrokeFIndices.cs
- RegexBoyerMoore.cs
- ConfigXmlAttribute.cs
- KnownAssemblyEntry.cs
- TextEndOfLine.cs