// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_2_0 && CONFIGURATION_DEP
+#if CONFIGURATION_DEP
#if !TARGET_JVM
extern alias PrebuiltSystem;
internal class CustomizableFileSettingsProvider : SettingsProvider, IApplicationSettingsProvider
{
+ // KLUDGE WARNING.
+ //
+ // This is used from within System.Web to allow mapping of the ExeConfigFilename to
+ // the correct Web.config for the current request. Otherwise web applications will
+ // not be able to access settings from Web.config. The type assigned to this
+ // variable must descend from the ConfigurationFileMap class and its
+ // MachineConfigFilename will be used to set the ExeConfigFilename.
+ //
+ // This is necessary to fix bug #491531
+#pragma warning disable 649
+ private static Type webConfigurationFileMapType;
+#pragma warning restore 649
+
private static string userRoamingPath = "";
private static string userLocalPath = "";
private static string userRoamingPathPrevVersion = "";
assembly = Assembly.GetCallingAssembly ();
#if !TARGET_JVM
-
byte [] pkt = assembly.GetName ().GetPublicKeyToken ();
return String.Format ("{0}_{1}_{2}",
AppDomain.CurrentDomain.FriendlyName,
- pkt != null ? "StrongName" : "Url",
+ pkt != null && pkt.Length > 0 ? "StrongName" : "Url",
GetEvidenceHash());
-
#else // AssemblyProductAttribute-based code
AssemblyProductAttribute [] attrs = (AssemblyProductAttribute[]) assembly.GetCustomAttributes (typeof (AssemblyProductAttribute), true);
#endif
}
- // FIXME: it seems that something else is used
- // here, to convert hash bytes to string.
+ // Note: Changed from base64() to hex output to avoid unexpected chars like '\' or '/' with filesystem meaning.
+ // Otherwise eventually filenames, which are invalid on linux or windows, might be created.
+ // Signed-off-by: Carsten Schlote <schlote@vahanus.net>
+ // TODO: Compare with .NET. It might be also, that their way isn't suitable for Unix OS derivates (slahes in output)
private static string GetEvidenceHash ()
{
Assembly assembly = Assembly.GetEntryAssembly ();
assembly = Assembly.GetCallingAssembly ();
byte [] pkt = assembly.GetName ().GetPublicKeyToken ();
- byte [] hash = SHA1.Create ().ComputeHash (pkt != null ? pkt : Encoding.UTF8.GetBytes (assembly.EscapedCodeBase));
-
- return Convert.ToBase64String (hash);
+ byte [] hash = SHA1.Create ().ComputeHash (pkt != null && pkt.Length >0 ? pkt : Encoding.UTF8.GetBytes (assembly.EscapedCodeBase));
+ System.Text.StringBuilder evidence_string = new System.Text.StringBuilder();
+ foreach (byte b in hash)
+ evidence_string.AppendFormat("{0:x2}",b);
+ return evidence_string.ToString ();
}
private static string GetProductVersion ()
if (userGroup == null) {
userGroup = new UserSettingsGroup ();
config.SectionGroups.Add ("userSettings", userGroup);
- ApplicationSettingsBase asb = context.CurrentSettings;
- ClientSettingsSection cs = new ClientSettingsSection ();
- userGroup.Sections.Add ((asb != null ? asb.GetType () : typeof (ApplicationSettingsBase)).FullName, cs);
+ }
+ ApplicationSettingsBase asb = context.CurrentSettings;
+ string class_name = NormalizeInvalidXmlChars ((asb != null ? asb.GetType () : typeof (ApplicationSettingsBase)).FullName);
+ ClientSettingsSection userSection = null;
+ ConfigurationSection cnf = userGroup.Sections.Get (class_name);
+ userSection = cnf as ClientSettingsSection;
+ if (userSection == null) {
+ userSection = new ClientSettingsSection ();
+ userGroup.Sections.Add (class_name, userSection);
}
bool hasChanges = false;
- foreach (ConfigurationSection section in userGroup.Sections) {
- ClientSettingsSection userSection = section as ClientSettingsSection;
- if (userSection == null)
+ if (userSection == null)
+ return;
+
+ foreach (SettingsPropertyValue value in collection) {
+ if (checkUserLevel && value.Property.Attributes.Contains (typeof (SettingsManageabilityAttribute)) != isRoaming)
+ continue;
+ // The default impl does not save the ApplicationScopedSetting properties
+ if (value.Property.Attributes.Contains (typeof (ApplicationScopedSettingAttribute)))
continue;
- foreach (SettingsPropertyValue value in collection) {
- if (checkUserLevel && value.Property.Attributes.Contains (typeof (SettingsManageabilityAttribute)) != isRoaming)
- continue;
- hasChanges = true;
- SettingElement element = userSection.Settings.Get (value.Name);
- if (element == null) {
- element = new SettingElement (value.Name, value.Property.SerializeAs);
- userSection.Settings.Add (element);
- }
- if (element.Value.ValueXml == null)
- element.Value.ValueXml = new XmlDocument ().CreateDocumentFragment ();
- switch (value.Property.SerializeAs) {
- case SettingsSerializeAs.Xml:
- element.Value.ValueXml.InnerXml = value.SerializedValue as string;
- break;
- case SettingsSerializeAs.String:
- element.Value.ValueXml.InnerText = value.SerializedValue as string;
- break;
- case SettingsSerializeAs.Binary:
- element.Value.ValueXml.InnerText = Convert.ToBase64String (value.SerializedValue as byte []);
- break;
- default:
- throw new NotImplementedException ();
- }
+ hasChanges = true;
+ SettingElement element = userSection.Settings.Get (value.Name);
+ if (element == null) {
+ element = new SettingElement (value.Name, value.Property.SerializeAs);
+ userSection.Settings.Add (element);
+ }
+ if (element.Value.ValueXml == null)
+ element.Value.ValueXml = new XmlDocument ().CreateElement ("value");
+ switch (value.Property.SerializeAs) {
+ case SettingsSerializeAs.Xml:
+ element.Value.ValueXml.InnerXml = (value.SerializedValue as string) ?? string.Empty;
+ break;
+ case SettingsSerializeAs.String:
+ element.Value.ValueXml.InnerText = value.SerializedValue as string;
+ break;
+ case SettingsSerializeAs.Binary:
+ element.Value.ValueXml.InnerText = value.SerializedValue != null ? Convert.ToBase64String (value.SerializedValue as byte []) : string.Empty;
+ break;
+ default:
+ throw new NotImplementedException ();
}
}
if (hasChanges)
#endif
}
+ // NOTE: We should add here all the chars that are valid in a name of a class (Ecma-wise),
+ // but invalid in an xml element name, and provide a better impl if we get too many of them.
+ string NormalizeInvalidXmlChars (string str)
+ {
+ char [] invalid_chars = new char [] { '+' };
+
+ if (str == null || str.IndexOfAny (invalid_chars) == -1)
+ return str;
+
+ // Replace with its hexadecimal values.
+ str = str.Replace ("+", "_x002B_");
+ return str;
+ }
+
private void LoadPropertyValue (SettingsPropertyCollection collection, SettingElement element, bool allowOverwrite)
{
SettingsProperty prop = collection [element.Name];
SettingsPropertyValue value = new SettingsPropertyValue (prop);
value.IsDirty = false;
- value.SerializedValue = element.Value.ValueXml != null ? element.Value.ValueXml.InnerText : prop.DefaultValue;
+ if (element.Value.ValueXml != null) {
+ switch (value.Property.SerializeAs) {
+ case SettingsSerializeAs.Xml:
+ value.SerializedValue = element.Value.ValueXml.InnerXml;
+ break;
+ case SettingsSerializeAs.String:
+ value.SerializedValue = element.Value.ValueXml.InnerText;
+ break;
+ case SettingsSerializeAs.Binary:
+ value.SerializedValue = Convert.FromBase64String (element.Value.ValueXml.InnerText);
+ break;
+ }
+ }
+ else
+ value.SerializedValue = prop.DefaultValue;
try
{
if (allowOverwrite)
{
CreateExeMap ();
- if (values == null) {
- values = new SettingsPropertyValueCollection ();
- string groupName = context ["GroupName"] as string;
- LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.None, "applicationSettings", false, groupName);
- LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.None, "userSettings", false, groupName);
+ values = new SettingsPropertyValueCollection ();
+ string groupName = context ["GroupName"] as string;
+ groupName = NormalizeInvalidXmlChars (groupName); // we likely saved the element removing the non valid xml chars.
+ LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.None, "applicationSettings", false, groupName);
+ LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.None, "userSettings", false, groupName);
- LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoaming, "userSettings", true, groupName);
- LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoamingAndLocal, "userSettings", true, groupName);
+ LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoaming, "userSettings", true, groupName);
+ LoadProperties (exeMapCurrent, collection, ConfigurationUserLevel.PerUserRoamingAndLocal, "userSettings", true, groupName);
- // create default values if not exist
- foreach (SettingsProperty p in collection)
- if (values [p.Name] == null)
- values.Add (new SettingsPropertyValue (p));
- }
+ // create default values if not exist
+ foreach (SettingsProperty p in collection)
+ if (values [p.Name] == null)
+ values.Add (new SettingsPropertyValue (p));
return values;
}
// current version
exeMapCurrent = new ExeConfigurationFileMap ();
+
// exeMapCurrent.ExeConfigFilename = System.Windows.Forms.Application.ExecutablePath + ".config";
Assembly entry = Assembly.GetEntryAssembly () ?? Assembly.GetExecutingAssembly ();
exeMapCurrent.ExeConfigFilename = entry.Location + ".config";
exeMapCurrent.LocalUserConfigFilename = UserLocalFullPath;
exeMapCurrent.RoamingUserConfigFilename = UserRoamingFullPath;
+ if (webConfigurationFileMapType != null && typeof (ConfigurationFileMap).IsAssignableFrom (webConfigurationFileMapType)) {
+ try {
+ ConfigurationFileMap cfgFileMap = Activator.CreateInstance (webConfigurationFileMapType) as ConfigurationFileMap;
+ if (cfgFileMap != null) {
+ string fpath = cfgFileMap.MachineConfigFilename;
+ if (!String.IsNullOrEmpty (fpath))
+ exeMapCurrent.ExeConfigFilename = fpath;
+ }
+ } catch {
+ // ignore
+ }
+ }
+
// previous version
if ((PrevUserLocalFullPath != "") && (PrevUserRoamingFullPath != ""))
{
public void Reset (SettingsContext context)
{
- CreateExeMap ();
- foreach (SettingsPropertyValue propertyValue in values) {
- propertyValue.PropertyValue = propertyValue.Property.DefaultValue;
- propertyValue.IsDirty = true;
+ SettingsPropertyCollection coll = new SettingsPropertyCollection ();
+ // GetPropertyValues (context, coll);
+ if (values != null) {
+ foreach (SettingsPropertyValue propertyValue in values) {
+ // Can't use propertyValue.Property.DefaultValue
+ // as it may cause InvalidCastException (see bug# 532180)
+ values[propertyValue.Name].PropertyValue = propertyValue.Reset ();
+ }
}
- SetPropertyValues (context, values);
}
// FIXME: implement