Mark tests as not working under TARGET_JVM
[mono.git] / mcs / class / System.Data / System.Data.Common / DbDataPermission.cs
index f14770453d7198335732580347a9b2dd43568a18..9d2139c982b98c59e140ec2977071112b3bf79eb 100644 (file)
 //
-// System.Data.Common.DbDataAdapter.cs
+// System.Data.Common.DbDataPermission.cs
 //
-// Author:
-//   Rodrigo Moya (rodrigo@ximian.com)
+// Authors:
+//     Rodrigo Moya (rodrigo@ximian.com)
+//     Tim Coleman (tim@timcoleman.com)
+//     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // (C) Ximian, Inc
+// Copyright (C) Tim Coleman, 2002-2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
+using System.Collections;
+using System.Security;
 using System.Security.Permissions;
 
-namespace System.Data.Common
-{
-       /// <summary>
-       /// Provides the capability for a .NET data provider to ensure that a user has a security level adequate for accessing data.
-       /// </summary>
-       public abstract class DBDataPermission : CodeAccessPermission,
-               IUnrestrictedPermission
-       {
+namespace System.Data.Common {
+
+       [Serializable]
+       public abstract class DBDataPermission : CodeAccessPermission, IUnrestrictedPermission {
+
+               #region Fields
+
+               private const int version = 1;
+
                private bool allowBlankPassword;
-               private PermissionState permissionState;
+               private PermissionState state;
+               private Hashtable _connections;
 
-               protected DBDataPermission () {
-                       allowBlankPassword = false;
-                       permissionState = PermissionState.None;
+               #endregion // Fields
+
+               #region Constructors
+
+#if NET_2_0
+               [Obsolete ("use DBDataPermission (PermissionState.None)", true)]
+#endif
+               protected DBDataPermission () 
+                       : this (PermissionState.None)
+               {
                }
 
-               protected DBDataPermission (PermissionState state) {
-                       allowBlankPassword = false;
-                       permissionState = state;
+               protected DBDataPermission (DBDataPermission permission)
+               {
+                       if (permission == null)
+                               throw new ArgumentNullException ("permission");
+
+                       state = permission.state;
+                       if (state != PermissionState.Unrestricted) {
+                               allowBlankPassword = permission.allowBlankPassword;
+                               _connections = (Hashtable) permission._connections.Clone ();
+                       }
+               }
+
+               protected DBDataPermission (DBDataPermissionAttribute permissionAttribute)
+               {
+                       if (permissionAttribute == null)
+                               throw new ArgumentNullException ("permissionAttribute");
+
+                       _connections = new Hashtable ();
+                       if (permissionAttribute.Unrestricted) {
+                               state = PermissionState.Unrestricted;
+                       }
+                       else {
+                               state = PermissionState.None;
+                               allowBlankPassword = permissionAttribute.AllowBlankPassword;
+                               if (permissionAttribute.ConnectionString.Length > 0) {
+                                       Add (permissionAttribute.ConnectionString, permissionAttribute.KeyRestrictions, 
+                                               permissionAttribute.KeyRestrictionBehavior);
+                               }
+                       }
+               }
+
+               protected DBDataPermission (PermissionState state) 
+               {
+                       this.state = PermissionHelper.CheckPermissionState (state, true);
+                       _connections = new Hashtable ();
+               }
+
+#if NET_2_0
+               [Obsolete ("use DBDataPermission (PermissionState.None)", true)]
+               protected 
+#else
+               public
+#endif
+               DBDataPermission (PermissionState state, bool allowBlankPassword)
+                       : this (state)
+               {
+                       this.allowBlankPassword = allowBlankPassword;
+               }
+
+               #endregion // Constructors
+
+               #region Properties
+
+               public bool AllowBlankPassword {
+                       get { return allowBlankPassword; }
+                       set { allowBlankPassword = value; }
                }
+               
+               #endregion // Properties
+
+               #region Methods
 
-               public DBDataPermission (PermissionState state, bool abp) {
-                       allowBlankPassword = abp;
-                       permissionState = state;
+               public virtual void Add (string connectionString, string restrictions, KeyRestrictionBehavior behavior)
+               {
+                       state = PermissionState.None;
+                       _connections [connectionString] = new object [2] { restrictions, behavior };
                }
 
-               public override IPermission Copy () {
-                       DbDataPermission copy = new DbDataPermission (
-                               permissionState, allowBlankPassword);
+               protected void Clear ()
+               {
+                       _connections.Clear ();
+               }
 
-                       return copy;
+               public override IPermission Copy () 
+               {
+                       DBDataPermission dbdp = CreateInstance ();
+                       dbdp.allowBlankPassword = this.allowBlankPassword;
+                       dbdp._connections = (Hashtable) this._connections.Clone ();
+                       return dbdp;
                }
 
-               [MonoTODO]
-               public override void FromXml (SecurityElement securityElement) {
-                       throw new NotImplementedException ();
+               protected virtual DBDataPermission CreateInstance ()
+               {
+                       return (DBDataPermission) Activator.CreateInstance (this.GetType (), new object [1] { PermissionState.None });
                }
 
-               [MonoTODO]
-               public override IPermission Intersect (IPermission target) {
-                       throw new NotImplementedException ();
+               public override void FromXml (SecurityElement securityElement) 
+               {
+                       PermissionHelper.CheckSecurityElement (securityElement, "securityElement", version, version);
+                       // Note: we do not (yet) care about the return value 
+                       // as we only accept version 1 (min/max values)
+
+                       state = (PermissionHelper.IsUnrestricted (securityElement) ? 
+                               PermissionState.Unrestricted : PermissionState.None);
+
+                       allowBlankPassword = false;
+                       string blank = securityElement.Attribute ("AllowBlankPassword");
+                       if (blank != null) {
+#if NET_2_0
+                               // avoid possible exceptions with Fx 2.0
+                               if (!Boolean.TryParse (blank, out allowBlankPassword))
+                                       allowBlankPassword = false;
+#else
+                               try {
+                                       allowBlankPassword = Boolean.Parse (blank);
+                               }
+                               catch {
+                                       allowBlankPassword = false;
+                               }
+#endif
+                       }
+
+                       if (securityElement.Children != null) {
+                               foreach (SecurityElement child in securityElement.Children) {
+                                       string connect = child.Attribute ("ConnectionString");
+                                       string restricts = child.Attribute ("KeyRestrictions");
+                                       KeyRestrictionBehavior behavior = (KeyRestrictionBehavior) Enum.Parse (
+                                               typeof (KeyRestrictionBehavior), child.Attribute ("KeyRestrictionBehavior"));
+
+                                       if ((connect != null) && (connect.Length > 0))
+                                               Add (connect, restricts, behavior);
+                               }
+                       }
                }
 
-               [MonoTODO]
-               public override bool IsSubsetOf (IPermission target) {
-                       throw new NotImplementedException ();
+               public override IPermission Intersect (IPermission target) 
+               {
+                       // FIXME: restrictions not completely implemented - nor documented
+                       DBDataPermission dbdp = Cast (target);
+                       if (dbdp == null)
+                               return null;
+                       if (IsUnrestricted ()) {
+                               if (dbdp.IsUnrestricted ()) {
+                                       DBDataPermission u = CreateInstance ();
+                                       u.state = PermissionState.Unrestricted;
+                                       return u;
+                               }
+                               return dbdp.Copy ();
+                       }
+                       if (dbdp.IsUnrestricted ())
+                               return Copy ();
+                       if (IsEmpty () || dbdp.IsEmpty ())
+                               return null;
+
+                       DBDataPermission p = CreateInstance ();
+                       p.allowBlankPassword = (allowBlankPassword && dbdp.allowBlankPassword);
+                       foreach (DictionaryEntry de in _connections) {
+                               object o = dbdp._connections [de.Key];
+                               if (o != null)
+                                       p._connections.Add (de.Key, de.Value);
+                       }
+                       return (p._connections.Count > 0) ? p : null;
                }
 
-               public bool IsUnrestricted () {
-                       if (permissionState == PermissionState.Unrestricted)
+               public override bool IsSubsetOf (IPermission target) 
+               {
+                       // FIXME: restrictions not completely implemented - nor documented
+                       DBDataPermission dbdp = Cast (target);
+                       if (dbdp == null)
+                               return IsEmpty ();
+                       if (dbdp.IsUnrestricted ())
                                return true;
-                       return false;
+                       if (IsUnrestricted ())
+                               return dbdp.IsUnrestricted ();
+
+                       if (allowBlankPassword && !dbdp.allowBlankPassword)
+                               return false;
+                       if (_connections.Count > dbdp._connections.Count)
+                               return false;
+
+                       foreach (DictionaryEntry de in _connections) {
+                               object o = dbdp._connections [de.Key];
+                               if (o == null)
+                                       return false;
+                               // FIXME: this is a subset of what is required
+                               // it seems that we must process both the connect string
+                               // and the restrictions - but this has other effects :-/
+                       }
+                       return true;
                }
 
-               [MonoTODO]
-               public override SecurityElement ToXml () {
-                       throw new NotImplementedException ();
+               public bool IsUnrestricted () 
+               {
+                       return (state == PermissionState.Unrestricted);
                }
 
-               [MonoTODO]
-               public override IPermission Union (IPermission target) {
-                       throw new NotImplementedException ();
+               public override SecurityElement ToXml ()
+               {
+                       SecurityElement se = PermissionHelper.Element (this.GetType (), version);
+                       if (IsUnrestricted ()) {
+                               se.AddAttribute ("Unrestricted", "true");
+                       }
+                       else {
+                               // attribute is present for both True and False
+                               se.AddAttribute ("AllowBlankPassword", allowBlankPassword.ToString ());
+                               foreach (DictionaryEntry de in _connections) {
+                                       SecurityElement child = new SecurityElement ("add");
+                                       child.AddAttribute ("ConnectionString", (string) de.Key);
+                                       object[] restrictionsInfo = (object[]) de.Value;
+                                       child.AddAttribute ("KeyRestrictions", (string) restrictionsInfo [0]);
+                                       KeyRestrictionBehavior krb = (KeyRestrictionBehavior) restrictionsInfo [1];
+                                       child.AddAttribute ("KeyRestrictionBehavior", krb.ToString ());
+                                       se.AddChild (child);
+                               }
+                       }
+                       return se;
                }
-               
-               public bool AllowBlankPassword {
-                       get {
-                               return allowBlankPassword;
+
+               public override IPermission Union (IPermission target) 
+               {
+                       // FIXME: restrictions not completely implemented - nor documented
+                       DBDataPermission dbdp = Cast (target);
+                       if (dbdp == null)
+                               return Copy ();
+                       if (IsEmpty () && dbdp.IsEmpty ())
+                               return Copy ();
+
+                       DBDataPermission p = CreateInstance ();
+                       if (IsUnrestricted () || dbdp.IsUnrestricted ()) {
+                               p.state = PermissionState.Unrestricted;
+                       }
+                       else {
+                               p.allowBlankPassword = (allowBlankPassword || dbdp.allowBlankPassword);
+                               p._connections = new Hashtable (_connections.Count + dbdp._connections.Count);
+                               foreach (DictionaryEntry de in _connections)
+                                       p._connections.Add (de.Key, de.Value);
+                               // don't duplicate
+                               foreach (DictionaryEntry de in dbdp._connections)
+                                       p._connections [de.Key] = de.Value;
                        }
-                       set {
-                               allowBlankPassword = value;
+                       return p;
+               }
+
+               // helpers
+
+               private bool IsEmpty ()
+               {
+                       return ((state != PermissionState.Unrestricted) && (_connections.Count == 0));
+               }
+
+               private DBDataPermission Cast (IPermission target)
+               {
+                       if (target == null)
+                               return null;
+
+                       DBDataPermission dbdp = (target as DBDataPermission);
+                       if (dbdp == null) {
+                               PermissionHelper.ThrowInvalidPermission (target, this.GetType ());
                        }
+
+                       return dbdp;
                }
+
+               #endregion // Methods
        }
 }