Fix RemoteEndpoint with async+DualMode (#4717)
[mono.git] / mcs / class / System.Net / System.Net.Policy / FlashCrossDomainPolicyParser.cs
1 //
2 // FlashCrossDomainPolicyParser.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //      Moonlight List (moonlight-list@lists.ximian.com)
7 //
8 // Copyright (C) 2009-2010 Novell, Inc.  http://www.novell.com
9 //
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:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
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.
28 //
29
30 #if MOBILE
31
32 using System;
33 using System.Collections.Generic;
34 using System.IO;
35 using System.Linq;
36 using System.Xml;
37
38 /*
39
40 Specification: http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html
41
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)
45
46 default namespace = ""
47
48 grammar {
49
50 start = cross-domain-policy
51
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"
56     }
57   }?,
58   element allow-access-from {
59     attribute domain { text },
60     attribute to-ports { text }?,
61     attribute secure { xs:boolean }?
62   }*,
63   element allow-http-request-headers-from {
64     attribute domain { text },
65     attribute headers { text },
66     attribute secure { xs:boolean }?
67   }*,
68   element allow-access-from-identity {
69     element signatory {
70       element certificate {
71         attribute fingerprint { text },
72         attribute fingerprint-algorithm { text }
73       }
74     }
75   }*
76 }
77
78 }
79
80 */
81
82 namespace System.Net.Policy {
83
84         partial class FlashCrossDomainPolicy {
85
86                 static bool ReadBooleanAttribute (string attribute)
87                 {
88                         switch (attribute) {
89                         case null:
90                         case "true":
91                                 return true;
92                         case "false":
93                                 return false;
94                         default:
95                                 throw new XmlException ();
96                         }
97                 }
98
99                 // only "domain" and "secure" attributes are allowed - anything else is considered invalid
100                 static AllowAccessFrom CreateAllowAccessFrom (XmlReader reader)
101                 {
102                         int n = reader.AttributeCount;
103                         string domain = reader.GetAttribute ("domain");
104                         if (domain != null)
105                                 n--;
106                         string secure = reader.GetAttribute ("secure");
107                         if (secure != null)
108                                 n--;
109                         if (n != 0)
110                                 throw new XmlException ("unknown/unsupported attributes");
111
112                         return new AllowAccessFrom () { Domain = domain, Secure = ReadBooleanAttribute (secure) };
113                 }
114
115                 // only "domain", "secure" and "headers" attributes are allowed - anything else is considered invalid
116                 static AllowHttpRequestHeadersFrom CreateAllowHttpRequestHeadersFrom (XmlReader reader)
117                 {
118                         int n = reader.AttributeCount;
119                         string domain = reader.GetAttribute ("domain");
120                         if (domain != null)
121                                 n--;
122                         string secure = reader.GetAttribute ("secure");
123                         if (secure != null)
124                                 n--;
125                         string headers = reader.GetAttribute ("headers");
126                         if (headers != null)
127                                 n--;
128                         if (n != 0)
129                                 throw new XmlException ("unknown/unsupported attributes");
130
131                         var h = new AllowHttpRequestHeadersFrom () { Domain = domain, Secure = ReadBooleanAttribute (secure) };
132                         h.Headers.SetHeaders (headers);
133                         return h;
134                 }
135
136                 // only "permitted-cross-domain-policies" attribute is allowed - anything else is considered invalid
137                 static string GetSiteControl (XmlReader reader)
138                 {
139                         int n = reader.AttributeCount;
140                         string site = reader.GetAttribute ("permitted-cross-domain-policies");
141                         if (site != null)
142                                 n--;
143                         if (n != 0)
144                                 throw new XmlException ("unknown/unsupported attributes");
145                         return site;
146                 }
147
148                 static public ICrossDomainPolicy FromStream (Stream stream)
149                 {
150                         FlashCrossDomainPolicy cdp = new FlashCrossDomainPolicy ();
151
152                         // Silverlight accepts whitespaces before the XML - which is invalid XML
153                         StreamReader sr = new StreamReader (stream);
154                         while (Char.IsWhiteSpace ((char) sr.Peek ()))
155                                 sr.Read ();
156
157                         XmlReaderSettings policy_settings = new XmlReaderSettings ();
158                         policy_settings.DtdProcessing = DtdProcessing.Ignore;
159                         using (XmlReader reader = XmlReader.Create (sr, policy_settings)) {
160
161                                 reader.MoveToContent ();
162                                 if (reader.HasAttributes || reader.IsEmptyElement) {
163                                         reader.Skip ();
164                                         return null;
165                                 }
166
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) {
171                                                         reader.Skip ();
172                                                         continue;
173                                                 }
174
175                                                 switch (reader.LocalName) {
176                                                 case "site-control":
177                                                         cdp.SiteControl = GetSiteControl (reader);
178                                                         reader.Skip ();
179                                                         break;
180                                                 case "allow-access-from":
181                                                         var a = CreateAllowAccessFrom (reader);
182                                                         cdp.AllowedAccesses.Add (a);
183                                                         reader.Skip ();
184                                                         break;
185                                                 case "allow-http-request-headers-from":
186                                                         var h = CreateAllowHttpRequestHeadersFrom (reader);
187                                                         cdp.AllowedHttpRequestHeaders.Add (h);
188                                                         reader.Skip ();
189                                                         break;
190                                                 default:
191                                                         reader.Skip ();
192                                                         return null;
193                                                 }
194                                         }
195                                         reader.ReadEndElement ();
196                                         reader.MoveToContent ();
197                                 }
198                         }
199
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);
205                         }
206                         return cdp;
207                 }
208         }
209 }
210
211 #endif
212