Merge pull request #2400 from esdrubal/extrahead
authorMarcos Henrich <marcoshenrich@gmail.com>
Mon, 15 Feb 2016 12:21:29 +0000 (12:21 +0000)
committerMarcos Henrich <marcoshenrich@gmail.com>
Mon, 15 Feb 2016 12:21:29 +0000 (12:21 +0000)
[System] Fix extra head in config bug.

mcs/class/System.Configuration/System.Configuration/Configuration.cs
mcs/class/System.Configuration/Test/System.Configuration/ConfigurationManagerTest.cs
mcs/class/System/System.Configuration/CustomizableFileSettingsProvider.cs
mcs/class/System/Test/System.Configuration/ApplicationSettingsBaseTest.cs

index 760371766904e216889732ba05dc9a24cc7746b3..fb48cc9664f27b743154806f992f342e7e9a8f35 100644 (file)
@@ -133,8 +133,12 @@ namespace System.Configuration {
                                rootGroup.StreamName = streamName;
                        }
                        
-                       if (streamName != null)
-                               Load ();
+                       try {
+                               if (streamName != null)
+                                       Load ();
+                       } catch (XmlException ex) {
+                               throw new ConfigurationErrorsException (ex.Message, ex, streamName, 0);
+                       }
                }
                
                internal Configuration Parent {
index d2e1a240f6d5c59621fa35c79d182eac32151c33..7efff1dddffcf879f53a0a534b24cded54d0a213 100644 (file)
@@ -627,5 +627,23 @@ namespace MonoTests.System.Configuration {
                        Assert.AreEqual ("Server=(local);Initial Catalog=someDb;User Id=someUser;Password=somePassword;Application Name=someAppName;Min Pool Size=5;Max Pool Size=500;Connect Timeout=10;Connection Lifetime=29;",
                                         connString);
                }
+
+               [Test]
+               public void BadConfig ()
+               {
+                       string xml = @" badXml";
+
+                       var file = Path.Combine (tempFolder, "badConfig.config");
+                       File.WriteAllText (file, xml);
+
+                       try {
+                               var fileMap = new ConfigurationFileMap (file);
+                               var configuration = ConfigurationManager.OpenMappedMachineConfiguration (fileMap);
+                               Assert.Fail ("Exception ConfigurationErrorsException was expected.");
+                       } catch (ConfigurationErrorsException e) {
+                               Assert.AreEqual (file, e.Filename);
+                       }
+
+               }
        }
 }
index 4b69010b975f59370e4afc85cabae0f96640dcfd..31d56ce09eb38acf77a1e3a2a9ab1466b66b1266 100644 (file)
@@ -578,6 +578,34 @@ namespace System.Configuration
                private ExeConfigurationFileMap exeMapPrev = null;
                private SettingsPropertyValueCollection values = null;
 
+               /// <remarks>
+               /// Hack to remove the XmlDeclaration that the XmlSerializer adds.
+               /// <br />
+               /// see <a href="https://github.com/mono/mono/pull/2273">Issue 2273</a> for details
+               /// </remarks>
+               private string StripXmlHeader (string serializedValue)
+               {
+                       if (serializedValue == null)
+                       {
+                               return string.Empty;
+                       }
+
+                       XmlDocument doc = new XmlDocument ();
+                       XmlElement valueXml = doc.CreateElement ("value");
+                       valueXml.InnerXml = serializedValue;
+
+                       foreach (XmlNode child in valueXml.ChildNodes) {
+                               if (child.NodeType == XmlNodeType.XmlDeclaration) {
+                                       valueXml.RemoveChild (child);
+                                       break;
+                               }
+                       }
+
+                       // InnerXml will give you well-formed XML that you could save as a separate document, and 
+                       // InnerText will immediately give you a pure-text representation of this inner XML.
+                       return valueXml.InnerXml;
+               }
+
                private void SaveProperties (ExeConfigurationFileMap exeMap, SettingsPropertyValueCollection collection, ConfigurationUserLevel level, SettingsContext context, bool checkUserLevel)
                {
                        Configuration config = ConfigurationManager.OpenMappedExeConfiguration (exeMap, level);
@@ -585,8 +613,6 @@ namespace System.Configuration
                        UserSettingsGroup userGroup = config.GetSectionGroup ("userSettings") as UserSettingsGroup;
                        bool isRoaming = (level == ConfigurationUserLevel.PerUserRoaming);
 
-#if true // my reimplementation
-
                        if (userGroup == null) {
                                userGroup = new UserSettingsGroup ();
                                config.SectionGroups.Add ("userSettings", userGroup);
@@ -623,7 +649,7 @@ namespace System.Configuration
                                        element.Value.ValueXml = new XmlDocument ().CreateElement ("value");
                                switch (value.Property.SerializeAs) {
                                case SettingsSerializeAs.Xml:
-                                       element.Value.ValueXml.InnerXml = (value.SerializedValue as string) ?? string.Empty;
+                                       element.Value.ValueXml.InnerXml = StripXmlHeader (value.SerializedValue as string);
                                        break;
                                case SettingsSerializeAs.String:
                                        element.Value.ValueXml.InnerText = value.SerializedValue as string;
@@ -637,43 +663,6 @@ namespace System.Configuration
                        }
                        if (hasChanges)
                                config.Save (ConfigurationSaveMode.Minimal, true);
-
-#else // original impl. - likely buggy to miss some properties to save
-
-                       foreach (ConfigurationSection configSection in userGroup.Sections)
-                       {
-                               ClientSettingsSection userSection = configSection as ClientSettingsSection;
-                               if (userSection != null)
-                               {
-/*
-                                       userSection.Settings.Clear();
-
-                                       foreach (SettingsPropertyValue propertyValue in collection)
-                                       {
-                                               if (propertyValue.IsDirty)
-                                               {
-                                                       SettingElement element = new SettingElement(propertyValue.Name, SettingsSerializeAs.String);
-                                                       element.Value.ValueXml = new XmlDocument();
-                                                       element.Value.ValueXml.InnerXml = (string)propertyValue.SerializedValue;
-                                                       userSection.Settings.Add(element);
-                                               }
-                                       }
-*/
-                                       foreach (SettingElement element in userSection.Settings)
-                                       {
-                                               if (collection [element.Name] != null) {
-                                                       if (collection [element.Name].Property.Attributes.Contains (typeof (SettingsManageabilityAttribute)) != isRoaming)
-                                                               continue;
-
-                                                       element.SerializeAs = SettingsSerializeAs.String;
-                                                       element.Value.ValueXml.InnerXml = (string) collection [element.Name].SerializedValue;   ///Value = XmlElement
-                                               }
-                                       }
-                               }
-                       }
-                       config.Save (ConfigurationSaveMode.Minimal, true);
-#endif
                }
 
                // NOTE: We should add here all the chars that are valid in a name of a class (Ecma-wise),
index 7b0b3ac8152a99b66953033ad54429352806d452..e12f53291d208b523a3b974f70e561018a4a9ea2 100644 (file)
 
 //#define SPEW
 
-
 using System;
+using System.IO;
+using System.Xml;
+using System.Xml.Serialization;
+using System.Xml.Schema;
 using System.Text;
 using System.Configuration;
 using System.ComponentModel;
@@ -461,6 +464,60 @@ namespace MonoTests.System.Configuration {
                        Assert.AreEqual ("eclair", holder1.TestKey, "#4");
                        Assert.AreEqual ("", holder2.TestKey, "#5");
                }
+
+               class Settings : ApplicationSettingsBase
+               {
+                       [UserScopedSetting]
+                       public WindowPositionList WindowPositions {
+                               get {
+                                       return ((WindowPositionList)(this ["WindowPositions"]));
+                               }
+                               set {
+                                       this ["WindowPositions"] = value;
+                               }
+                       }
+               }
+
+               [Serializable]
+               public class WindowPositionList : IXmlSerializable
+               {
+                       public XmlSchema GetSchema ()
+                       {
+                               return null;
+                       }
+
+                       public void ReadXml (XmlReader reader)
+                       {
+                               reader.ReadStartElement ("sampleNode");
+                               reader.ReadEndElement ();
+                       }
+
+                       public void WriteXml (XmlWriter writer)
+                       {
+                               writer.WriteStartElement ("sampleNode");
+                               writer.WriteEndElement ();
+                       }
+               }
+
+               [Test] //Covers 36388
+               public void XmlHeader ()
+               {
+                       try {
+                               var settings = new Settings ();
+                               settings.Reset ();
+                               settings.Save ();
+
+                               settings.WindowPositions = new WindowPositionList ();
+
+                               settings.Save ();
+                               // If Reloads fails then saved data is corrupted
+                               settings.Reload ();
+                       } catch (ConfigurationErrorsException e) {
+                               // Delete corrupted config file so other test won't fail.
+                               File.Delete (e.Filename);
+                               Assert.Fail ("Invalid data was saved to config file.");
+                       }
+               }
        }
 }