Merge pull request #463 from strawd/concurrent-requests
[mono.git] / mcs / class / corlib / System.Security.Policy / NetCodeGroup.cs
1 //
2 // System.Security.Policy.NetCodeGroup.cs
3 //
4 // Authors:
5 //      Jackson Harper (Jackson@LatitudeGeo.com)
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // (C) 2002 Jackson Harper, All rights reserved
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Collections;
32 using System.Globalization;
33 using System.Runtime.InteropServices;
34 using System.Security.Permissions;
35
36 namespace System.Security.Policy {
37
38         [Serializable]
39         [ComVisible (true)]
40         public sealed class NetCodeGroup : CodeGroup {
41
42                 public static readonly string AbsentOriginScheme = String.Empty;
43                 public static readonly string AnyOtherOriginScheme = "*";
44
45                 private Hashtable _rules = new Hashtable ();
46                 private int _hashcode;
47
48                 public NetCodeGroup (IMembershipCondition membershipCondition) 
49                         : base (membershipCondition, null) 
50                 {
51                 }
52
53                 // for PolicyLevel (to avoid validation duplication)
54                 internal NetCodeGroup (SecurityElement e, PolicyLevel level)
55                         : base (e, level)
56                 {
57                 }
58         
59                 //
60                 // Public Properties
61                 //
62
63                 public override string AttributeString {
64                         get { return null; }
65                 }
66         
67                 public override string MergeLogic {
68                         get { return "Union"; }
69                 }
70
71                 public override string PermissionSetName {
72                         get { return "Same site Web"; }
73                 }
74
75
76                 //
77                 // Public Methods
78                 //
79
80                 [MonoTODO ("(2.0) missing validations")]
81                 public void AddConnectAccess (string originScheme, CodeConnectAccess connectAccess)
82                 {
83                         if (originScheme == null)
84                                 throw new ArgumentException ("originScheme");
85
86                         // TODO (2.0) - invalid characters in originScheme
87                         if ((originScheme == AbsentOriginScheme) && (connectAccess.Scheme == CodeConnectAccess.OriginScheme)) {
88                                 throw new ArgumentOutOfRangeException ("connectAccess", Locale.GetText (
89                                         "Schema == CodeConnectAccess.OriginScheme"));
90                         }
91
92                         if (_rules.ContainsKey (originScheme)) {
93                                 // NULL has no effect
94                                 if (connectAccess != null) {
95                                         CodeConnectAccess[] existing = (CodeConnectAccess[]) _rules [originScheme];
96                                         CodeConnectAccess[] array = new CodeConnectAccess [existing.Length + 1];
97                                         Array.Copy (existing, 0, array, 0, existing.Length);
98                                         array [existing.Length] = connectAccess;
99                                         _rules [originScheme] = array;
100                                 }
101                         }
102                         else {
103                                 CodeConnectAccess[] array = new CodeConnectAccess [1];
104                                 array [0] = connectAccess;
105                                 _rules.Add (originScheme, array);
106                                 // add null to prevent access
107                         }
108                 }
109
110                 public override CodeGroup Copy ()
111                 {
112                         NetCodeGroup copy = new NetCodeGroup (MembershipCondition);
113                         copy.Name = Name;
114                         copy.Description = Description;
115                         copy.PolicyStatement = PolicyStatement;         
116
117                         foreach (CodeGroup child in Children) {
118                                 copy.AddChild (child.Copy ());  // deep copy
119                         }
120                         return copy;
121                 }
122
123                 private bool Equals (CodeConnectAccess[] rules1, CodeConnectAccess[] rules2)
124                 {
125                         for (int i=0; i < rules1.Length; i++) {
126                                 bool found = false;
127                                 for (int j=0; j < rules2.Length; j++) {
128                                         if (rules1 [i].Equals (rules2 [j])) {
129                                                 found = true;
130                                                 break;
131                                         }
132                                 }
133                                 if (!found)
134                                         return false;
135                         }
136                         return true;
137                 }
138
139                 public override bool Equals (object o)
140                 {
141                         if (!base.Equals (o))
142                                 return false;
143                         NetCodeGroup ncg = (o as NetCodeGroup);
144                         if (ncg == null) 
145                                 return false;
146         
147                         // check rules
148                         foreach (DictionaryEntry de in _rules) {
149                                 bool found = false;
150                                 CodeConnectAccess[] ccas = (CodeConnectAccess[]) ncg._rules [de.Key];
151                                 if (ccas != null)
152                                         found = Equals ((CodeConnectAccess[]) de.Value, ccas);
153                                 else
154                                         found = (de.Value == null);
155
156                                 if (!found)
157                                         return false;
158                         }
159                         return true;
160                 }
161
162                 public DictionaryEntry[] GetConnectAccessRules ()
163                 {
164                         DictionaryEntry[] result = new DictionaryEntry [_rules.Count];
165                         _rules.CopyTo (result, 0);
166                         return result;
167                 }
168
169                 public override int GetHashCode ()
170                 {
171                         if (_hashcode == 0) {
172                                 _hashcode = base.GetHashCode ();
173                                 foreach (DictionaryEntry de in _rules) {
174                                         CodeConnectAccess[] ccas = (CodeConnectAccess[]) de.Value;
175                                         if (ccas != null) {
176                                                 foreach (CodeConnectAccess cca in ccas) {
177                                                         _hashcode ^= cca.GetHashCode ();
178                                                 }
179                                         }
180                                 }
181                         }
182                         return _hashcode;
183                 }
184
185                 public override PolicyStatement Resolve (Evidence evidence)
186                 {
187                         if (evidence == null) 
188                                 throw new ArgumentNullException ("evidence");
189
190                         if (!MembershipCondition.Check (evidence))
191                                 return null;
192
193                         PermissionSet ps = null;
194                         if (this.PolicyStatement == null)
195                                 ps = new PermissionSet (PermissionState.None);
196                         else
197                                 ps = this.PolicyStatement.PermissionSet.Copy ();
198
199                         if (this.Children.Count > 0) {
200                                 foreach (CodeGroup child_cg in this.Children) {
201                                         PolicyStatement child_pst = child_cg.Resolve (evidence);
202                                         if (child_pst != null) {
203                                                 ps = ps.Union (child_pst.PermissionSet);
204                                         }
205                                 }
206                         }
207
208                         PolicyStatement pst = this.PolicyStatement.Copy ();
209                         pst.PermissionSet = ps;
210                         return pst;
211                 }
212
213                 public void ResetConnectAccess ()
214                 {
215                         _rules.Clear ();
216                 }
217
218                 public override CodeGroup ResolveMatchingCodeGroups (Evidence evidence) 
219                 {
220                         if (evidence == null)
221                                 throw new ArgumentNullException ("evidence");
222                         
223                         CodeGroup return_group = null;
224                         if (MembershipCondition.Check (evidence)) {
225                                 return_group = Copy ();
226
227                                 foreach (CodeGroup child_group in Children) {
228                                         CodeGroup matching = 
229                                                 child_group.ResolveMatchingCodeGroups (evidence);
230                                         if (matching == null)
231                                                 continue;
232                                         return_group.AddChild (matching);
233                                 }
234                         }
235
236                         return return_group;
237                 }
238
239                 [MonoTODO ("(2.0) Add new stuff (CodeConnectAccess) into XML")]
240                 protected override void CreateXml (SecurityElement element, PolicyLevel level)
241                 {
242                         base.CreateXml (element, level);
243                 }
244
245                 [MonoTODO ("(2.0) Parse new stuff (CodeConnectAccess) from XML")]
246                 protected override void ParseXml (SecurityElement e, PolicyLevel level)
247                 {
248                         base.ParseXml (e, level);
249                 }
250         }
251 }