diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 7792a4ab0a..3de44447cb 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -646,7 +646,6 @@ - diff --git a/src/Main/Base/Project/Src/Project/Converter/PrjxToSolutionProject.cs b/src/Main/Base/Project/Src/Project/Converter/PrjxToSolutionProject.cs index afa492fed0..1de201a7af 100644 --- a/src/Main/Base/Project/Src/Project/Converter/PrjxToSolutionProject.cs +++ b/src/Main/Base/Project/Src/Project/Converter/PrjxToSolutionProject.cs @@ -236,7 +236,7 @@ namespace ICSharpCode.SharpDevelop.Project.Converter } // We have to use the stringWriter for writing because xslt.Transform doesn't use // writer.Formatting. Also, we need to remove some unwanted whitespace from the beginning. - using (MSBuildFileWriter writer = new MSBuildFileWriter(outFile, Encoding.UTF8)) { + using (XmlTextWriter writer = new XmlTextWriter(outFile, Encoding.UTF8)) { writer.Formatting = Formatting.Indented; using (XmlTextReader reader = new XmlTextReader(new StringReader(stringWriter.ToString()))) { reader.WhitespaceHandling = WhitespaceHandling.Significant; diff --git a/src/Main/Base/Project/Src/Project/Items/ProjectItem.cs b/src/Main/Base/Project/Src/Project/Items/ProjectItem.cs index 6587b9624c..14583ba15e 100644 --- a/src/Main/Base/Project/Src/Project/Items/ProjectItem.cs +++ b/src/Main/Base/Project/Src/Project/Items/ProjectItem.cs @@ -6,6 +6,8 @@ // using System; +using System.Globalization; +using System.Text; using System.IO; using System.ComponentModel; using System.Collections.Generic; @@ -138,10 +140,60 @@ namespace ICSharpCode.SharpDevelop.Project Properties); } + public static string MSBuildEscape(string text) + { + StringBuilder b = null; + for (int i = 0; i < text.Length; i++) { + char c = text[i]; + if (c == '%') { + if (b == null) b = new StringBuilder(text, 0, i, text.Length + 6); + b.Append("%25"); + } else if (c == ';') { + if (b == null) b = new StringBuilder(text, 0, i, text.Length + 6); + b.Append("%3b"); + } else { + if (b != null) { + b.Append(c); + } + } + } + if (b != null) + return b.ToString(); + else + return text; + } + + public static string MSBuildUnescape(string text) + { + StringBuilder b = null; + for (int i = 0; i < text.Length; i++) { + char c = text[i]; + if (c == '%' && i + 2 < text.Length) { + if (b == null) b = new StringBuilder(text, 0, i, text.Length + 6); + string a = text[i + 1].ToString() + text[i + 2].ToString(); + int num; + if (int.TryParse(a, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out num)) { + b.Append((char)num); + i += 2; + } else { + b.Append('%'); + } + } else { + if (b != null) { + b.Append(c); + } + } + } + if (b != null) + return b.ToString(); + else + return text; + } + public static ProjectItem ReadItem(XmlReader reader, IProject project, string itemType) { ProjectItem newItem = project != null ? project.CreateProjectItem(itemType) : ProjectItemFactory.CreateProjectItem(project, itemType); - newItem.Include = reader.GetAttribute("Include"); + newItem.Include = MSBuildUnescape(reader.GetAttribute("Include")); if (!reader.IsEmptyElement) { PropertyGroup.ReadProperties(reader, newItem.Properties, itemType); } @@ -152,12 +204,12 @@ namespace ICSharpCode.SharpDevelop.Project internal void WriteItem(XmlWriter writer) { writer.WriteStartElement(Tag); - writer.WriteAttributeString("Include", Include); - Properties.WriteProperties(writer); + writer.WriteAttributeString("Include", MSBuildEscape(Include)); + this.Properties.WriteProperties(writer); writer.WriteEndElement(); } - internal static void ReadItemGroup(XmlTextReader reader, IProject project, List items) + internal static void ReadItemGroup(XmlReader reader, IProject project, List items) { if (reader.IsEmptyElement) { return; diff --git a/src/Main/Base/Project/Src/Project/MSBuildFile.cs b/src/Main/Base/Project/Src/Project/MSBuildFile.cs deleted file mode 100644 index ec1595b99d..0000000000 --- a/src/Main/Base/Project/Src/Project/MSBuildFile.cs +++ /dev/null @@ -1,108 +0,0 @@ -// -// -// -// -// $Revision$ -// - -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.IO; -using System.Globalization; -using System.Collections.Generic; -using System.Text; -using System.Text.RegularExpressions; -using System.Xml; -using System.Xml.Xsl; -using ICSharpCode.Core; -using ICSharpCode.SharpDevelop.Internal.Templates; -using ICSharpCode.SharpDevelop.Gui; - -namespace ICSharpCode.SharpDevelop.Project -{ - // Summary: - // Represents a reader that reads MSBuild files converting the MSBuild specific escape %25 to % - public class MSBuildFileReader : XmlTextReader - { - private string Convert(string instr) - { - if (instr != null && instr.Contains("%25")) { - return instr.Replace("%25", "%"); - } - return instr; - } - public MSBuildFileReader(string fileName) : base(fileName) { } - public MSBuildFileReader(TextReader r) : base(r) { } - // - // Summary: - // Gets the value of the attribute with the specified index. - // - // Parameters: - // i: - // The index of the attribute. The index is zero-based. (The first attribute - // has index 0.) - // - // Returns: - // The value of the specified attribute. - // - // Exceptions: - // System.ArgumentOutOfRangeException - // - public override string GetAttribute(int i) - { - return Convert(base.GetAttribute(i)); - } - // - // Summary: - // Gets the value of the attribute with the specified name. - // - // Parameters: - // name: - // The qualified name of the attribute. - // - // Returns: - // The value of the specified attribute. If the attribute is not found, null is - // returned. - public override string GetAttribute(string name) - { - return Convert(base.GetAttribute(name)); - } - // - // Summary: - // Gets the value of the attribute with the specified local name and namespace - // URI. - // - // Parameters: - // localName: - // The local name of the attribute. - // namespaceURI: - // The namespace URI of the attribute. - // - // Returns: - // The value of the specified attribute. If the attribute is not found, null is - // returned. This method does not move the reader. - public override string GetAttribute(string localName, string namespaceURI) - { - return Convert(base.GetAttribute(localName, namespaceURI)); - } - } - // Summary: - // Represents a writer that writes MSBuild files converting the MSBuild specific escape % to %25 - public class MSBuildFileWriter : XmlTextWriter - { - private string Convert(string instr) - { - if (instr != null && instr.Contains("%")) { - return instr.Replace("%", "%25"); - } - return instr; - } - public MSBuildFileWriter(string fileName, Encoding encoding) : base(fileName, encoding) { } - - public override void WriteString(string text) - { - base.WriteString(Convert(text)); - } - } -} diff --git a/src/Main/Base/Project/Src/Project/MSBuildProject.cs b/src/Main/Base/Project/Src/Project/MSBuildProject.cs index 7e40ea69e9..655a07d52c 100644 --- a/src/Main/Base/Project/Src/Project/MSBuildProject.cs +++ b/src/Main/Base/Project/Src/Project/MSBuildProject.cs @@ -90,7 +90,7 @@ namespace ICSharpCode.SharpDevelop.Project protected void SetupProject(string projectFileName) { this.FileName = Path.GetFullPath(projectFileName); - using (MSBuildFileReader reader = new MSBuildFileReader(projectFileName)) { + using (XmlTextReader reader = new XmlTextReader(projectFileName)) { reader.WhitespaceHandling = WhitespaceHandling.Significant; reader.Namespaces = false; reader.MoveToContent(); // we have to skip over the XmlDeclaration (if it exists) @@ -110,7 +110,7 @@ namespace ICSharpCode.SharpDevelop.Project ProjectItem.ReadItemGroup(reader, this, Items); break; case "Import": - string import = reader.GetAttribute("Project"); + string import = ProjectItem.MSBuildUnescape(reader.GetAttribute("Project")); Imports.Add(import); break; default: @@ -124,7 +124,7 @@ namespace ICSharpCode.SharpDevelop.Project string userSettingsFileName = projectFileName + ".user"; if (File.Exists(userSettingsFileName)) { - using (MSBuildFileReader reader = new MSBuildFileReader(userSettingsFileName)) { + using (XmlTextReader reader = new XmlTextReader(userSettingsFileName)) { reader.WhitespaceHandling = WhitespaceHandling.Significant; reader.Namespaces = false; reader.MoveToContent(); // we have to skip over the XmlDeclaration (if it exists) @@ -179,7 +179,7 @@ namespace ICSharpCode.SharpDevelop.Project Dictionary configurations = isUserFile ? this.userConfigurations : this.configurations; string conditionProperty = match.Result("${property}"); - string configuration = match.Result("${value}"); + string configuration = ProjectItem.MSBuildUnescape(match.Result("${value}")); if (conditionProperty == "$(Configuration)|$(Platform)") { // configuration is ok } else if (conditionProperty == "$(Configuration)") { @@ -211,7 +211,7 @@ namespace ICSharpCode.SharpDevelop.Project if (!System.IO.Directory.Exists(outputDirectory)) { System.IO.Directory.CreateDirectory(outputDirectory); } - using (MSBuildFileWriter writer = new MSBuildFileWriter(fileName, Encoding.UTF8)) { + using (XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.UTF8)) { writer.Formatting = Formatting.Indented; writer.Namespaces = false; @@ -267,7 +267,7 @@ namespace ICSharpCode.SharpDevelop.Project foreach (string import in Imports) { writer.WriteStartElement("Import"); - writer.WriteAttributeString("Project", import); + writer.WriteAttributeString("Project", ProjectItem.MSBuildEscape(import)); writer.WriteEndElement(); } @@ -276,7 +276,7 @@ namespace ICSharpCode.SharpDevelop.Project string userSettingsFileName = fileName + ".user"; if (userConfigurations.Count > 0 || UserBaseConfiguration.PropertyCount > 0 || File.Exists(userSettingsFileName)) { - using (MSBuildFileWriter writer = new MSBuildFileWriter(userSettingsFileName, Encoding.UTF8)) { + using (XmlTextWriter writer = new XmlTextWriter(userSettingsFileName, Encoding.UTF8)) { writer.Formatting = Formatting.Indented; writer.Namespaces = false; writer.WriteStartElement("Project"); @@ -290,7 +290,7 @@ namespace ICSharpCode.SharpDevelop.Project } } - static void SaveProperties(MSBuildFileWriter writer, PropertyGroup baseConfiguration, Dictionary configurations) + static void SaveProperties(XmlWriter writer, PropertyGroup baseConfiguration, Dictionary configurations) { if (baseConfiguration.PropertyCount > 0) { writer.WriteStartElement("PropertyGroup"); @@ -304,22 +304,22 @@ namespace ICSharpCode.SharpDevelop.Project } writer.WriteStartElement("PropertyGroup"); if (entry.Key.StartsWith("*|")) { - writer.WriteAttributeString("Condition", " '$(Platform)' == '" + entry.Key.Substring(2) + "' "); + writer.WriteAttributeString("Condition", " '$(Platform)' == '" + ProjectItem.MSBuildEscape(entry.Key.Substring(2)) + "' "); } else if (entry.Key.EndsWith("|*")) { - writer.WriteAttributeString("Condition", " '$(Configuration)' == '" + entry.Key.Substring(0, entry.Key.Length - 2) + "' "); + writer.WriteAttributeString("Condition", " '$(Configuration)' == '" + ProjectItem.MSBuildEscape(entry.Key.Substring(0, entry.Key.Length - 2)) + "' "); } else { - writer.WriteAttributeString("Condition", " '$(Configuration)|$(Platform)' == '" + entry.Key + "' "); + writer.WriteAttributeString("Condition", " '$(Configuration)|$(Platform)' == '" + ProjectItem.MSBuildEscape(entry.Key) + "' "); } entry.Value.WriteProperties(writer); writer.WriteEndElement(); } } - static void SaveUnknownXmlSections(MSBuildFileWriter writer, List unknownElements) + static void SaveUnknownXmlSections(XmlWriter writer, List unknownElements) { foreach (string element in unknownElements) { // round-trip xml text again for better formatting - MSBuildFileReader reader = new MSBuildFileReader(new StringReader(element)); + XmlTextReader reader = new XmlTextReader(new StringReader(element)); writer.WriteNode(reader, false); reader.Close(); } diff --git a/src/Main/Base/Project/Src/Project/PropertyGroup.cs b/src/Main/Base/Project/Src/Project/PropertyGroup.cs index b4ea222af3..f4a3c6ea78 100644 --- a/src/Main/Base/Project/Src/Project/PropertyGroup.cs +++ b/src/Main/Base/Project/Src/Project/PropertyGroup.cs @@ -161,7 +161,7 @@ namespace ICSharpCode.SharpDevelop.Project properties[propertyName] = null; goto reLoop; } - properties[propertyName] = reader.Value.Trim(); + properties[propertyName] = ProjectItem.MSBuildUnescape(reader.Value.Trim()); } break; } @@ -178,7 +178,7 @@ namespace ICSharpCode.SharpDevelop.Project } if (entry.Value != null) { - writer.WriteValue(entry.Value); + writer.WriteValue(ProjectItem.MSBuildEscape(entry.Value)); } writer.WriteEndElement(); } diff --git a/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs b/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs index 3c19242419..fc90fef7f8 100644 --- a/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs +++ b/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs @@ -180,7 +180,7 @@ namespace ICSharpCode.Core return l; } - public void WriteProperties(XmlTextWriter writer) + public void WriteProperties(XmlWriter writer) { foreach (KeyValuePair entry in properties) { object val = entry.Value; @@ -206,7 +206,7 @@ namespace ICSharpCode.Core } } - void WriteValue(XmlTextWriter writer, object val) + void WriteValue(XmlWriter writer, object val) { if (val != null) { if (val is string) {