* Makefile: Don't build make-map.exe.
[mono.git] / mcs / class / System.Data / System.Data.Common / DbDataPermission.cs
1 //
2 // System.Data.Common.DbDataPermission.cs
3 //
4 // Authors:
5 //      Rodrigo Moya (rodrigo@ximian.com)
6 //      Tim Coleman (tim@timcoleman.com)
7 //      Sebastien Pouliot  <sebastien@ximian.com>
8 //
9 // (C) Ximian, Inc
10 // Copyright (C) Tim Coleman, 2002-2003
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System.Collections;
34 using System.Security;
35 using System.Security.Permissions;
36
37 namespace System.Data.Common {
38
39         [Serializable]
40         public abstract class DBDataPermission : CodeAccessPermission, IUnrestrictedPermission {
41
42                 #region Fields
43
44                 private const int version = 1;
45
46                 private bool allowBlankPassword;
47                 private PermissionState state;
48                 private Hashtable _connections;
49
50                 #endregion // Fields
51
52                 #region Constructors
53
54 #if NET_2_0
55                 [Obsolete ("use DBDataPermission (PermissionState.None)", true)]
56 #endif
57                 protected DBDataPermission () 
58                         : this (PermissionState.None)
59                 {
60                 }
61
62                 protected DBDataPermission (DBDataPermission permission)
63                 {
64                         if (permission == null)
65                                 throw new ArgumentNullException ("permission");
66
67                         state = permission.state;
68                         if (state != PermissionState.Unrestricted) {
69                                 allowBlankPassword = permission.allowBlankPassword;
70                                 _connections = (Hashtable) permission._connections.Clone ();
71                         }
72                 }
73
74                 protected DBDataPermission (DBDataPermissionAttribute permissionAttribute)
75                 {
76                         if (permissionAttribute == null)
77                                 throw new ArgumentNullException ("permissionAttribute");
78
79                         _connections = new Hashtable ();
80                         if (permissionAttribute.Unrestricted) {
81                                 state = PermissionState.Unrestricted;
82                         }
83                         else {
84                                 state = PermissionState.None;
85                                 allowBlankPassword = permissionAttribute.AllowBlankPassword;
86                                 if (permissionAttribute.ConnectionString.Length > 0) {
87                                         Add (permissionAttribute.ConnectionString, permissionAttribute.KeyRestrictions, 
88                                                 permissionAttribute.KeyRestrictionBehavior);
89                                 }
90                         }
91                 }
92
93                 protected DBDataPermission (PermissionState state) 
94                 {
95                         this.state = PermissionHelper.CheckPermissionState (state, true);
96                         _connections = new Hashtable ();
97                 }
98
99 #if NET_2_0
100                 [Obsolete ("use DBDataPermission (PermissionState.None)", true)]
101                 protected 
102 #else
103                 public
104 #endif
105                 DBDataPermission (PermissionState state, bool allowBlankPassword)
106                         : this (state)
107                 {
108                         this.allowBlankPassword = allowBlankPassword;
109                 }
110
111                 #endregion // Constructors
112
113                 #region Properties
114
115                 public bool AllowBlankPassword {
116                         get { return allowBlankPassword; }
117                         set { allowBlankPassword = value; }
118                 }
119                 
120                 #endregion // Properties
121
122                 #region Methods
123
124                 public virtual void Add (string connectionString, string restrictions, KeyRestrictionBehavior behavior)
125                 {
126                         state = PermissionState.None;
127                         _connections [connectionString] = new object [2] { restrictions, behavior };
128                 }
129
130                 protected void Clear ()
131                 {
132                         _connections.Clear ();
133                 }
134
135                 public override IPermission Copy () 
136                 {
137                         DBDataPermission dbdp = CreateInstance ();
138                         dbdp.allowBlankPassword = this.allowBlankPassword;
139                         dbdp._connections = (Hashtable) this._connections.Clone ();
140                         return dbdp;
141                 }
142
143                 protected virtual DBDataPermission CreateInstance ()
144                 {
145                         return (DBDataPermission) Activator.CreateInstance (this.GetType (), new object [1] { PermissionState.None });
146                 }
147
148                 public override void FromXml (SecurityElement securityElement) 
149                 {
150                         PermissionHelper.CheckSecurityElement (securityElement, "securityElement", version, version);
151                         // Note: we do not (yet) care about the return value 
152                         // as we only accept version 1 (min/max values)
153
154                         state = (PermissionHelper.IsUnrestricted (securityElement) ? 
155                                 PermissionState.Unrestricted : PermissionState.None);
156
157                         allowBlankPassword = false;
158                         string blank = securityElement.Attribute ("AllowBlankPassword");
159                         if (blank != null) {
160 #if NET_2_0
161                                 // avoid possible exceptions with Fx 2.0
162                                 if (!Boolean.TryParse (blank, out allowBlankPassword))
163                                         allowBlankPassword = false;
164 #else
165                                 try {
166                                         allowBlankPassword = Boolean.Parse (blank);
167                                 }
168                                 catch {
169                                         allowBlankPassword = false;
170                                 }
171 #endif
172                         }
173
174                         if (securityElement.Children != null) {
175                                 foreach (SecurityElement child in securityElement.Children) {
176                                         string connect = child.Attribute ("ConnectionString");
177                                         string restricts = child.Attribute ("KeyRestrictions");
178                                         KeyRestrictionBehavior behavior = (KeyRestrictionBehavior) Enum.Parse (
179                                                 typeof (KeyRestrictionBehavior), child.Attribute ("KeyRestrictionBehavior"));
180
181                                         if ((connect != null) && (connect.Length > 0))
182                                                 Add (connect, restricts, behavior);
183                                 }
184                         }
185                 }
186
187                 [MonoTODO ("restrictions not completely implemented - nor documented")]
188                 public override IPermission Intersect (IPermission target) 
189                 {
190                         DBDataPermission dbdp = Cast (target);
191                         if (dbdp == null)
192                                 return null;
193                         if (IsUnrestricted ()) {
194                                 if (dbdp.IsUnrestricted ()) {
195                                         DBDataPermission u = CreateInstance ();
196                                         u.state = PermissionState.Unrestricted;
197                                         return u;
198                                 }
199                                 return dbdp.Copy ();
200                         }
201                         if (dbdp.IsUnrestricted ())
202                                 return Copy ();
203                         if (IsEmpty () || dbdp.IsEmpty ())
204                                 return null;
205
206                         DBDataPermission p = CreateInstance ();
207                         p.allowBlankPassword = (allowBlankPassword && dbdp.allowBlankPassword);
208                         foreach (DictionaryEntry de in _connections) {
209                                 object o = dbdp._connections [de.Key];
210                                 if (o != null)
211                                         p._connections.Add (de.Key, de.Value);
212                         }
213                         return (p._connections.Count > 0) ? p : null;
214                 }
215
216                 [MonoTODO ("restrictions not completely implemented - nor documented")]
217                 public override bool IsSubsetOf (IPermission target) 
218                 {
219                         DBDataPermission dbdp = Cast (target);
220                         if (dbdp == null)
221                                 return IsEmpty ();
222                         if (dbdp.IsUnrestricted ())
223                                 return true;
224                         if (IsUnrestricted ())
225                                 return dbdp.IsUnrestricted ();
226
227                         if (allowBlankPassword && !dbdp.allowBlankPassword)
228                                 return false;
229                         if (_connections.Count > dbdp._connections.Count)
230                                 return false;
231
232                         foreach (DictionaryEntry de in _connections) {
233                                 object o = dbdp._connections [de.Key];
234                                 if (o == null)
235                                         return false;
236                                 // FIXME: this is a subset of what is required
237                                 // it seems that we must process both the connect string
238                                 // and the restrictions - but this has other effects :-/
239                         }
240                         return true;
241                 }
242
243                 public bool IsUnrestricted () 
244                 {
245                         return (state == PermissionState.Unrestricted);
246                 }
247
248                 public override SecurityElement ToXml ()
249                 {
250                         SecurityElement se = PermissionHelper.Element (this.GetType (), version);
251                         if (IsUnrestricted ()) {
252                                 se.AddAttribute ("Unrestricted", "true");
253                         }
254                         else {
255                                 // attribute is present for both True and False
256                                 se.AddAttribute ("AllowBlankPassword", allowBlankPassword.ToString ());
257                                 foreach (DictionaryEntry de in _connections) {
258                                         SecurityElement child = new SecurityElement ("add");
259                                         child.AddAttribute ("ConnectionString", (string) de.Key);
260                                         object[] restrictionsInfo = (object[]) de.Value;
261                                         child.AddAttribute ("KeyRestrictions", (string) restrictionsInfo [0]);
262                                         KeyRestrictionBehavior krb = (KeyRestrictionBehavior) restrictionsInfo [1];
263                                         child.AddAttribute ("KeyRestrictionBehavior", krb.ToString ());
264                                         se.AddChild (child);
265                                 }
266                         }
267                         return se;
268                 }
269
270                 [MonoTODO ("restrictions not completely implemented - nor documented")]
271                 public override IPermission Union (IPermission target) 
272                 {
273                         DBDataPermission dbdp = Cast (target);
274                         if (dbdp == null)
275                                 return Copy ();
276                         if (IsEmpty () && dbdp.IsEmpty ())
277                                 return Copy ();
278
279                         DBDataPermission p = CreateInstance ();
280                         if (IsUnrestricted () || dbdp.IsUnrestricted ()) {
281                                 p.state = PermissionState.Unrestricted;
282                         }
283                         else {
284                                 p.allowBlankPassword = (allowBlankPassword || dbdp.allowBlankPassword);
285                                 p._connections = new Hashtable (_connections.Count + dbdp._connections.Count);
286                                 foreach (DictionaryEntry de in _connections)
287                                         p._connections.Add (de.Key, de.Value);
288                                 // don't duplicate
289                                 foreach (DictionaryEntry de in dbdp._connections)
290                                         p._connections [de.Key] = de.Value;
291                         }
292                         return p;
293                 }
294
295                 // helpers
296
297                 private bool IsEmpty ()
298                 {
299                         return ((state != PermissionState.Unrestricted) && (_connections.Count == 0));
300                 }
301
302                 private DBDataPermission Cast (IPermission target)
303                 {
304                         if (target == null)
305                                 return null;
306
307                         DBDataPermission dbdp = (target as DBDataPermission);
308                         if (dbdp == null) {
309                                 PermissionHelper.ThrowInvalidPermission (target, this.GetType ());
310                         }
311
312                         return dbdp;
313                 }
314
315                 #endregion // Methods
316         }
317 }