Merge pull request #5198 from BrzVlad/fix-binprot-stats
[mono.git] / mcs / class / corlib / System.Security.Permissions / PrincipalPermission.cs
index aa146abaa38bdbbf7cbc70acf8e5285148bb5519..5052eef0b07e37cbdbfb7a7131c5931c07377970 100644 (file)
@@ -5,7 +5,7 @@
 //     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // Copyright (C) 2003 Motus Technologies. http://www.motus.com
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2005 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
 //
 
 using System.Collections;
+using System.Runtime.InteropServices;
 using System.Security.Principal;
 using System.Threading;
 
 namespace System.Security.Permissions {
 
+       [ComVisible (true)]
        [Serializable]
        public sealed class PrincipalPermission : IPermission, IUnrestrictedPermission, IBuiltInPermission {
 
@@ -90,7 +92,7 @@ namespace System.Security.Permissions {
 
                internal PrincipalPermission (ArrayList principals) 
                {
-                       this.principals = principals;
+                       this.principals = (ArrayList) principals.Clone ();
                }
 
                // Properties
@@ -124,25 +126,33 @@ namespace System.Security.Permissions {
                                }
 
                                if (!demand)
-                                       throw new SecurityException ("invalid Principal");
+                                       throw new SecurityException ("Demand for principal refused.");
                        }
                }
 
-               public void FromXml (SecurityElement esd
+               public void FromXml (SecurityElement elem
                {
                        // General validation in CodeAccessPermission
-                       CodeAccessPermission.CheckSecurityElement (esd, "esd", version, version);
+                       CheckSecurityElement (elem, "elem", version, version);
                        // Note: we do not (yet) care about the return value 
                        // as we only accept version 1 (min/max values)
 
+                       principals.Clear ();
                        // Children is null, not empty, when no child is present
-                       if (esd.Children != null) {
-                               foreach (SecurityElement se in esd.Children) {
+                       if (elem.Children != null) {
+                               foreach (SecurityElement se in elem.Children) {
                                        if (se.Tag != "Identity")
                                                throw new ArgumentException ("not IPermission/Identity");
-                                       string name = (se.Attributes ["Name"] as string);
-                                       string role = (se.Attributes ["Role"] as string);
-                                       bool isAuthenticated = ((se.Attributes ["Authenticated"] as string) == "true");
+                                       string name = se.Attribute ("ID");
+                                       string role = se.Attribute ("Role");
+                                       string auth = se.Attribute ("Authenticated");
+                                       bool isAuthenticated = false;
+                                       if (auth != null) {
+                                               try {
+                                                       isAuthenticated = Boolean.Parse (auth);
+                                               }
+                                               catch {}
+                                       }
                                        PrincipalInfo pi = new PrincipalInfo (name, role, isAuthenticated);
                                        principals.Add (pi);
                                }
@@ -167,9 +177,13 @@ namespace System.Security.Permissions {
                                                string name = null;
                                                if ((pi.Name == opi.Name) || (opi.Name == null))
                                                        name = pi.Name;
+                                               else if (pi.Name == null)
+                                                       name = opi.Name;
                                                string role = null;
                                                if ((pi.Role == opi.Role) || (opi.Role == null))
                                                        role = pi.Role;
+                                               else if (pi.Role == null)
+                                                       role = opi.Role;
                                                if ((name != null) || (role != null)) {
                                                        PrincipalInfo ipi = new PrincipalInfo (name, role, pi.IsAuthenticated);
                                                        intersect.principals.Add (ipi);
@@ -185,7 +199,7 @@ namespace System.Security.Permissions {
                {
                        PrincipalPermission pp = Cast (target);
                        if (pp == null)
-                               return false;
+                               return IsEmpty ();
 
                        if (IsUnrestricted ())
                                return pp.IsUnrestricted ();
@@ -224,7 +238,7 @@ namespace System.Security.Permissions {
 
                public SecurityElement ToXml () 
                {
-                       SecurityElement se = new SecurityElement ("IPermission");
+                       SecurityElement se = new SecurityElement ("Permission");
                        Type type = this.GetType ();
                        se.AddAttribute ("class", type.FullName + ", " + type.Assembly.ToString ().Replace ('\"', '\''));
                        se.AddAttribute ("version", version.ToString ());
@@ -232,7 +246,7 @@ namespace System.Security.Permissions {
                        foreach (PrincipalInfo pi in principals) {
                                SecurityElement sec = new SecurityElement ("Identity");
                                if (pi.Name != null)
-                                       sec.AddAttribute ("Name", pi.Name);
+                                       sec.AddAttribute ("ID", pi.Name);
                                if (pi.Role != null)
                                        sec.AddAttribute ("Role", pi.Role);
                                if (pi.IsAuthenticated)
@@ -242,9 +256,9 @@ namespace System.Security.Permissions {
                        return se;
                }
 
-               public IPermission Union (IPermission target)
+               public IPermission Union (IPermission other)
                {
-                       PrincipalPermission pp = Cast (target);
+                       PrincipalPermission pp = Cast (other);
                        if (pp == null)
                                return Copy ();
 
@@ -253,12 +267,12 @@ namespace System.Security.Permissions {
 
                        PrincipalPermission union = new PrincipalPermission (principals);
                        foreach (PrincipalInfo pi in pp.principals)
-                               principals.Add (pi);
+                               union.principals.Add (pi);
 
                        return union;
                }
 
-#if NET_2_0
+               [ComVisible (false)]
                public override bool Equals (object obj)
                {
                        if (obj == null)
@@ -291,11 +305,11 @@ namespace System.Security.Permissions {
 
                // according to documentation (fx 2.0 beta 1) we can have 
                // different hash code even if both a Equals
+               [ComVisible (false)]
                public override int GetHashCode ()
                {
                        return base.GetHashCode ();
                }
-#endif
 
                // IBuiltInPermission
                int IBuiltInPermission.GetTokenIndex ()
@@ -317,5 +331,49 @@ namespace System.Security.Permissions {
 
                        return pp;
                }
+
+               private bool IsEmpty ()
+               {
+                       return (principals.Count == 0);
+               }
+
+               // Normally permissions tags are "IPermission" but this (non-CAS) permission use "Permission"
+               internal int CheckSecurityElement (SecurityElement se, string parameterName, int minimumVersion, int maximumVersion) 
+               {
+                       if (se == null)
+                               throw new ArgumentNullException (parameterName);
+
+                       // Tag is case-sensitive
+                       if (se.Tag != "Permission") {
+                               string msg = String.Format (Locale.GetText ("Invalid tag {0}"), se.Tag);
+                               throw new ArgumentException (msg, parameterName);
+                       }
+
+                       // Note: we do not care about the class attribute at 
+                       // this stage (in fact we don't even if the class 
+                       // attribute is present or not). Anyway the object has
+                       // already be created, with success, if we're loading it
+
+                       // we assume minimum version if no version number is supplied
+                       int version = minimumVersion;
+                       string v = se.Attribute ("version");
+                       if (v != null) {
+                               try {
+                                       version = Int32.Parse (v);
+                               }
+                               catch (Exception e) {
+                                       string msg = Locale.GetText ("Couldn't parse version from '{0}'.");
+                                       msg = String.Format (msg, v);
+                                       throw new ArgumentException (msg, parameterName, e);
+                               }
+                       }
+
+                       if ((version < minimumVersion) || (version > maximumVersion)) {
+                               string msg = Locale.GetText ("Unknown version '{0}', expected versions between ['{1}','{2}'].");
+                               msg = String.Format (msg, version, minimumVersion, maximumVersion);
+                               throw new ArgumentException (msg, parameterName);
+                       }
+                       return version;
+               }
        }
 }