Merge branch 'master' of http://github.com/mono/mono
[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
36 namespace System.Security.Permissions {
37
38         [ComVisible (true)]
39         [Serializable]
40         public sealed class EnvironmentPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission {
41
42                 #region Fields
43
44                 private const int version = 1;
45
46 //              EnvironmentPermissionAccess flags;
47                 PermissionState _state;
48                 ArrayList readList;
49                 ArrayList writeList;
50
51                 #endregion // Fields
52
53                 #region Constructors
54
55                 public EnvironmentPermission (PermissionState state) : base ()
56                 {
57                         _state = CheckPermissionState (state, true);
58                         readList = new ArrayList ();
59                         writeList = new ArrayList ();
60                 }
61
62                 public EnvironmentPermission (EnvironmentPermissionAccess flag, string pathList) : base ()
63                 {
64                         readList = new ArrayList ();
65                         writeList = new ArrayList ();
66                         SetPathList (flag, pathList);
67                 }
68
69                 #endregion // Constructors
70
71                 #region Methods
72
73                 public void AddPathList (EnvironmentPermissionAccess flag, string pathList)
74                 {
75                         if (pathList == null)
76                                 throw new ArgumentNullException ("pathList");
77
78                         string[] paths;
79                         switch (flag) {
80                                 case EnvironmentPermissionAccess.AllAccess:
81                                         paths = pathList.Split (';');
82                                         foreach (string path in paths) {
83                                                 if (!readList.Contains (path))
84                                                         readList.Add (path);
85                                                 if (!writeList.Contains (path))
86                                                         writeList.Add (path);
87                                         }
88                                         break;
89                                 case EnvironmentPermissionAccess.NoAccess:
90                                         // ??? unit tests doesn't show removal using NoAccess ???
91                                         break;
92                                 case EnvironmentPermissionAccess.Read:
93                                         paths = pathList.Split (';');
94                                         foreach (string path in paths) {
95                                                 if (!readList.Contains (path))
96                                                         readList.Add (path);
97                                         }
98                                         break;
99                                 case EnvironmentPermissionAccess.Write:
100                                         paths = pathList.Split (';');
101                                         foreach (string path in paths) {
102                                                 if (!writeList.Contains (path))
103                                                         writeList.Add (path);
104                                         }
105                                         break;
106                                 default:
107                                         ThrowInvalidFlag (flag, false);
108                                         break;
109                         }
110                 }
111
112                 public override IPermission Copy ()
113                 {
114                         EnvironmentPermission ep = new EnvironmentPermission (_state);
115                         string path = GetPathList (EnvironmentPermissionAccess.Read);
116                         if (path != null)
117                                 ep.SetPathList (EnvironmentPermissionAccess.Read, path);
118                         path = GetPathList (EnvironmentPermissionAccess.Write);
119                         if (path != null)
120                                 ep.SetPathList (EnvironmentPermissionAccess.Write, path);
121                         return ep;
122                 }
123
124                 public override void FromXml (SecurityElement esd)
125                 {
126                         // General validation in CodeAccessPermission
127                         CheckSecurityElement (esd, "esd", version, version);
128                         // Note: we do not (yet) care about the return value 
129                         // as we only accept version 1 (min/max values)
130
131                         if (IsUnrestricted (esd))
132                                 _state = PermissionState.Unrestricted;
133
134                         string read = esd.Attribute ("Read");
135                         if ((read != null) && (read.Length > 0))
136                                 SetPathList (EnvironmentPermissionAccess.Read, read);
137
138                         string write = esd.Attribute ("Write");
139                         if ((write != null) && (write.Length > 0))
140                                 SetPathList (EnvironmentPermissionAccess.Write, write);
141                 }
142
143                 public string GetPathList (EnvironmentPermissionAccess flag)
144                 {
145                         switch (flag) {
146                                 case EnvironmentPermissionAccess.AllAccess:
147                                 case EnvironmentPermissionAccess.NoAccess:
148                                         ThrowInvalidFlag (flag, true);
149                                         break;
150                                 case EnvironmentPermissionAccess.Read:
151                                         return GetPathList (readList);
152                                 case EnvironmentPermissionAccess.Write:
153                                         return GetPathList (writeList);
154                                 default:
155                                         ThrowInvalidFlag (flag, false);
156                                         break;
157                         }
158                         return null; // never reached
159                 }
160
161                 public override IPermission Intersect (IPermission target)
162                 {
163                         EnvironmentPermission ep = Cast (target);
164                         if (ep == null)
165                                 return null;
166
167                         if (IsUnrestricted ())
168                                 return ep.Copy ();
169                         if (ep.IsUnrestricted ())
170                                 return Copy ();
171
172                         int n = 0;
173                         EnvironmentPermission result = new EnvironmentPermission (PermissionState.None);
174                         string readTarget = ep.GetPathList (EnvironmentPermissionAccess.Read);
175                         if (readTarget != null) {
176                                 string[] targets = readTarget.Split (';');
177                                 foreach (string t in targets) {
178                                         if (readList.Contains (t)) {
179                                                 result.AddPathList (EnvironmentPermissionAccess.Read, t);
180                                                 n++;
181                                         }
182                                 }
183                         }
184
185                         string writeTarget = ep.GetPathList (EnvironmentPermissionAccess.Write);
186                         if (writeTarget != null) {
187                                 string[] targets = writeTarget.Split (';');
188                                 foreach (string t in targets) {
189                                         if (writeList.Contains (t)) {
190                                                 result.AddPathList (EnvironmentPermissionAccess.Write, t);
191                                                 n++;
192                                         }
193                                 }
194                         }
195                         return ((n > 0) ? result : null);
196                 }
197
198                 public override bool IsSubsetOf (IPermission target)
199                 {
200                         EnvironmentPermission ep = Cast (target);
201                         if (ep == null)
202                                 return false;
203
204                         if (IsUnrestricted ())
205                                 return ep.IsUnrestricted ();
206                         else if (ep.IsUnrestricted ())
207                                 return true;
208
209                         foreach (string s in readList) {
210                                 if (!ep.readList.Contains (s))
211                                         return false;
212                         }
213
214                         foreach (string s in writeList) {
215                                 if (!ep.writeList.Contains (s))
216                                         return false;
217                         }
218
219                         return true;
220                 }
221
222                 public bool IsUnrestricted ()
223                 {
224                         return (_state == PermissionState.Unrestricted);
225                 }
226
227                 public void SetPathList (EnvironmentPermissionAccess flag, string pathList)
228                 {
229                         if (pathList == null)
230                                 throw new ArgumentNullException ("pathList");
231                         string[] paths;
232                         switch (flag) {
233                                 case EnvironmentPermissionAccess.AllAccess:
234                                         readList.Clear ();
235                                         writeList.Clear ();
236                                         paths = pathList.Split (';');
237                                         foreach (string path in paths) {
238                                                 readList.Add (path);
239                                                 writeList.Add (path);
240                                         }
241                                         break;
242                                 case EnvironmentPermissionAccess.NoAccess:
243                                         // ??? unit tests doesn't show removal using NoAccess ???
244                                         break;
245                                 case EnvironmentPermissionAccess.Read:
246                                         readList.Clear ();
247                                         paths = pathList.Split (';');
248                                         foreach (string path in paths) {
249                                                 readList.Add (path);
250                                         }
251                                         break;
252                                 case EnvironmentPermissionAccess.Write:
253                                         writeList.Clear ();
254                                         paths = pathList.Split (';');
255                                         foreach (string path in paths) {
256                                                 writeList.Add (path);
257                                         }
258                                         break;
259                                 default:
260                                         ThrowInvalidFlag (flag, false);
261                                         break;
262                         }
263                 }
264
265                 public override SecurityElement ToXml ()
266                 {
267                         SecurityElement se = Element (version);
268
269                         if (_state == PermissionState.Unrestricted) {
270                                 se.AddAttribute ("Unrestricted", "true");
271                         }
272                         else {
273                                 string path = GetPathList (EnvironmentPermissionAccess.Read);
274                                 if (path != null)
275                                         se.AddAttribute ("Read", path);
276                                 path = GetPathList (EnvironmentPermissionAccess.Write);
277                                 if (path != null)
278                                         se.AddAttribute ("Write", path);
279                         }
280                         return se;
281                 }
282
283                 public override IPermission Union (IPermission other)
284                 {
285                         EnvironmentPermission ep = Cast (other);
286                         if (ep == null)
287                                 return Copy ();
288
289                         if (IsUnrestricted () || ep.IsUnrestricted ())
290                                 return new EnvironmentPermission (PermissionState.Unrestricted);
291
292                         if (IsEmpty () && ep.IsEmpty ())
293                                 return null;
294
295                         EnvironmentPermission result = (EnvironmentPermission) Copy ();
296                         string path = ep.GetPathList (EnvironmentPermissionAccess.Read);
297                         if (path != null) 
298                                 result.AddPathList (EnvironmentPermissionAccess.Read, path);
299                         path = ep.GetPathList (EnvironmentPermissionAccess.Write);
300                         if (path != null)
301                                 result.AddPathList (EnvironmentPermissionAccess.Write, path);
302                         return result;
303                 }
304
305                 // IBuiltInPermission
306                 int IBuiltInPermission.GetTokenIndex ()
307                 {
308                         return (int) BuiltInToken.Environment;
309                 }
310
311                 // helpers
312
313                 private bool IsEmpty ()
314                 {
315                         return ((_state == PermissionState.None) && (readList.Count == 0) && (writeList.Count == 0));
316                 }
317
318                 private EnvironmentPermission Cast (IPermission target)
319                 {
320                         if (target == null)
321                                 return null;
322
323                         EnvironmentPermission ep = (target as EnvironmentPermission);
324                         if (ep == null) {
325                                 ThrowInvalidPermission (target, typeof (EnvironmentPermission));
326                         }
327
328                         return ep;
329                 }
330
331                 internal void ThrowInvalidFlag (EnvironmentPermissionAccess flag, bool context) 
332                 {
333                         string msg = null;
334                         if (context)
335                                 msg = Locale.GetText ("Unknown flag '{0}'.");
336                         else
337                                 msg = Locale.GetText ("Invalid flag '{0}' in this context.");
338                         throw new ArgumentException (String.Format (msg, flag), "flag");
339                 }
340
341                 private string GetPathList (ArrayList list)
342                 {
343                         if (IsUnrestricted ())
344                                 return String.Empty;
345                         if (list.Count == 0)
346                                 return String.Empty;
347                         StringBuilder sb = new StringBuilder ();
348                         foreach (string path in list) {
349                                 sb.Append (path);
350                                 sb.Append (";");
351                         }
352
353                         string result = sb.ToString ();
354                         // remove last ';'
355                         int n = result.Length;
356                         if (n > 0)
357                                 return result.Substring (0, n - 1);
358
359                         return String.Empty;
360                 }
361
362                 #endregion // Methods
363         }
364 }