2008-03-14 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / class / corlib / System.Security.Permissions / EnvironmentPermission.cs
1 //
2 // System.Security.Permissions.EnvironmentPermission.cs
3 //
4 // Authors:
5 //      Tim Coleman <tim@timcoleman.com>
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // Copyright (C) 2002, Tim Coleman
9 // Portions Copyright (C) 2003 Motus Technologies (http://www.motus.com)
10 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Collections;
33 using System.Runtime.InteropServices;
34 using System.Text;
35 \r
36 namespace System.Security.Permissions {\r
37 \r
38 #if NET_2_0
39         [ComVisible (true)]
40 #endif
41         [Serializable]
42         public sealed class EnvironmentPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission {
43
44                 #region Fields
45
46                 private const int version = 1;
47
48                 EnvironmentPermissionAccess flags;
49                 PermissionState _state;
50                 ArrayList readList;
51                 ArrayList writeList;
52
53                 #endregion // Fields
54
55                 #region Constructors
56
57                 public EnvironmentPermission (PermissionState state) : base ()
58                 {
59                         _state = CheckPermissionState (state, true);
60                         readList = new ArrayList ();
61                         writeList = new ArrayList ();
62                 }
63
64                 public EnvironmentPermission (EnvironmentPermissionAccess flag, string pathList) : base ()
65                 {
66                         readList = new ArrayList ();
67                         writeList = new ArrayList ();
68                         SetPathList (flag, pathList);
69                 }
70
71                 #endregion // Constructors
72
73                 #region Methods
74
75                 public void AddPathList (EnvironmentPermissionAccess flag, string pathList)
76                 {
77                         if (pathList == null)
78                                 throw new ArgumentNullException ("pathList");
79
80                         string[] paths;
81                         switch (flag) {
82                                 case EnvironmentPermissionAccess.AllAccess:
83                                         paths = pathList.Split (';');
84                                         foreach (string path in paths) {
85                                                 if (!readList.Contains (path))
86                                                         readList.Add (path);
87                                                 if (!writeList.Contains (path))
88                                                         writeList.Add (path);
89                                         }
90                                         break;
91                                 case EnvironmentPermissionAccess.NoAccess:
92                                         // ??? unit tests doesn't show removal using NoAccess ???
93                                         break;
94                                 case EnvironmentPermissionAccess.Read:
95                                         paths = pathList.Split (';');
96                                         foreach (string path in paths) {
97                                                 if (!readList.Contains (path))
98                                                         readList.Add (path);
99                                         }
100                                         break;
101                                 case EnvironmentPermissionAccess.Write:
102                                         paths = pathList.Split (';');
103                                         foreach (string path in paths) {
104                                                 if (!writeList.Contains (path))
105                                                         writeList.Add (path);
106                                         }
107                                         break;
108                                 default:
109                                         ThrowInvalidFlag (flag, false);
110                                         break;
111                         }
112                 }
113
114                 public override IPermission Copy ()
115                 {
116                         EnvironmentPermission ep = new EnvironmentPermission (_state);
117                         string path = GetPathList (EnvironmentPermissionAccess.Read);
118                         if (path != null)
119                                 ep.SetPathList (EnvironmentPermissionAccess.Read, path);
120                         path = GetPathList (EnvironmentPermissionAccess.Write);
121                         if (path != null)
122                                 ep.SetPathList (EnvironmentPermissionAccess.Write, path);
123                         return ep;
124                 }
125
126                 public override void FromXml (SecurityElement esd)
127                 {
128                         // General validation in CodeAccessPermission
129                         CheckSecurityElement (esd, "esd", version, version);
130                         // Note: we do not (yet) care about the return value 
131                         // as we only accept version 1 (min/max values)
132
133                         if (IsUnrestricted (esd))
134                                 _state = PermissionState.Unrestricted;
135
136                         string read = esd.Attribute ("Read");
137                         if ((read != null) && (read.Length > 0))
138                                 SetPathList (EnvironmentPermissionAccess.Read, read);
139
140                         string write = esd.Attribute ("Write");
141                         if ((write != null) && (write.Length > 0))
142                                 SetPathList (EnvironmentPermissionAccess.Write, write);
143                 }
144
145                 public string GetPathList (EnvironmentPermissionAccess flag)
146                 {
147                         switch (flag) {
148                                 case EnvironmentPermissionAccess.AllAccess:
149                                 case EnvironmentPermissionAccess.NoAccess:
150                                         ThrowInvalidFlag (flag, true);
151                                         break;
152                                 case EnvironmentPermissionAccess.Read:
153                                         return GetPathList (readList);
154                                 case EnvironmentPermissionAccess.Write:
155                                         return GetPathList (writeList);
156                                 default:
157                                         ThrowInvalidFlag (flag, false);
158                                         break;
159                         }
160                         return null; // never reached
161                 }
162
163                 public override IPermission Intersect (IPermission target)
164                 {
165                         EnvironmentPermission ep = Cast (target);
166                         if (ep == null)
167                                 return null;
168
169                         if (IsUnrestricted ())
170                                 return ep.Copy ();
171                         if (ep.IsUnrestricted ())
172                                 return Copy ();
173
174                         int n = 0;
175                         EnvironmentPermission result = new EnvironmentPermission (PermissionState.None);
176                         string readTarget = ep.GetPathList (EnvironmentPermissionAccess.Read);
177                         if (readTarget != null) {
178                                 string[] targets = readTarget.Split (';');
179                                 foreach (string t in targets) {
180                                         if (readList.Contains (t)) {
181                                                 result.AddPathList (EnvironmentPermissionAccess.Read, t);
182                                                 n++;
183                                         }
184                                 }
185                         }
186
187                         string writeTarget = ep.GetPathList (EnvironmentPermissionAccess.Write);
188                         if (writeTarget != null) {
189                                 string[] targets = writeTarget.Split (';');
190                                 foreach (string t in targets) {
191                                         if (writeList.Contains (t)) {
192                                                 result.AddPathList (EnvironmentPermissionAccess.Write, t);
193                                                 n++;
194                                         }
195                                 }
196                         }
197                         return ((n > 0) ? result : null);
198                 }
199
200                 public override bool IsSubsetOf (IPermission target)
201                 {
202                         EnvironmentPermission ep = Cast (target);
203                         if (ep == null)
204                                 return false;
205
206                         if (IsUnrestricted ())
207                                 return ep.IsUnrestricted ();
208                         else if (ep.IsUnrestricted ())
209                                 return true;
210
211                         foreach (string s in readList) {
212                                 if (!ep.readList.Contains (s))
213                                         return false;
214                         }
215
216                         foreach (string s in writeList) {
217                                 if (!ep.writeList.Contains (s))
218                                         return false;
219                         }
220
221                         return true;
222                 }
223
224                 public bool IsUnrestricted ()
225                 {
226                         return (_state == PermissionState.Unrestricted);
227                 }
228
229                 public void SetPathList (EnvironmentPermissionAccess flag, string pathList)
230                 {
231                         if (pathList == null)
232                                 throw new ArgumentNullException ("pathList");
233                         string[] paths;
234                         switch (flag) {
235                                 case EnvironmentPermissionAccess.AllAccess:
236                                         readList.Clear ();
237                                         writeList.Clear ();
238                                         paths = pathList.Split (';');
239                                         foreach (string path in paths) {
240                                                 readList.Add (path);
241                                                 writeList.Add (path);
242                                         }
243                                         break;
244                                 case EnvironmentPermissionAccess.NoAccess:
245                                         // ??? unit tests doesn't show removal using NoAccess ???
246                                         break;
247                                 case EnvironmentPermissionAccess.Read:
248                                         readList.Clear ();
249                                         paths = pathList.Split (';');
250                                         foreach (string path in paths) {
251                                                 readList.Add (path);
252                                         }
253                                         break;
254                                 case EnvironmentPermissionAccess.Write:
255                                         writeList.Clear ();
256                                         paths = pathList.Split (';');
257                                         foreach (string path in paths) {
258                                                 writeList.Add (path);
259                                         }
260                                         break;
261                                 default:
262                                         ThrowInvalidFlag (flag, false);
263                                         break;
264                         }
265                 }
266
267                 public override SecurityElement ToXml ()
268                 {
269                         SecurityElement se = Element (version);
270
271                         if (_state == PermissionState.Unrestricted) {
272                                 se.AddAttribute ("Unrestricted", "true");
273                         }
274                         else {
275                                 string path = GetPathList (EnvironmentPermissionAccess.Read);
276                                 if (path != null)
277                                         se.AddAttribute ("Read", path);
278                                 path = GetPathList (EnvironmentPermissionAccess.Write);
279                                 if (path != null)
280                                         se.AddAttribute ("Write", path);
281                         }
282                         return se;
283                 }
284
285                 public override IPermission Union (IPermission other)
286                 {
287                         EnvironmentPermission ep = Cast (other);
288                         if (ep == null)
289                                 return Copy ();
290
291                         if (IsUnrestricted () || ep.IsUnrestricted ())
292                                 return new EnvironmentPermission (PermissionState.Unrestricted);
293
294                         if (IsEmpty () && ep.IsEmpty ())
295                                 return null;
296
297                         EnvironmentPermission result = (EnvironmentPermission) Copy ();
298                         string path = ep.GetPathList (EnvironmentPermissionAccess.Read);
299                         if (path != null) 
300                                 result.AddPathList (EnvironmentPermissionAccess.Read, path);
301                         path = ep.GetPathList (EnvironmentPermissionAccess.Write);
302                         if (path != null)
303                                 result.AddPathList (EnvironmentPermissionAccess.Write, path);
304                         return result;
305                 }
306
307                 // IBuiltInPermission
308                 int IBuiltInPermission.GetTokenIndex ()
309                 {
310                         return (int) BuiltInToken.Environment;
311                 }
312
313                 // helpers
314
315                 private bool IsEmpty ()
316                 {
317                         return ((_state == PermissionState.None) && (readList.Count == 0) && (writeList.Count == 0));
318                 }
319
320                 private EnvironmentPermission Cast (IPermission target)
321                 {
322                         if (target == null)
323                                 return null;
324
325                         EnvironmentPermission ep = (target as EnvironmentPermission);
326                         if (ep == null) {
327                                 ThrowInvalidPermission (target, typeof (EnvironmentPermission));
328                         }
329
330                         return ep;
331                 }
332
333                 internal void ThrowInvalidFlag (EnvironmentPermissionAccess flag, bool context) 
334                 {
335                         string msg = null;
336                         if (context)
337                                 msg = Locale.GetText ("Unknown flag '{0}'.");
338                         else
339                                 msg = Locale.GetText ("Invalid flag '{0}' in this context.");
340                         throw new ArgumentException (String.Format (msg, flag), "flag");
341                 }
342
343                 private string GetPathList (ArrayList list)
344                 {
345                         if (IsUnrestricted ())
346                                 return String.Empty;
347 #if NET_2_0
348                         if (list.Count == 0)
349                                 return String.Empty;
350 #else
351                         if (list.Count == 0)
352                                 return null;
353 #endif
354                         StringBuilder sb = new StringBuilder ();
355                         foreach (string path in list) {
356                                 sb.Append (path);
357                                 sb.Append (";");
358                         }
359
360                         string result = sb.ToString ();
361                         // remove last ';'
362                         int n = result.Length;
363                         if (n > 0)
364                                 return result.Substring (0, n - 1);
365 #if NET_2_0
366                         return String.Empty;
367 #else
368                         return ((_state == PermissionState.Unrestricted) ? String.Empty : null);
369 #endif
370                 }
371
372                 #endregion // Methods
373         }
374 }