start populating the new System.Web.Configuration_2.0 dir
[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 #if NET_2_0
94                 [MonoTODO]
95                 protected DBDataPermission (DbConnectionOptions connectionOptions)
96                         : this (PermissionState.None)
97                 {
98                         // ignore null (i.e. no ArgumentNullException)
99                         if (connectionOptions != null) {
100                                 throw new NotImplementedException ();
101                         }
102                 }
103 #endif
104
105                 protected DBDataPermission (PermissionState state) 
106                 {
107                         this.state = PermissionHelper.CheckPermissionState (state, true);
108                         _connections = new Hashtable ();
109                 }
110
111 #if NET_2_0
112                 [Obsolete ("use DBDataPermission (PermissionState.None)", true)]
113 #endif
114                 public DBDataPermission (PermissionState state, bool allowBlankPassword)
115                         : this (state)
116                 {
117                         this.allowBlankPassword = allowBlankPassword;
118                 }
119
120                 #endregion // Constructors
121
122                 #region Properties
123
124                 public bool AllowBlankPassword {
125                         get { return allowBlankPassword; }
126                         set { allowBlankPassword = value; }
127                 }
128                 
129                 #endregion // Properties
130
131                 #region Methods
132
133 #if NET_2_0
134                 public virtual void Add (string connectionString, string restrictions, KeyRestrictionBehavior behavior)
135                 {
136                         state = PermissionState.None;
137                         AddConnectionString (connectionString, restrictions, behavior, null, false);
138                 }
139
140                 [MonoTODO ("synonyms and useFirstKeyValue aren't supported")]
141                 protected virtual void AddConnectionString (string connectionString, string restrictions, 
142                         KeyRestrictionBehavior behavior, Hashtable synonyms, bool useFirstKeyValue)
143                 {
144                         _connections [connectionString] = new object [2] { restrictions, behavior };
145                 }
146 #elif NET_1_1
147                 public virtual void Add (string connectionString, string restrictions, KeyRestrictionBehavior behavior)
148                 {
149                         state = PermissionState.None;
150                         _connections [connectionString] = new object [2] { restrictions, behavior };
151                 }
152 #endif
153
154                 protected void Clear ()
155                 {
156                         _connections.Clear ();
157                 }
158
159                 public override IPermission Copy () 
160                 {
161                         DBDataPermission dbdp = CreateInstance ();
162                         dbdp.allowBlankPassword = this.allowBlankPassword;
163                         dbdp._connections = (Hashtable) this._connections.Clone ();
164                         return dbdp;
165                 }
166
167                 protected virtual DBDataPermission CreateInstance ()
168                 {
169                         return (DBDataPermission) Activator.CreateInstance (this.GetType (), new object [1] { PermissionState.None });
170                 }
171
172                 public override void FromXml (SecurityElement securityElement) 
173                 {
174                         PermissionHelper.CheckSecurityElement (securityElement, "securityElement", version, version);
175                         // Note: we do not (yet) care about the return value 
176                         // as we only accept version 1 (min/max values)
177
178                         state = (PermissionHelper.IsUnrestricted (securityElement) ? 
179                                 PermissionState.Unrestricted : PermissionState.None);
180
181                         allowBlankPassword = false;
182                         string blank = securityElement.Attribute ("AllowBlankPassword");
183                         if (blank != null) {
184 #if NET_2_0
185                                 // avoid possible exceptions with Fx 2.0
186                                 if (!Boolean.TryParse (blank, out allowBlankPassword))
187                                         allowBlankPassword = false;
188 #else
189                                 try {
190                                         allowBlankPassword = Boolean.Parse (blank);
191                                 }
192                                 catch {
193                                         allowBlankPassword = false;
194                                 }
195 #endif
196                         }
197
198                         if (securityElement.Children != null) {
199                                 foreach (SecurityElement child in securityElement.Children) {
200                                         string connect = child.Attribute ("ConnectionString");
201                                         string restricts = child.Attribute ("KeyRestrictions");
202                                         KeyRestrictionBehavior behavior = (KeyRestrictionBehavior) Enum.Parse (
203                                                 typeof (KeyRestrictionBehavior), child.Attribute ("KeyRestrictionBehavior"));
204
205                                         if ((connect != null) && (connect.Length > 0))
206                                                 Add (connect, restricts, behavior);
207                                 }
208                         }
209                 }
210
211                 [MonoTODO ("restrictions not completely implemented - nor documented")]
212                 public override IPermission Intersect (IPermission target) 
213                 {
214                         DBDataPermission dbdp = Cast (target);
215                         if (dbdp == null)
216                                 return null;
217                         if (IsUnrestricted ()) {
218                                 if (dbdp.IsUnrestricted ()) {
219                                         DBDataPermission u = CreateInstance ();
220                                         u.state = PermissionState.Unrestricted;
221                                         return u;
222                                 }
223                                 return dbdp.Copy ();
224                         }
225                         if (dbdp.IsUnrestricted ())
226                                 return Copy ();
227                         if (IsEmpty () || dbdp.IsEmpty ())
228                                 return null;
229
230                         DBDataPermission p = CreateInstance ();
231                         p.allowBlankPassword = (allowBlankPassword && dbdp.allowBlankPassword);
232                         foreach (DictionaryEntry de in _connections) {
233                                 object o = dbdp._connections [de.Key];
234                                 if (o != null)
235                                         p._connections.Add (de.Key, de.Value);
236                         }
237                         return (p._connections.Count > 0) ? p : null;
238                 }
239
240                 [MonoTODO ("restrictions not completely implemented - nor documented")]
241                 public override bool IsSubsetOf (IPermission target) 
242                 {
243                         DBDataPermission dbdp = Cast (target);
244                         if (dbdp == null)
245                                 return IsEmpty ();
246                         if (dbdp.IsUnrestricted ())
247                                 return true;
248                         if (IsUnrestricted ())
249                                 return dbdp.IsUnrestricted ();
250
251                         if (allowBlankPassword && !dbdp.allowBlankPassword)
252                                 return false;
253                         if (_connections.Count > dbdp._connections.Count)
254                                 return false;
255
256                         foreach (DictionaryEntry de in _connections) {
257                                 object o = dbdp._connections [de.Key];
258                                 if (o == null)
259                                         return false;
260                                 // FIXME: this is a subset of what is required
261                                 // it seems that we must process both the connect string
262                                 // and the restrictions - but this has other effects :-/
263                         }
264                         return true;
265                 }
266
267                 public bool IsUnrestricted () 
268                 {
269                         return (state == PermissionState.Unrestricted);
270                 }
271
272 #if NET_2_0
273                 [MonoTODO ("DO NOT IMPLEMENT - will be removed")]
274                 [Obsolete ("DO NOT IMPLEMENT - will be removed")]
275                 protected void SetConnectionString (DbConnectionOptions constr)
276                 {
277                         throw new NotImplementedException ();
278                 }
279
280                 [MonoTODO ("DO NOT IMPLEMENT - will be removed")]
281                 [Obsolete ("DO NOT IMPLEMENT - will be removed")]
282                 public virtual void SetRestriction (string connectionString, string restrictions, KeyRestrictionBehavior behavior)
283                 {
284                         throw new NotImplementedException ();
285                 }
286 #endif
287
288                 public override SecurityElement ToXml ()
289                 {
290                         SecurityElement se = PermissionHelper.Element (this.GetType (), version);
291                         if (IsUnrestricted ()) {
292                                 se.AddAttribute ("Unrestricted", "true");
293                         }
294                         else {
295                                 // attribute is present for both True and False
296                                 se.AddAttribute ("AllowBlankPassword", allowBlankPassword.ToString ());
297                                 foreach (DictionaryEntry de in _connections) {
298                                         SecurityElement child = new SecurityElement ("add");
299                                         child.AddAttribute ("ConnectionString", (string) de.Key);
300                                         object[] restrictionsInfo = (object[]) de.Value;
301                                         child.AddAttribute ("KeyRestrictions", (string) restrictionsInfo [0]);
302                                         KeyRestrictionBehavior krb = (KeyRestrictionBehavior) restrictionsInfo [1];
303                                         child.AddAttribute ("KeyRestrictionBehavior", krb.ToString ());
304                                         se.AddChild (child);
305                                 }
306                         }
307                         return se;
308                 }
309
310                 [MonoTODO ("restrictions not completely implemented - nor documented")]
311                 public override IPermission Union (IPermission target) 
312                 {
313                         DBDataPermission dbdp = Cast (target);
314                         if (dbdp == null)
315                                 return Copy ();
316                         if (IsEmpty () && dbdp.IsEmpty ())
317                                 return Copy ();
318
319                         DBDataPermission p = CreateInstance ();
320                         if (IsUnrestricted () || dbdp.IsUnrestricted ()) {
321                                 p.state = PermissionState.Unrestricted;
322                         }
323                         else {
324                                 p.allowBlankPassword = (allowBlankPassword || dbdp.allowBlankPassword);
325                                 p._connections = new Hashtable (_connections.Count + dbdp._connections.Count);
326                                 foreach (DictionaryEntry de in _connections)
327                                         p._connections.Add (de.Key, de.Value);
328                                 // don't duplicate
329                                 foreach (DictionaryEntry de in dbdp._connections)
330                                         p._connections [de.Key] = de.Value;
331                         }
332                         return p;
333                 }
334
335                 // helpers
336
337                 private bool IsEmpty ()
338                 {
339                         return ((state != PermissionState.Unrestricted) && (_connections.Count == 0));
340                 }
341
342                 private DBDataPermission Cast (IPermission target)
343                 {
344                         if (target == null)
345                                 return null;
346
347                         DBDataPermission dbdp = (target as DBDataPermission);
348                         if (dbdp == null) {
349                                 PermissionHelper.ThrowInvalidPermission (target, this.GetType ());
350                         }
351
352                         return dbdp;
353                 }
354
355                 #endregion // Methods
356         }
357 }