2 // ClientAccessPolicyParser.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
6 // Moonlight List (moonlight-list@lists.ximian.com)
8 // Copyright (C) 2009-2010 Novell, Inc. http://www.novell.com
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System
.Collections
.Generic
;
39 default namespace = ""
45 access-policy = element access-policy {
46 element cross-domain-access {
47 element policy { allow-from, grant-to }
51 allow-from = element allow-from {
52 attribute http-request-headers { text },
54 attribute uri { text }
58 grant-to = element grant-to {
59 (resource | socket-resource)+
62 resource = element resource {
63 attribute path { text },
64 attribute include-subpaths { "true" | "false" }
67 socket-resource = element socket-resource {
68 attribute port { text },
69 attribute protocol { text }
75 namespace System
.Net
.Policy
{
77 partial class ClientAccessPolicy
{
79 static public ICrossDomainPolicy
FromStream (Stream stream
)
81 ClientAccessPolicy cap
= new ClientAccessPolicy ();
83 // Silverlight accepts whitespaces before the XML - which is invalid XML
84 StreamReader sr
= new StreamReader (stream
);
85 while (Char
.IsWhiteSpace ((char) sr
.Peek ()))
88 XmlReaderSettings policy_settings
= new XmlReaderSettings ();
89 policy_settings
.DtdProcessing
= DtdProcessing
.Ignore
;
90 using (XmlReader reader
= XmlReader
.Create (sr
, policy_settings
)) {
91 reader
.MoveToContent ();
92 if (reader
.IsEmptyElement
) {
96 reader
.ReadStartElement ("access-policy", String
.Empty
);
97 for (reader
.MoveToContent (); reader
.NodeType
!= XmlNodeType
.EndElement
; reader
.MoveToContent ()) {
98 if (reader
.NodeType
!= XmlNodeType
.Element
)
99 throw new XmlException (String
.Format ("Unexpected access-policy content: {0}", reader
.NodeType
));
101 if ((reader
.LocalName
!= "cross-domain-access") || reader
.IsEmptyElement
) {
106 reader
.ReadStartElement ("cross-domain-access", String
.Empty
);
107 for (reader
.MoveToContent (); reader
.NodeType
!= XmlNodeType
.EndElement
; reader
.MoveToContent ()) {
108 if (reader
.NodeType
!= XmlNodeType
.Element
)
109 throw new XmlException (String
.Format ("Unexpected access-policy content: {0}", reader
.NodeType
));
111 if ((reader
.Name
!= "policy") || reader
.IsEmptyElement
) {
116 ReadPolicyElement (reader
, cap
);
118 reader
.ReadEndElement ();
120 reader
.ReadEndElement ();
125 static void ReadPolicyElement (XmlReader reader
, ClientAccessPolicy cap
)
127 if (reader
.HasAttributes
|| reader
.IsEmptyElement
) {
132 var policy
= new AccessPolicy ();
135 reader
.ReadStartElement ("policy", String
.Empty
);
136 for (reader
.MoveToContent (); reader
.NodeType
!= XmlNodeType
.EndElement
; reader
.MoveToContent ()) {
137 if (reader
.NodeType
!= XmlNodeType
.Element
)
138 throw new XmlException (String
.Format ("Unexpected policy content: {0}", reader
.NodeType
));
140 switch (reader
.LocalName
) {
142 ReadAllowFromElement (reader
, policy
);
145 ReadGrantToElement (reader
, policy
);
155 cap
.AccessPolicyList
.Add (policy
);
156 reader
.ReadEndElement ();
159 static void ReadAllowFromElement (XmlReader reader
, AccessPolicy policy
)
161 var v
= new AllowFrom ();
164 if (reader
.HasAttributes
|| reader
.IsEmptyElement
) {
169 v
.HttpRequestHeaders
.SetHeaders (reader
.GetAttribute ("http-request-headers"));
170 reader
.ReadStartElement ("allow-from", String
.Empty
);
171 for (reader
.MoveToContent (); reader
.NodeType
!= XmlNodeType
.EndElement
; reader
.MoveToContent ()) {
172 if (reader
.NodeType
!= XmlNodeType
.Element
)
173 throw new XmlException (String
.Format ("Unexpected allow-from content: {0}", reader
.NodeType
));
174 if (!String
.IsNullOrEmpty (reader
.NamespaceURI
)) {
178 switch (reader
.LocalName
) {
180 var d
= reader
.GetAttribute ("uri");
183 v
.AllowAnyDomain
= true;
207 policy
.AllowedServices
.Add (v
);
208 reader
.ReadEndElement ();
211 // only "path" and "include-subpaths" attributes are allowed - anything else is not considered
212 static Resource
CreateResource (XmlReader reader
)
214 int n
= reader
.AttributeCount
;
215 string path
= reader
.GetAttribute ("path");
218 string subpaths
= reader
.GetAttribute ("include-subpaths");
219 if (subpaths
!= null)
221 if ((n
!= 0) || !reader
.IsEmptyElement
)
224 return new Resource () {
226 IncludeSubpaths
= subpaths
== null ? false : XmlConvert
.ToBoolean (subpaths
)
230 static void ReadGrantToElement (XmlReader reader
, AccessPolicy policy
)
232 var v
= new GrantTo ();
235 if (reader
.HasAttributes
|| reader
.IsEmptyElement
) {
240 reader
.ReadStartElement ("grant-to", String
.Empty
);
241 for (reader
.MoveToContent (); reader
.NodeType
!= XmlNodeType
.EndElement
; reader
.MoveToContent ()) {
242 if (reader
.NodeType
!= XmlNodeType
.Element
)
243 throw new XmlException (String
.Format ("Unexpected grant-to content: {0}", reader
.NodeType
));
244 if (!String
.IsNullOrEmpty (reader
.NamespaceURI
)) {
249 switch (reader
.LocalName
) {
251 var r
= CreateResource (reader
);
257 case "socket-resource":
258 // ignore everything that is not TCP
259 if (reader
.GetAttribute ("protocol") != "tcp")
261 // we can merge them all together inside a policy
262 policy
.PortMask
|= ParsePorts (reader
.GetAttribute ("port"));
271 policy
.GrantedResources
.Add (v
);
272 reader
.ReadEndElement ();
275 // e.g. reserved ? 4534-4502
276 static long ParsePorts (string ports
)
279 int sep
= ports
.IndexOf ('-');
282 ushort from = ParsePort (ports
.Substring (0, sep
));
283 ushort to
= ParsePort (ports
.Substring (sep
+ 1));
284 for (int port
= from; port
<= to
; port
++)
285 mask
|= (long) (1ul << (port
- AccessPolicy
.MinPort
));
288 ushort port
= ParsePort (ports
);
289 mask
|= (long) (1ul << (port
- AccessPolicy
.MinPort
));
294 static ushort ParsePort (string s
)
297 if (!UInt16
.TryParse (s
, out port
) || (port
< AccessPolicy
.MinPort
) || (port
> AccessPolicy
.MaxPort
))
298 throw new XmlException ("Invalid port");