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