| File: System\ServiceModel\Dispatcher\EndpointAddressProcessor.cs | Web Access |
| Project: src\src\System.ServiceModel.Primitives\src\System.ServiceModel.Primitives.csproj (System.ServiceModel.Primitives) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Generic; using System.Globalization; using System.Text; using System.Xml; namespace System.ServiceModel.Dispatcher { internal class EndpointAddressProcessor { // QName Attributes internal static readonly string XsiNs = XmlUtil.XmlSerializerSchemaInstanceNamespace; internal const string SerNs = "http://schemas.microsoft.com/2003/10/Serialization/"; internal const string TypeLN = "type"; internal const string ItemTypeLN = "ItemType"; internal const string FactoryTypeLN = "FactoryType"; internal static string GetComparableForm(StringBuilder builder, XmlReader reader) { List<Attr> attrSet = new List<Attr>(); int valueLength = -1; while (!reader.EOF) { XmlNodeType type = reader.MoveToContent(); switch (type) { case XmlNodeType.Element: CompleteValue(builder, valueLength); valueLength = -1; builder.Append("<"); AppendString(builder, reader.LocalName); builder.Append(":"); AppendString(builder, reader.NamespaceURI); builder.Append(" "); // Scan attributes attrSet.Clear(); if (reader.MoveToFirstAttribute()) { do { // Ignore namespaces if (reader.Prefix == "xmlns" || reader.Name == "xmlns") { continue; } if (reader.LocalName == AddressingStrings.IsReferenceParameter && reader.NamespaceURI == Addressing10Strings.Namespace) { continue; // ignore IsReferenceParameter } string val = reader.Value; if ((reader.LocalName == TypeLN && reader.NamespaceURI == XsiNs) || (reader.NamespaceURI == SerNs && (reader.LocalName == ItemTypeLN || reader.LocalName == FactoryTypeLN))) { string local, ns; XmlUtil.ParseQName(reader, val, out local, out ns); val = local + "^" + local.Length.ToString(CultureInfo.InvariantCulture) + ":" + ns + "^" + ns.Length.ToString(CultureInfo.InvariantCulture); } else if (reader.LocalName == XD.UtilityDictionary.IdAttribute.Value && reader.NamespaceURI == XD.UtilityDictionary.Namespace.Value) { // ignore wsu:Id attributes added by security to sign the header continue; } attrSet.Add(new Attr(reader.LocalName, reader.NamespaceURI, val)); } while (reader.MoveToNextAttribute()); } reader.MoveToElement(); if (attrSet.Count > 0) { attrSet.Sort(); for (int i = 0; i < attrSet.Count; ++i) { Attr a = attrSet[i]; AppendString(builder, a.local); builder.Append(":"); AppendString(builder, a.ns); builder.Append("=\""); AppendString(builder, a.val); builder.Append("\" "); } } if (reader.IsEmptyElement) { builder.Append("></>"); // Should be the same as an empty tag. } else { builder.Append(">"); } break; case XmlNodeType.EndElement: CompleteValue(builder, valueLength); valueLength = -1; builder.Append("</>"); break; // Need to escape CDATA values case XmlNodeType.CDATA: CompleteValue(builder, valueLength); valueLength = -1; builder.Append("<![CDATA["); AppendString(builder, reader.Value); builder.Append("]]>"); break; case XmlNodeType.SignificantWhitespace: case XmlNodeType.Text: if (valueLength < 0) { valueLength = builder.Length; } builder.Append(reader.Value); break; default: // Do nothing break; } reader.Read(); } return builder.ToString(); } private static void AppendString(StringBuilder builder, string s) { builder.Append(s); builder.Append("^"); builder.Append(s.Length.ToString(CultureInfo.InvariantCulture)); } private static void CompleteValue(StringBuilder builder, int startLength) { if (startLength < 0) { return; } int len = builder.Length - startLength; builder.Append("^"); builder.Append(len.ToString(CultureInfo.InvariantCulture)); } internal class Attr : IComparable<Attr> { internal string local; internal string ns; internal string val; private string _key; internal Attr(string l, string ns, string v) { local = l; this.ns = ns; val = v; _key = ns + ":" + l; } public int CompareTo(Attr a) { return string.Compare(_key, a._key, StringComparison.Ordinal); } } } }