2010-05-27 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / System.Security.Permissions / RegistryPermission.cs
blob8fd282fde45a01264c63933d8abc31ba2df23f6d
1 //
2 // System.Security.Permissions.RegistryPermission.cs
3 //
4 // Author
5 // Sebastien Pouliot <sebastien@ximian.com>
6 //
7 // Copyright (C) 2003 Motus Technologies. http://www.motus.com
8 // Copyright (C) 2004-2005 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.
30 using System.Collections;
31 using System.Globalization;
32 using System.Text;
34 using System.Runtime.InteropServices;
35 using System.Security.AccessControl;
37 namespace System.Security.Permissions {
39 [Serializable]
40 [ComVisible (true)]
41 public sealed class RegistryPermission
42 : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission {
44 private const int version = 1;
46 private PermissionState _state;
47 // private RegistryPermissionAccess _access;
48 private ArrayList createList;
49 private ArrayList readList;
50 private ArrayList writeList;
51 // private AccessControlActions _control;
52 // Constructors
54 public RegistryPermission (PermissionState state)
56 _state = CheckPermissionState (state, true);
57 createList = new ArrayList ();
58 readList = new ArrayList ();
59 writeList = new ArrayList ();
62 public RegistryPermission (RegistryPermissionAccess access, string pathList)
64 _state = PermissionState.None;
65 createList = new ArrayList ();
66 readList = new ArrayList ();
67 writeList = new ArrayList ();
68 AddPathList (access, pathList);
70 public RegistryPermission (RegistryPermissionAccess access, AccessControlActions control, string pathList)
72 if (!Enum.IsDefined (typeof (AccessControlActions), control)) {
73 string msg = String.Format (Locale.GetText ("Invalid enum {0}"), control);
74 throw new ArgumentException (msg, "AccessControlActions");
76 _state = PermissionState.None;
77 AddPathList (access, control, pathList);
80 // Properties
82 // Methods
84 public void AddPathList (RegistryPermissionAccess access, string pathList)
86 if (pathList == null)
87 throw new ArgumentNullException ("pathList");
89 switch (access) {
90 case RegistryPermissionAccess.AllAccess:
91 AddWithUnionKey (createList, pathList);
92 AddWithUnionKey (readList, pathList);
93 AddWithUnionKey (writeList, pathList);
94 break;
95 case RegistryPermissionAccess.NoAccess:
96 // ??? unit tests doesn't show removal using NoAccess ???
97 break;
98 case RegistryPermissionAccess.Create:
99 AddWithUnionKey (createList, pathList);
100 break;
101 case RegistryPermissionAccess.Read:
102 AddWithUnionKey (readList, pathList);
103 break;
104 case RegistryPermissionAccess.Write:
105 AddWithUnionKey (writeList, pathList);
106 break;
107 default:
108 ThrowInvalidFlag (access, false);
109 break;
112 [MonoTODO ("(2.0) Access Control isn't implemented")]
113 public void AddPathList (RegistryPermissionAccess access, AccessControlActions control, string pathList)
115 throw new NotImplementedException ();
117 public string GetPathList (RegistryPermissionAccess access)
119 switch (access) {
120 case RegistryPermissionAccess.AllAccess:
121 case RegistryPermissionAccess.NoAccess:
122 ThrowInvalidFlag (access, true);
123 break;
124 case RegistryPermissionAccess.Create:
125 return GetPathList (createList);
126 case RegistryPermissionAccess.Read:
127 return GetPathList (readList);
128 case RegistryPermissionAccess.Write:
129 return GetPathList (writeList);
130 default:
131 ThrowInvalidFlag (access, false);
132 break;
134 return null; // never reached
137 public void SetPathList (RegistryPermissionAccess access, string pathList)
139 if (pathList == null)
140 throw new ArgumentNullException ("pathList");
142 string[] paths;
143 switch (access) {
144 case RegistryPermissionAccess.AllAccess:
145 createList.Clear ();
146 readList.Clear ();
147 writeList.Clear ();
148 paths = pathList.Split (';');
149 foreach (string path in paths) {
150 createList.Add (path);
151 readList.Add (path);
152 writeList.Add (path);
154 break;
155 case RegistryPermissionAccess.NoAccess:
156 // ??? unit tests doesn't show removal using NoAccess ???
157 break;
158 case RegistryPermissionAccess.Create:
159 createList.Clear ();
160 paths = pathList.Split (';');
161 foreach (string path in paths) {
162 createList.Add (path);
164 break;
165 case RegistryPermissionAccess.Read:
166 readList.Clear ();
167 paths = pathList.Split (';');
168 foreach (string path in paths) {
169 readList.Add (path);
171 break;
172 case RegistryPermissionAccess.Write:
173 writeList.Clear ();
174 paths = pathList.Split (';');
175 foreach (string path in paths) {
176 writeList.Add (path);
178 break;
179 default:
180 ThrowInvalidFlag (access, false);
181 break;
185 public override IPermission Copy ()
187 RegistryPermission rp = new RegistryPermission (_state);
189 string path = GetPathList (RegistryPermissionAccess.Create);
190 if (path != null)
191 rp.SetPathList (RegistryPermissionAccess.Create, path);
193 path = GetPathList (RegistryPermissionAccess.Read);
194 if (path != null)
195 rp.SetPathList (RegistryPermissionAccess.Read, path);
197 path = GetPathList (RegistryPermissionAccess.Write);
198 if (path != null)
199 rp.SetPathList (RegistryPermissionAccess.Write, path);
200 return rp;
203 public override void FromXml (SecurityElement esd)
205 // General validation in CodeAccessPermission
206 CheckSecurityElement (esd, "esd", version, version);
207 // Note: we do not (yet) care about the return value
208 // as we only accept version 1 (min/max values)
210 // General validation in CodeAccessPermission
211 CheckSecurityElement (esd, "esd", version, version);
212 // Note: we do not (yet) care about the return value
213 // as we only accept version 1 (min/max values)
215 if (IsUnrestricted (esd))
216 _state = PermissionState.Unrestricted;
218 string create = esd.Attribute ("Create");
219 if ((create != null) && (create.Length > 0))
220 SetPathList (RegistryPermissionAccess.Create, create);
222 string read = esd.Attribute ("Read");
223 if ((read != null) && (read.Length > 0))
224 SetPathList (RegistryPermissionAccess.Read, read);
226 string write = esd.Attribute ("Write");
227 if ((write != null) && (write.Length > 0))
228 SetPathList (RegistryPermissionAccess.Write, write);
231 public override IPermission Intersect (IPermission target)
233 RegistryPermission rp = Cast (target);
234 if (rp == null)
235 return null;
237 if (IsUnrestricted ())
238 return rp.Copy ();
239 if (rp.IsUnrestricted ())
240 return Copy ();
242 RegistryPermission result = new RegistryPermission (PermissionState.None);
244 IntersectKeys (createList, rp.createList, result.createList);
245 IntersectKeys (readList, rp.readList, result.readList);
246 IntersectKeys (writeList, rp.writeList, result.writeList);
248 return (result.IsEmpty () ? null : result);
251 public override bool IsSubsetOf (IPermission target)
253 RegistryPermission rp = Cast (target);
254 if (rp == null)
255 return false;
256 if (rp.IsEmpty ())
257 return IsEmpty ();
259 if (IsUnrestricted ())
260 return rp.IsUnrestricted ();
261 else if (rp.IsUnrestricted ())
262 return true;
264 if (!KeyIsSubsetOf (createList, rp.createList))
265 return false;
266 if (!KeyIsSubsetOf (readList, rp.readList))
267 return false;
268 if (!KeyIsSubsetOf (writeList, rp.writeList))
269 return false;
271 return true;
274 public bool IsUnrestricted ()
276 return (_state == PermissionState.Unrestricted);
279 public override SecurityElement ToXml ()
281 SecurityElement se = Element (version);
283 if (_state == PermissionState.Unrestricted) {
284 se.AddAttribute ("Unrestricted", "true");
286 else {
287 string path = GetPathList (RegistryPermissionAccess.Create);
288 if (path != null)
289 se.AddAttribute ("Create", path);
290 path = GetPathList (RegistryPermissionAccess.Read);
291 if (path != null)
292 se.AddAttribute ("Read", path);
293 path = GetPathList (RegistryPermissionAccess.Write);
294 if (path != null)
295 se.AddAttribute ("Write", path);
297 return se;
300 public override IPermission Union (IPermission other)
302 RegistryPermission rp = Cast (other);
303 if (rp == null)
304 return Copy ();
306 if (IsUnrestricted () || rp.IsUnrestricted ())
307 return new RegistryPermission (PermissionState.Unrestricted);
309 if (IsEmpty () && rp.IsEmpty ())
310 return null;
312 RegistryPermission result = (RegistryPermission) Copy ();
313 string path = rp.GetPathList (RegistryPermissionAccess.Create);
314 if (path != null)
315 result.AddPathList (RegistryPermissionAccess.Create, path);
316 path = rp.GetPathList (RegistryPermissionAccess.Read);
317 if (path != null)
318 result.AddPathList (RegistryPermissionAccess.Read, path);
319 path = rp.GetPathList (RegistryPermissionAccess.Write);
320 if (path != null)
321 result.AddPathList (RegistryPermissionAccess.Write, path);
322 return result;
325 // IBuiltInPermission
326 int IBuiltInPermission.GetTokenIndex ()
328 return (int) BuiltInToken.Registry;
331 // helpers
333 private bool IsEmpty ()
335 return ((_state == PermissionState.None) && (createList.Count == 0) &&
336 (readList.Count == 0) && (writeList.Count == 0));
339 private RegistryPermission Cast (IPermission target)
341 if (target == null)
342 return null;
344 RegistryPermission rp = (target as RegistryPermission);
345 if (rp == null) {
346 ThrowInvalidPermission (target, typeof (RegistryPermission));
349 return rp;
352 internal void ThrowInvalidFlag (RegistryPermissionAccess flag, bool context)
354 string msg = null;
355 if (context)
356 msg = Locale.GetText ("Unknown flag '{0}'.");
357 else
358 msg = Locale.GetText ("Invalid flag '{0}' in this context.");
359 throw new ArgumentException (String.Format (msg, flag), "flag");
362 private string GetPathList (ArrayList list)
364 if (IsUnrestricted ())
365 return String.Empty;
366 if (list.Count == 0)
367 return String.Empty;
368 StringBuilder sb = new StringBuilder ();
369 foreach (string path in list) {
370 sb.Append (path);
371 sb.Append (";");
374 string result = sb.ToString ();
375 // remove last ';'
376 int n = result.Length;
377 if (n > 0)
378 return result.Substring (0, n - 1);
379 return String.Empty;
382 internal bool KeyIsSubsetOf (IList local, IList target)
384 bool result = false;
385 foreach (string l in local) {
386 foreach (string t in target) {
387 if (l.StartsWith (t)) {
388 result = true;
389 break;
392 if (!result)
393 return false;
395 return true;
398 internal void AddWithUnionKey (IList list, string pathList)
400 string[] paths = pathList.Split (';');
401 foreach (string path in paths) {
402 int len = list.Count;
403 if (len == 0) {
404 list.Add (path);
406 else {
407 for (int i=0; i < len; i++) {
408 string s = (string) list [i];
409 if (s.StartsWith (path)) {
410 // replace (with reduced version)
411 list [i] = path;
413 else if (path.StartsWith (s)) {
414 // no need to add
416 else {
417 list.Add (path);
424 internal void IntersectKeys (IList local, IList target, IList result)
426 foreach (string l in local) {
427 foreach (string t in target) {
428 if (t.Length > l.Length) {
429 if (t.StartsWith (l))
430 result.Add (t);
432 else {
433 if (l.StartsWith (t))
434 result.Add (l);