2 // FlashCrossDomainPolicyParser.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;
40 Specification: http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html
42 # This grammar is based on the xsd from Adobe, but the schema is wrong.
43 # It should have used interleave (all). Some crossdomain.xml are invalidated.
44 # (For example, try mono-xmltool --validate-xsd http://www.adobe.com/xml/schemas/PolicyFile.xsd http://twitter.com/crossdomain.xml)
46 default namespace = ""
50 start = cross-domain-policy
52 cross-domain-policy = element cross-domain-policy {
53 element site-control {
54 attribute permitted-cross-domain-policies {
55 "all" | "by-contract-type" | "by-ftp-filename" | "master-only" | "none"
58 element allow-access-from {
59 attribute domain { text },
60 attribute to-ports { text }?,
61 attribute secure { xs:boolean }?
63 element allow-http-request-headers-from {
64 attribute domain { text },
65 attribute headers { text },
66 attribute secure { xs:boolean }?
68 element allow-access-from-identity {
71 attribute fingerprint { text },
72 attribute fingerprint-algorithm { text }
82 namespace System.Net.Policy {
84 partial class FlashCrossDomainPolicy {
86 static bool ReadBooleanAttribute (string attribute)
95 throw new XmlException ();
99 // only "domain" and "secure" attributes are allowed - anything else is considered invalid
100 static AllowAccessFrom CreateAllowAccessFrom (XmlReader reader)
102 int n = reader.AttributeCount;
103 string domain = reader.GetAttribute ("domain");
106 string secure = reader.GetAttribute ("secure");
110 throw new XmlException ("unknown/unsupported attributes");
112 return new AllowAccessFrom () { Domain = domain, Secure = ReadBooleanAttribute (secure) };
115 // only "domain", "secure" and "headers" attributes are allowed - anything else is considered invalid
116 static AllowHttpRequestHeadersFrom CreateAllowHttpRequestHeadersFrom (XmlReader reader)
118 int n = reader.AttributeCount;
119 string domain = reader.GetAttribute ("domain");
122 string secure = reader.GetAttribute ("secure");
125 string headers = reader.GetAttribute ("headers");
129 throw new XmlException ("unknown/unsupported attributes");
131 var h = new AllowHttpRequestHeadersFrom () { Domain = domain, Secure = ReadBooleanAttribute (secure) };
132 h.Headers.SetHeaders (headers);
136 // only "permitted-cross-domain-policies" attribute is allowed - anything else is considered invalid
137 static string GetSiteControl (XmlReader reader)
139 int n = reader.AttributeCount;
140 string site = reader.GetAttribute ("permitted-cross-domain-policies");
144 throw new XmlException ("unknown/unsupported attributes");
148 static public ICrossDomainPolicy FromStream (Stream stream)
150 FlashCrossDomainPolicy cdp = new FlashCrossDomainPolicy ();
152 // Silverlight accepts whitespaces before the XML - which is invalid XML
153 StreamReader sr = new StreamReader (stream);
154 while (Char.IsWhiteSpace ((char) sr.Peek ()))
157 XmlReaderSettings policy_settings = new XmlReaderSettings ();
158 policy_settings.DtdProcessing = DtdProcessing.Ignore;
159 using (XmlReader reader = XmlReader.Create (sr, policy_settings)) {
161 reader.MoveToContent ();
162 if (reader.HasAttributes || reader.IsEmptyElement) {
167 while (!reader.EOF) {
168 reader.ReadStartElement ("cross-domain-policy", String.Empty);
169 for (reader.MoveToContent (); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent ()) {
170 if (reader.NodeType != XmlNodeType.Element) {
175 switch (reader.LocalName) {
177 cdp.SiteControl = GetSiteControl (reader);
180 case "allow-access-from":
181 var a = CreateAllowAccessFrom (reader);
182 cdp.AllowedAccesses.Add (a);
185 case "allow-http-request-headers-from":
186 var h = CreateAllowHttpRequestHeadersFrom (reader);
187 cdp.AllowedHttpRequestHeaders.Add (h);
195 reader.ReadEndElement ();
196 reader.MoveToContent ();
200 // if none supplied set a default for headers
201 if (cdp.AllowedHttpRequestHeaders.Count == 0) {
202 var h = new AllowHttpRequestHeadersFrom () { Domain = "*", Secure = true };
203 h.Headers.SetHeaders (null); // defaults
204 cdp.AllowedHttpRequestHeaders.Add (h);