//******************************************************************************************************// CategorizedSettingsElement.cs - Gbtc//// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.//// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See// the NOTICE file distributed with this work for additional information regarding copyright ownership.// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may// not use this file except in compliance with the License. You may obtain a copy of the License at://// http://www.opensource.org/licenses/MIT//// Unless agreed to in writing, the subject software distributed under the License is distributed on an// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the// License for the specific language governing permissions and limitations.//// Code Modification History:// ----------------------------------------------------------------------------------------------------// 04/11/2006 - Pinal C. Patel// Generated original version of source code.// 05/25/2006 - J. Ritchie Carroll// Added Try/Catch safety wrapper around GetTypedValue implementation.// 06/01/2006 - J. Ritchie Carroll// Added GetTypedValue overload to handle boolean types as a special case.// 08/17/2007 - Darrell Zuercher// Edited code comments.// 09/17/2008 - Pinal C. Patel// Converted code to C#.// 09/22/2008 - J. Ritchie Carroll// Made boolean types a special case (i.e., using ParseBoolean extension).// 09/29/2008 - Pinal C. Patel// Reviewed code comments.// 09/14/2009 - Stephen C. Wills// Added new header and license agreement.// 04/15/2010 - Pinal C. Patel// Modified property setters to update the internal property bag only if values have changed.// 04/20/2010 - Pinal C. Patel// Added new Category property for the purpose of managing user scope setting.// Removed publicly accessible constructors for manageability.// Added Scope property as a way of identifying user scope settings.// 04/21/2010 - Pinal C. Patel// Removed unnecessary overloads of Update() for manageability.// 04/22/2010 - Pinal C. Patel// Fixed encryption related bug introduced when adding support for user scope settings.// 12/05/2010 - Pinal C. Patel// Modified Update() and ValueAs() to specify CultureInfo for the conversion.// 01/11/2011 - Pinal C. Patel// Added support for use of Eval() in Value to reference other setting values and static members// of .NET types.// 12/14/2012 - Starlynn Danyelle Gilliam// Modified Header,////****************************************************************************************************** using System;using System.Configuration;using System.Reflection;using System.Text.RegularExpressions;using GSF.Security.Cryptography; namespace GSF.Configuration{ #region [ Enumerations ] /// <summary> /// Specifies the scope of a setting represented by <see cref="CategorizedSettingsElement"/>. /// </summary> public enum SettingScope { /// <summary> /// Settings is intended for user specific use. /// </summary> User, /// <summary> /// Settings is intended for application wide use. /// </summary> Application } #endregion /// <summary> /// Represents a settings entry in the config file. /// </summary> public class CategorizedSettingsElement : ConfigurationElement { #region [ Members ] // Constants /// <summary> /// Specifies the default value for the <see cref="Value"/> property. /// </summary> public const string DefaultValue = ""; /// <summary> /// Specifies the default value for the <see cref="Description"/> property. /// </summary> public const string DefaultDescription = ""; /// <summary> /// Specifies the default value for the <see cref="Encrypted"/> property. /// </summary> public const bool DefaultEncrypted = false; /// <summary> /// Specifies the default value for the <see cref="Scope"/> property. /// </summary> public const SettingScope DefaultScope = SettingScope.Application; private const string DefaultCryptoKey = "0679d9ae-aca5-4702-a3f5-604415096987"; private const string EvalRegex = @"Eval\((?<Container>(?<Accessor>[\w\d]+\.?)+)\.(?<Target>[\w\d]+)\)"; // Fields private string m_cryptoKey; private CategorizedSettingsElementCollection m_category; #endregion #region [ Constructors ] /// <summary> /// Required by the configuration API and is for internal use only. /// </summary> internal CategorizedSettingsElement(CategorizedSettingsElementCollection category) : this(category, "") { } /// <summary> /// Required by the configuration API and is for internal use only. /// </summary> internal CategorizedSettingsElement(CategorizedSettingsElementCollection category, string name) { m_category = category; this.Name = name; m_cryptoKey = DefaultCryptoKey; } #endregion #region [ Properties ] /// <summary> /// Gets or sets the <see cref="CategorizedSettingsElementCollection"/> to which this <see cref="CategorizedSettingsElement"/> belongs. /// </summary> public CategorizedSettingsElementCollection Category { get { return m_category; } internal set { m_category = value; } } /// <summary> /// Gets or sets the identifier of the setting. /// </summary> /// <returns>The identifier of the setting.</returns> [ConfigurationProperty("name", IsKey = true, IsRequired = true)] public string Name { get { return (string)base["name"]; } set { base["name"] = value; Modified = true; } } /// <summary> /// Gets or sets the value of the setting. /// </summary> /// <returns>The value of the setting.</returns> /// <remarks> /// <see cref="Value"/> can reference the value of another setting using <b>Eval([Section].[Setting])</b> syntax or the value of a known .NET /// type's static member (field, non-indexed property or parameterless method) using <b>Eval([Type].[Member])</b> syntax as shown in the example below: /// <code> /// <![CDATA[ /// <?xml version="1.0"?> /// <configuration> /// <configSections> /// <section name="categorizedSettings" type="GSF.Configuration.CategorizedSettingsSection, GSF.Core" /> /// </configSections> /// <categorizedSettings> /// <database> /// <add name="SettingsTable" value="dbo.Settings" description="Table that contains the settings." /// encrypted="false" /> /// <add name="AdminEmail" value="SELECT * FROM Eval(Database.SettingsTable) WHERE Name = 'AdminEmail'" /// description="Email address of the administrator." encrypted="false" /> /// <add name="AuditQuery" value="SELECT * FROM dbo.Log WHERE EntryTime < 'Eval(System.DateTime.UtcNow)'" /// description="Query for retrieving audit records." encrypted="false" /> /// </database> /// </categorizedSettings> /// </configuration> /// ]]> /// </code> /// </remarks> [ConfigurationProperty("value", IsRequired = true, DefaultValue = DefaultValue)] public string Value { get { return EvaluateValue(DecryptValue(GetRawValue())); } set { // Continue only if values are different. string currentValue; try { currentValue = DecryptValue(GetRawValue()); } catch (ConfigurationErrorsException) { // Clear value if it fails to decrypt, updating anyway currentValue = string.Empty; } if (value.ToNonNullString().Equals(currentValue)) return; // Ensure only Eval() can replace Eval(). if (Regex.IsMatch(currentValue, EvalRegex, RegexOptions.IgnoreCase) && !Regex.IsMatch(value, EvalRegex, RegexOptions.IgnoreCase)) return; value = EncryptValue(value); if (Scope == SettingScope.Application || (object)Category[Name] == null) { // Setting is application wide or is being added for the first time. base["value"] = value; Modified = true; } else { // Setting is user specific so update setting in user settings store. Category.Section.File.UserSettings.Write(Category.Name, Name, value); } } } /// <summary> /// Gets or sets the description of the setting. /// </summary> /// <returns>The description of the setting.</returns> [ConfigurationProperty("description", IsRequired = true, DefaultValue = DefaultDescription)] public string Description { get { return (string)base["description"]; } set { // Continue only if values are different. if (value.ToNonNullString().Equals(Description)) return; base["description"] = value; Modified = true; } } /// <summary> /// Gets or sets a boolean value that indicates whether the setting value is to be encrypted. /// </summary> /// <returns>true, if the setting value is to be encrypted; otherwise false.</returns> [ConfigurationProperty("encrypted", IsRequired = true, DefaultValue = DefaultEncrypted)] public bool Encrypted { get { return (bool)base["encrypted"]; } set { // Continue only if values are different. if (value.Equals(Encrypted)) return; base["encrypted"] = value; Modified = true; } } /// <summary> /// Gets or sets the <see cref="SettingScope"/>. /// </summary> [ConfigurationProperty("scope", IsRequired = false, DefaultValue = DefaultScope)] public SettingScope Scope { get { return (SettingScope)base["scope"]; } set { // Continue only if values are different. if (value.Equals(Scope)) return; base["scope"] = value; Modified = true; } } /// <summary> /// Gets value that will actually be serialized to the configuration file. /// </summary> public string SerializedValue { get { return EncryptValue((string)base["value"]); } } internal bool Modified { set { if ((object)m_category != null) m_category.Modified = value; } } #endregion #region [ Methods ] /// <summary> /// Sets the key to be used for encrypting and decrypting the <see cref="Value"/>. /// </summary> /// <param name="cryptoKey">New crypto key.</param> public void SetCryptoKey(string cryptoKey) { if (!string.IsNullOrEmpty(cryptoKey)) { // Re-encrypt the existing value with the new key. This is done because the value gets encrypted, // if specified, with the default crypto key when the value is set during instantiation. string decryptedValue; try { decryptedValue = Value; } catch (ConfigurationErrorsException) { // Clear value if it fails to decrypt decryptedValue = string.Empty; } m_cryptoKey = cryptoKey; Value = decryptedValue; Modified = true; } } /// <summary> /// Updates setting information. /// </summary> /// <param name="value">New setting value.</param> public void Update(object value) { Update(value, Description, Encrypted, Scope); } /// <summary> /// Updates setting information. /// </summary> /// <param name="value">New setting value.</param> /// <param name="description">New setting description.</param> public void Update(object value, string description) { Update(value, description, Encrypted, Scope); } /// <summary> /// Updates setting information. /// </summary> /// <param name="value">New setting value.</param> /// <param name="description">New setting description.</param> /// <param name="encrypted">A boolean value that indicated whether the new setting value is to be encrypted.</param> public void Update(object value, string description, bool encrypted) { Update(value, description, encrypted, Scope); } /// <summary> /// Updates setting information. /// </summary> /// <param name="value">New setting value.</param> /// <param name="description">New setting description.</param> /// <param name="encrypted">A boolean value that indicated whether the new setting value is to be encrypted.</param> /// <param name="scope">One of the <see cref="SettingScope"/> values.</param> public void Update(object value, string description, bool encrypted, SettingScope scope) { this.Scope = scope; this.Encrypted = encrypted; this.Value = Common.TypeConvertToString(value, m_category.Section.File.Culture); this.Description = description; } /// <summary> /// Gets the setting value as the specified type. /// </summary> /// <typeparam name="T">Type to which the setting value is to be converted.</typeparam> /// <returns>The type-coerced value of the setting.</returns> /// <remarks> /// If this function fails to properly coerce value to specified type, the default value is returned. /// </remarks> public T ValueAs<T>() { return this.ValueAs(default(T)); } /// <summary> /// Gets the setting value as the specified type. /// </summary> /// <typeparam name="T">Type to which the setting value is to be converted.</typeparam> /// <param name="defaultValue">The default value to return if the setting value is empty.</param> /// <returns>The type-coerced value of the setting.</returns> /// <remarks> /// If this function fails to properly coerce value to specified type, the default value is returned. /// </remarks> public T ValueAs<T>(T defaultValue) { try { string value = Value; // Value is an empty string - use default value. if (string.IsNullOrEmpty(value)) return defaultValue; return value.ConvertToType<T>(null, m_category.Section.File.Culture); } catch { // Conversion to target type failed so use the default value. return defaultValue; } } /// <summary> /// Gets the setting value as a string. /// </summary> /// <returns>Value as string.</returns> public string ValueAsString() { return ValueAsString(string.Empty); } /// <summary> /// Gets the setting value as a string. /// </summary> /// <param name="defaultValue">The default value to return if the setting value is empty.</param> /// <returns>Value as string.</returns> public string ValueAsString(string defaultValue) { return ValueAs(defaultValue); } /// <summary> /// Gets the setting value as a boolean. /// </summary> /// <returns>Value as boolean.</returns> public bool ValueAsBoolean() { return ValueAsBoolean(default(bool)); } /// <summary> /// Gets the setting value as a boolean. /// </summary> /// <param name="defaultValue">The default value to return if the setting value is empty.</param> /// <returns>Value as boolean.</returns> public bool ValueAsBoolean(bool defaultValue) { try { string value = Value; // Value is an empty string - use default value. if (string.IsNullOrEmpty(value)) return defaultValue; // Value is not empty string - convert to boolean. return value.ParseBoolean(); } catchLines 1–500 of 851. Load more
//****************************************************************************************************** // CategorizedSettingsElement.cs - Gbtc // // Copyright © 2012, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 04/11/2006 - Pinal C. Patel // Generated original version of source code. // 05/25/2006 - J. Ritchie Carroll // Added Try/Catch safety wrapper around GetTypedValue implementation. // 06/01/2006 - J. Ritchie Carroll // Added GetTypedValue overload to handle boolean types as a special case. // 08/17/2007 - Darrell Zuercher // Edited code comments. // 09/17/2008 - Pinal C. Patel // Converted code to C#. // 09/22/2008 - J. Ritchie Carroll // Made boolean types a special case (i.e., using ParseBoolean extension). // 09/29/2008 - Pinal C. Patel // Reviewed code comments. // 09/14/2009 - Stephen C. Wills // Added new header and license agreement. // 04/15/2010 - Pinal C. Patel // Modified property setters to update the internal property bag only if values have changed. // 04/20/2010 - Pinal C. Patel // Added new Category property for the purpose of managing user scope setting. // Removed publicly accessible constructors for manageability. // Added Scope property as a way of identifying user scope settings. // 04/21/2010 - Pinal C. Patel // Removed unnecessary overloads of Update() for manageability. // 04/22/2010 - Pinal C. Patel // Fixed encryption related bug introduced when adding support for user scope settings. // 12/05/2010 - Pinal C. Patel // Modified Update() and ValueAs() to specify CultureInfo for the conversion. // 01/11/2011 - Pinal C. Patel // Added support for use of Eval() in Value to reference other setting values and static members // of .NET types. // 12/14/2012 - Starlynn Danyelle Gilliam // Modified Header, // //****************************************************************************************************** using System; using System.Configuration; using System.Reflection; using System.Text.RegularExpressions; using GSF.Security.Cryptography; namespace GSF.Configuration { #region [ Enumerations ] /// <summary> /// Specifies the scope of a setting represented by <see cref="CategorizedSettingsElement"/>. /// </summary> public enum SettingScope { /// <summary> /// Settings is intended for user specific use. /// </summary> User, /// <summary> /// Settings is intended for application wide use. /// </summary> Application } #endregion /// <summary> /// Represents a settings entry in the config file. /// </summary> public class CategorizedSettingsElement : ConfigurationElement { #region [ Members ] // Constants /// <summary> /// Specifies the default value for the <see cref="Value"/> property. /// </summary> public const string DefaultValue = ""; /// <summary> /// Specifies the default value for the <see cref="Description"/> property. /// </summary> public const string DefaultDescription = ""; /// <summary> /// Specifies the default value for the <see cref="Encrypted"/> property. /// </summary> public const bool DefaultEncrypted = false; /// <summary> /// Specifies the default value for the <see cref="Scope"/> property. /// </summary> public const SettingScope DefaultScope = SettingScope.Application; private const string DefaultCryptoKey = "0679d9ae-aca5-4702-a3f5-604415096987"; private const string EvalRegex = @"Eval\((?<Container>(?<Accessor>[\w\d]+\.?)+)\.(?<Target>[\w\d]+)\)"; // Fields private string m_cryptoKey; private CategorizedSettingsElementCollection m_category; #endregion #region [ Constructors ] /// <summary> /// Required by the configuration API and is for internal use only. /// </summary> internal CategorizedSettingsElement(CategorizedSettingsElementCollection category) : this(category, "") { } /// <summary> /// Required by the configuration API and is for internal use only. /// </summary> internal CategorizedSettingsElement(CategorizedSettingsElementCollection category, string name) { m_category = category; this.Name = name; m_cryptoKey = DefaultCryptoKey; } #endregion #region [ Properties ] /// <summary> /// Gets or sets the <see cref="CategorizedSettingsElementCollection"/> to which this <see cref="CategorizedSettingsElement"/> belongs. /// </summary> public CategorizedSettingsElementCollection Category { get { return m_category; } internal set { m_category = value; } } /// <summary> /// Gets or sets the identifier of the setting. /// </summary> /// <returns>The identifier of the setting.</returns> [ConfigurationProperty("name", IsKey = true, IsRequired = true)] public string Name { get { return (string)base["name"]; } set { base["name"] = value; Modified = true; } } /// <summary> /// Gets or sets the value of the setting. /// </summary> /// <returns>The value of the setting.</returns> /// <remarks> /// <see cref="Value"/> can reference the value of another setting using <b>Eval([Section].[Setting])</b> syntax or the value of a known .NET /// type's static member (field, non-indexed property or parameterless method) using <b>Eval([Type].[Member])</b> syntax as shown in the example below: /// <code> /// <![CDATA[ /// <?xml version="1.0"?> /// <configuration> /// <configSections> /// <section name="categorizedSettings" type="GSF.Configuration.CategorizedSettingsSection, GSF.Core" /> /// </configSections> /// <categorizedSettings> /// <database> /// <add name="SettingsTable" value="dbo.Settings" description="Table that contains the settings." /// encrypted="false" /> /// <add name="AdminEmail" value="SELECT * FROM Eval(Database.SettingsTable) WHERE Name = 'AdminEmail'" /// description="Email address of the administrator." encrypted="false" /> /// <add name="AuditQuery" value="SELECT * FROM dbo.Log WHERE EntryTime < 'Eval(System.DateTime.UtcNow)'" /// description="Query for retrieving audit records." encrypted="false" /> /// </database> /// </categorizedSettings> /// </configuration> /// ]]> /// </code> /// </remarks> [ConfigurationProperty("value", IsRequired = true, DefaultValue = DefaultValue)] public string Value { get { return EvaluateValue(DecryptValue(GetRawValue())); } set { // Continue only if values are different. string currentValue; try { currentValue = DecryptValue(GetRawValue()); } catch (ConfigurationErrorsException) { // Clear value if it fails to decrypt, updating anyway currentValue = string.Empty; } if (value.ToNonNullString().Equals(currentValue)) return; // Ensure only Eval() can replace Eval(). if (Regex.IsMatch(currentValue, EvalRegex, RegexOptions.IgnoreCase) && !Regex.IsMatch(value, EvalRegex, RegexOptions.IgnoreCase)) return; value = EncryptValue(value); if (Scope == SettingScope.Application || (object)Category[Name] == null) { // Setting is application wide or is being added for the first time. base["value"] = value; Modified = true; } else { // Setting is user specific so update setting in user settings store. Category.Section.File.UserSettings.Write(Category.Name, Name, value); } } } /// <summary> /// Gets or sets the description of the setting. /// </summary> /// <returns>The description of the setting.</returns> [ConfigurationProperty("description", IsRequired = true, DefaultValue = DefaultDescription)] public string Description { get { return (string)base["description"]; } set { // Continue only if values are different. if (value.ToNonNullString().Equals(Description)) return; base["description"] = value; Modified = true; } } /// <summary> /// Gets or sets a boolean value that indicates whether the setting value is to be encrypted. /// </summary> /// <returns>true, if the setting value is to be encrypted; otherwise false.</returns> [ConfigurationProperty("encrypted", IsRequired = true, DefaultValue = DefaultEncrypted)] public bool Encrypted { get { return (bool)base["encrypted"]; } set { // Continue only if values are different. if (value.Equals(Encrypted)) return; base["encrypted"] = value; Modified = true; } } /// <summary> /// Gets or sets the <see cref="SettingScope"/>. /// </summary> [ConfigurationProperty("scope", IsRequired = false, DefaultValue = DefaultScope)] public SettingScope Scope { get { return (SettingScope)base["scope"]; } set { // Continue only if values are different. if (value.Equals(Scope)) return; base["scope"] = value; Modified = true; } } /// <summary> /// Gets value that will actually be serialized to the configuration file. /// </summary> public string SerializedValue { get { return EncryptValue((string)base["value"]); } } internal bool Modified { set { if ((object)m_category != null) m_category.Modified = value; } } #endregion #region [ Methods ] /// <summary> /// Sets the key to be used for encrypting and decrypting the <see cref="Value"/>. /// </summary> /// <param name="cryptoKey">New crypto key.</param> public void SetCryptoKey(string cryptoKey) { if (!string.IsNullOrEmpty(cryptoKey)) { // Re-encrypt the existing value with the new key. This is done because the value gets encrypted, // if specified, with the default crypto key when the value is set during instantiation. string decryptedValue; try { decryptedValue = Value; } catch (ConfigurationErrorsException) { // Clear value if it fails to decrypt decryptedValue = string.Empty; } m_cryptoKey = cryptoKey; Value = decryptedValue; Modified = true; } } /// <summary> /// Updates setting information. /// </summary> /// <param name="value">New setting value.</param> public void Update(object value) { Update(value, Description, Encrypted, Scope); } /// <summary> /// Updates setting information. /// </summary> /// <param name="value">New setting value.</param> /// <param name="description">New setting description.</param> public void Update(object value, string description) { Update(value, description, Encrypted, Scope); } /// <summary> /// Updates setting information. /// </summary> /// <param name="value">New setting value.</param> /// <param name="description">New setting description.</param> /// <param name="encrypted">A boolean value that indicated whether the new setting value is to be encrypted.</param> public void Update(object value, string description, bool encrypted) { Update(value, description, encrypted, Scope); } /// <summary> /// Updates setting information. /// </summary> /// <param name="value">New setting value.</param> /// <param name="description">New setting description.</param> /// <param name="encrypted">A boolean value that indicated whether the new setting value is to be encrypted.</param> /// <param name="scope">One of the <see cref="SettingScope"/> values.</param> public void Update(object value, string description, bool encrypted, SettingScope scope) { this.Scope = scope; this.Encrypted = encrypted; this.Value = Common.TypeConvertToString(value, m_category.Section.File.Culture); this.Description = description; } /// <summary> /// Gets the setting value as the specified type. /// </summary> /// <typeparam name="T">Type to which the setting value is to be converted.</typeparam> /// <returns>The type-coerced value of the setting.</returns> /// <remarks> /// If this function fails to properly coerce value to specified type, the default value is returned. /// </remarks> public T ValueAs<T>() { return this.ValueAs(default(T)); } /// <summary> /// Gets the setting value as the specified type. /// </summary> /// <typeparam name="T">Type to which the setting value is to be converted.</typeparam> /// <param name="defaultValue">The default value to return if the setting value is empty.</param> /// <returns>The type-coerced value of the setting.</returns> /// <remarks> /// If this function fails to properly coerce value to specified type, the default value is returned. /// </remarks> public T ValueAs<T>(T defaultValue) { try { string value = Value; // Value is an empty string - use default value. if (string.IsNullOrEmpty(value)) return defaultValue; return value.ConvertToType<T>(null, m_category.Section.File.Culture); } catch { // Conversion to target type failed so use the default value. return defaultValue; } } /// <summary> /// Gets the setting value as a string. /// </summary> /// <returns>Value as string.</returns> public string ValueAsString() { return ValueAsString(string.Empty); } /// <summary> /// Gets the setting value as a string. /// </summary> /// <param name="defaultValue">The default value to return if the setting value is empty.</param> /// <returns>Value as string.</returns> public string ValueAsString(string defaultValue) { return ValueAs(defaultValue); } /// <summary> /// Gets the setting value as a boolean. /// </summary> /// <returns>Value as boolean.</returns> public bool ValueAsBoolean() { return ValueAsBoolean(default(bool)); } /// <summary> /// Gets the setting value as a boolean. /// </summary> /// <param name="defaultValue">The default value to return if the setting value is empty.</param> /// <returns>Value as boolean.</returns> public bool ValueAsBoolean(bool defaultValue) { try { string value = Value; // Value is an empty string - use default value. if (string.IsNullOrEmpty(value)) return defaultValue; // Value is not empty string - convert to boolean. return value.ParseBoolean(); } catch