Merge pull request #2542 from akoeplinger/remove-changelog
[mono.git] / mcs / class / System.Messaging / System.Messaging / MessageQueuePermission.cs
1 //
2 // System.Messaging.MessageQueuePermission.cs
3 //
4 // Authors:
5 //      Peter Van Isacker (sclytrack@planetinternet.be)
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // (C) 2003 Peter Van Isacker
9 // Copyright (C) 2004 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.Globalization;
32 using System.Security;
33 using System.Security.Permissions;
34
35 namespace System.Messaging {
36
37         [Serializable]
38         public sealed class MessageQueuePermission: CodeAccessPermission, IUnrestrictedPermission {
39
40                 private const int version = 1;
41
42                 private MessageQueuePermissionEntryCollection _list;
43                 private bool _unrestricted;
44
45                 public MessageQueuePermission ()
46                 {
47                         _list = new MessageQueuePermissionEntryCollection (this);
48                 }
49                 
50                 public MessageQueuePermission (MessageQueuePermissionEntry[] permissionAccessEntries)
51                         : this ()
52                 {
53                         foreach (MessageQueuePermissionEntry entry in permissionAccessEntries)
54                                 _list.Add (entry);
55                 }
56                 
57                 public MessageQueuePermission (PermissionState state)
58                         : this ()
59                 {
60                         _unrestricted = (state == PermissionState.Unrestricted);
61                 }
62                 
63                 public MessageQueuePermission (MessageQueuePermissionAccess permissionAccess, string path)
64                         : this ()
65                 {
66                         MessageQueuePermissionEntry entry = new MessageQueuePermissionEntry (permissionAccess, path);
67                         _list.Add (entry);
68                 }
69                 
70                 public MessageQueuePermission (MessageQueuePermissionAccess permissionAccess,
71                         string machineName, string label, string category) : this ()
72                 {
73                         MessageQueuePermissionEntry entry = new MessageQueuePermissionEntry (permissionAccess, machineName, label, category);
74                         _list.Add (entry);
75                 }
76                 
77                 public MessageQueuePermissionEntryCollection PermissionEntries {
78                         get { return _list; }
79                 }
80                 
81                 public override IPermission Copy ()
82                 {
83                         if (_unrestricted)
84                                 return new MessageQueuePermission (PermissionState.Unrestricted);
85                         else {
86                                 MessageQueuePermission copy = new MessageQueuePermission (PermissionState.None);
87                                 foreach (MessageQueuePermissionEntry entry in _list)
88                                         copy._list.Add (entry);
89                                 return copy;
90                         }
91                 }
92
93                 public bool IsUnrestricted () 
94                 {
95                         return _unrestricted;
96                 }
97
98                 [MonoTODO]
99                 public override void FromXml (SecurityElement securityElement)
100                 {
101                         CheckSecurityElement (securityElement, "securityElement", version, version);
102                         // Note: we do not (yet) care about the return value 
103                         // as we only accept version 1 (min/max values)
104
105                         _unrestricted = (IsUnrestricted (securityElement));
106
107                         // TODO read elements
108                 }
109                 
110                 [MonoTODO]
111                 public override IPermission Intersect (IPermission target)
112                 {
113                         Cast (target);
114                         return null;
115                 }
116                 
117                 [MonoTODO]
118                 public override bool IsSubsetOf (IPermission target)
119                 {
120                         Cast (target);
121                         return false;
122                 }
123                 
124                 [MonoTODO]
125                 public override SecurityElement ToXml ()
126                 {
127                         SecurityElement se = Element (version);
128                         if (_unrestricted)
129                                 se.AddAttribute ("Unrestricted", "true");
130                         else {
131                                 // TODO
132                         }
133                         return se;
134                 }
135                 
136                 [MonoTODO]
137                 public override IPermission Union (IPermission target)
138                 {
139                         Cast (target);
140                         return null;
141                 }
142
143                 // helpers
144
145                 private bool IsEmpty ()
146                 {
147                         return (!_unrestricted && (_list.Count == 0));
148                 }
149
150                 private MessageQueuePermission Cast (IPermission target)
151                 {
152                         if (target == null)
153                                 return null;
154
155                         MessageQueuePermission mqp = (target as MessageQueuePermission);
156                         if (mqp == null) {
157                                 ThrowInvalidPermission (target, typeof (MessageQueuePermission));
158                         }
159
160                         return mqp;
161                 }
162
163                 // static helpers
164
165                 private static char[] invalidChars = new char[] { '\t', '\n', '\v', '\f', '\r', ' ', '\\', '\x160' };
166
167                 internal static void ValidateMachineName (string name)
168                 {
169                         // FIXME: maybe other checks are required (but not documented)
170                         if ((name == null) || (name.Length == 0) || (name.IndexOfAny (invalidChars) != -1)) {
171                                 string msg = Locale.GetText ("Invalid machine name '{0}'.");
172                                 if (name == null)
173                                         name = "(null)";
174                                 msg = String.Format (msg, name);
175                                 throw new ArgumentException (msg, "MachineName");
176                         }
177                 }
178
179                 internal static void ValidatePath (string path)
180                 {
181                         // FIXME: maybe other checks are required (but not documented)
182                         if ((path.Length > 0) && (path [0] != '\\')) {
183                                 string msg = Locale.GetText ("Invalid path '{0}'.");
184                                 throw new ArgumentException (String.Format (msg, path), "Path");
185                         }
186                 }
187
188                 // NOTE: The following static methods should be moved out to a (static?) class 
189                 // if (ever) System.Drawing.dll gets more than one permission in it's assembly.
190
191                 // snippet moved from FileIOPermission (nickd) to be reused in all derived classes
192                 internal SecurityElement Element (int version) 
193                 {
194                         SecurityElement se = new SecurityElement ("IPermission");
195                         Type type = this.GetType ();
196                         se.AddAttribute ("class", type.FullName + ", " + type.Assembly.ToString ().Replace ('\"', '\''));
197                         se.AddAttribute ("version", version.ToString ());
198                         return se;
199                 }
200
201                 internal static PermissionState CheckPermissionState (PermissionState state, bool allowUnrestricted)
202                 {
203                         string msg;
204                         switch (state) {
205                         case PermissionState.None:
206                                 break;
207                         case PermissionState.Unrestricted:
208                                 if (!allowUnrestricted) {
209                                         msg = Locale.GetText ("Unrestricted isn't not allowed for identity permissions.");
210                                         throw new ArgumentException (msg, "state");
211                                 }
212                                 break;
213                         default:
214                                 msg = String.Format (Locale.GetText ("Invalid enum {0}"), state);
215                                 throw new ArgumentException (msg, "state");
216                         }
217                         return state;
218                 }
219
220                 // logic isn't identical to CodeAccessPermission.CheckSecurityElement - see unit tests
221                 internal static int CheckSecurityElement (SecurityElement se, string parameterName, int minimumVersion, int maximumVersion) 
222                 {
223                         if (se == null)
224                                 throw new ArgumentNullException (parameterName);
225
226                         if (se.Attribute ("class") == null) {
227                                 string msg = Locale.GetText ("Missing 'class' attribute.");
228                                 throw new ArgumentException (msg, parameterName);
229                         }
230
231                         // we assume minimum version if no version number is supplied
232                         int version = minimumVersion;
233                         string v = se.Attribute ("version");
234                         if (v != null) {
235                                 try {
236                                         version = Int32.Parse (v);
237                                 }
238                                 catch (Exception e) {
239                                         string msg = Locale.GetText ("Couldn't parse version from '{0}'.");
240                                         msg = String.Format (msg, v);
241                                         throw new ArgumentException (msg, parameterName, e);
242                                 }
243                         }
244
245                         if ((version < minimumVersion) || (version > maximumVersion)) {
246                                 string msg = Locale.GetText ("Unknown version '{0}', expected versions between ['{1}','{2}'].");
247                                 msg = String.Format (msg, version, minimumVersion, maximumVersion);
248                                 throw new ArgumentException (msg, parameterName);
249                         }
250                         return version;
251                 }
252
253                 // must be called after CheckSecurityElement (i.e. se != null)
254                 internal static bool IsUnrestricted (SecurityElement se) 
255                 {
256                         string value = se.Attribute ("Unrestricted");
257                         if (value == null)
258                                 return false;
259                         return (String.Compare (value, Boolean.TrueString, true, CultureInfo.InvariantCulture) == 0);
260                 }
261
262                 internal static void ThrowInvalidPermission (IPermission target, Type expected) 
263                 {
264                         string msg = Locale.GetText ("Invalid permission type '{0}', expected type '{1}'.");
265                         msg = String.Format (msg, target.GetType (), expected);
266                         throw new ArgumentException (msg, "target");
267                 }
268         }
269 }