1 // 2 // PolicyImportHelper.cs 3 // 4 // Author: 5 // Martin Baulig <martin.baulig@xamarin.com> 6 // 7 // Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com) 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining a copy 10 // of this software and associated documentation files (the "Software"), to deal 11 // in the Software without restriction, including without limitation the rights 12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 // copies of the Software, and to permit persons to whom the Software is 14 // furnished to do so, subject to the following conditions: 15 // 16 // The above copyright notice and this permission notice shall be included in 17 // all copies or substantial portions of the Software. 18 // 19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 // THE SOFTWARE. 26 using System; 27 using System.Xml; 28 using System.Collections.Generic; 29 using System.ServiceModel.Description; 30 31 using QName = System.Xml.XmlQualifiedName; 32 33 namespace System.ServiceModel.Channels { 34 35 internal static class PolicyImportHelper { 36 37 internal const string SecurityPolicyNS = "http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"; 38 internal const string PolicyNS = "http://schemas.xmlsoap.org/ws/2004/09/policy"; 39 internal const string MimeSerializationNS = "http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization"; 40 internal const string HttpAuthNS = "http://schemas.microsoft.com/ws/06/2004/policy/http"; 41 42 internal const string FramingPolicyNS = "http://schemas.microsoft.com/ws/2006/05/framing/policy"; 43 internal const string NetBinaryEncodingNS = "http://schemas.microsoft.com/ws/06/2004/mspolicy/netbinary1"; 44 45 internal const string WSSecurityNS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"; 46 GetTransportBindingPolicy(PolicyAssertionCollection collection)47 internal static XmlElement GetTransportBindingPolicy (PolicyAssertionCollection collection) 48 { 49 return FindAndRemove (collection, "TransportBinding", SecurityPolicyNS); 50 } 51 GetStreamedMessageFramingPolicy(PolicyAssertionCollection collection)52 internal static XmlElement GetStreamedMessageFramingPolicy (PolicyAssertionCollection collection) 53 { 54 return FindAndRemove (collection, "Streamed", FramingPolicyNS); 55 } 56 GetBinaryMessageEncodingPolicy(PolicyAssertionCollection collection)57 internal static XmlElement GetBinaryMessageEncodingPolicy (PolicyAssertionCollection collection) 58 { 59 return FindAndRemove (collection, "BinaryEncoding", NetBinaryEncodingNS); 60 } 61 GetMtomMessageEncodingPolicy(PolicyAssertionCollection collection)62 internal static XmlElement GetMtomMessageEncodingPolicy (PolicyAssertionCollection collection) 63 { 64 return FindAndRemove (collection, "OptimizedMimeSerialization", MimeSerializationNS); 65 } 66 FindAndRemove(PolicyAssertionCollection collection, string name, string ns)67 static XmlElement FindAndRemove (PolicyAssertionCollection collection, string name, string ns) 68 { 69 var element = collection.Find (name, ns); 70 if (element != null) 71 collection.Remove (element); 72 return element; 73 } 74 FindAssertionByNS( PolicyAssertionCollection collection, string ns)75 internal static List<XmlElement> FindAssertionByNS ( 76 PolicyAssertionCollection collection, string ns) 77 { 78 var list = new List<XmlElement> (); 79 foreach (var assertion in collection) { 80 if (assertion.NamespaceURI.Equals (ns)) 81 list.Add (assertion); 82 } 83 return list; 84 } 85 GetPolicyElements(XmlElement root, out bool error)86 internal static List<XmlElement> GetPolicyElements (XmlElement root, out bool error) 87 { 88 XmlElement policy = null; 89 var list = new List<XmlElement> (); 90 91 foreach (var node in root.ChildNodes) { 92 var e = node as XmlElement; 93 if (e == null) 94 continue; 95 if (!PolicyNS.Equals (e.NamespaceURI) || !e.LocalName.Equals ("Policy")) { 96 error = true; 97 return list; 98 } 99 if (policy != null) { 100 error = true; 101 return list; 102 } 103 policy = e; 104 } 105 106 if (policy == null) { 107 error = true; 108 return list; 109 } 110 111 foreach (var node in policy.ChildNodes) { 112 var e = node as XmlElement; 113 if (e != null) 114 list.Add (e); 115 } 116 117 error = false; 118 return list; 119 } 120 FindPolicyElement(MetadataImporter importer, XmlElement root, QName name, bool required, bool removeWhenFound, out XmlElement element)121 internal static bool FindPolicyElement (MetadataImporter importer, XmlElement root, 122 QName name, bool required, bool removeWhenFound, 123 out XmlElement element) 124 { 125 if (!FindPolicyElement (root, name, removeWhenFound, out element)) { 126 importer.AddWarning ("Invalid policy element: {0}", root.OuterXml); 127 return false; 128 } 129 if (required && (element == null)) { 130 importer.AddWarning ("Did not find policy element `{0}'.", name); 131 return false; 132 } 133 return true; 134 } 135 FindPolicyElement(XmlElement root, QName name, bool removeWhenFound, out XmlElement element)136 internal static bool FindPolicyElement (XmlElement root, QName name, 137 bool removeWhenFound, out XmlElement element) 138 { 139 XmlElement policy = null; 140 foreach (var node in root.ChildNodes) { 141 var e = node as XmlElement; 142 if (e == null) 143 continue; 144 if (!PolicyNS.Equals (e.NamespaceURI) || !e.LocalName.Equals ("Policy")) { 145 element = null; 146 return false; 147 } 148 if (policy != null) { 149 element = null; 150 return false; 151 } 152 policy = e; 153 } 154 155 if (policy == null) { 156 element = null; 157 return true; 158 } 159 160 element = null; 161 foreach (var node in policy.ChildNodes) { 162 var e = node as XmlElement; 163 if (e == null) 164 continue; 165 if (!name.Namespace.Equals (e.NamespaceURI) || !name.Name.Equals (e.LocalName)) 166 continue; 167 168 element = e; 169 break; 170 } 171 172 if (!removeWhenFound || (element == null)) 173 return true; 174 175 policy.RemoveChild (element); 176 177 bool foundAnother = false; 178 foreach (var node in policy.ChildNodes) { 179 var e = node as XmlElement; 180 if (e != null) { 181 foundAnother = true; 182 break; 183 } 184 } 185 186 if (!foundAnother) 187 root.RemoveChild (policy); 188 return true; 189 } 190 GetElement(MetadataImporter importer, XmlElement root, string name, string ns)191 internal static XmlElement GetElement (MetadataImporter importer, 192 XmlElement root, string name, string ns) 193 { 194 return GetElement (importer, root, name, ns, false); 195 } 196 GetElement(MetadataImporter importer, XmlElement root, string name, string ns, bool required)197 internal static XmlElement GetElement (MetadataImporter importer, 198 XmlElement root, string name, string ns, 199 bool required) 200 { 201 return GetElement (importer, root, new QName (name, ns), required); 202 } 203 GetElement(MetadataImporter importer, XmlElement root, QName name, bool required)204 internal static XmlElement GetElement (MetadataImporter importer, 205 XmlElement root, QName name, bool required) 206 { 207 var list = root.GetElementsByTagName (name.Name, name.Namespace); 208 if (list.Count < 1) { 209 if (required) 210 importer.AddWarning ("Did not find required policy element `{0}'", name); 211 return null; 212 } 213 214 if (list.Count > 1) { 215 importer.AddWarning ("Found duplicate policy element `{0}'", name); 216 return null; 217 } 218 219 var element = list [0] as XmlElement; 220 if (required && (element == null)) 221 importer.AddWarning ("Did not find required policy element `{0}'", name); 222 return element; 223 } 224 WrapPolicy(XmlElement element)225 internal static XmlElement WrapPolicy (XmlElement element) 226 { 227 var policy = element.OwnerDocument.CreateElement ("wsp", "Policy", PolicyNS); 228 policy.AppendChild (element); 229 return policy; 230 } 231 232 // 233 // Add a single element, wrapping it inside <wsp:Policy> 234 // AddWrappedPolicyElement(XmlElement root, XmlElement element)235 internal static void AddWrappedPolicyElement (XmlElement root, XmlElement element) 236 { 237 if (root.OwnerDocument != element.OwnerDocument) 238 element = (XmlElement)root.OwnerDocument.ImportNode (element, true); 239 if (!element.NamespaceURI.Equals (PolicyNS) || !element.LocalName.Equals ("Policy")) 240 element = WrapPolicy (element); 241 root.AppendChild (element); 242 } 243 244 // 245 // Add multiple elements, wrapping them inside a single <wsp:Policy> 246 // AddWrappedPolicyElements(XmlElement root, params XmlElement[] elements)247 internal static void AddWrappedPolicyElements (XmlElement root, params XmlElement[] elements) 248 { 249 var policy = root.OwnerDocument.CreateElement ("wsp", "Policy", PolicyNS); 250 root.AppendChild (policy); 251 252 foreach (var element in elements) { 253 XmlElement imported; 254 if (root.OwnerDocument != element.OwnerDocument) 255 imported = (XmlElement)root.OwnerDocument.ImportNode (element, true); 256 else 257 imported = element; 258 policy.AppendChild (element); 259 } 260 } 261 } 262 } 263 264