File: system\security\permissions\strongnameidentitypermission.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
// ==++==
 
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
// StrongNameIdentityPermission.cs
// 
// <OWNER>Microsoft</OWNER>
// 
 
namespace System.Security.Permissions
{
    using System;
#if FEATURE_CAS_POLICY
    using SecurityElement = System.Security.SecurityElement;
#endif // FEATURE_CAS_POLICY
    using System.Security.Util;
    using System.IO;
    using String = System.String;
    using Version = System.Version;
    using System.Security.Policy;
    using System.Collections;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Diagnostics.Contracts;
 
    // The only difference between this class and System.Security.Policy.StrongName is that this one
    // allows m_name to be null.  We should merge this class with System.Security.Policy.StrongName
    [Serializable]
    sealed internal class StrongName2
    {
        public StrongNamePublicKeyBlob m_publicKeyBlob;
        public String m_name;
        public Version m_version;
 
        public StrongName2(StrongNamePublicKeyBlob publicKeyBlob, String name, Version version)
        {
            m_publicKeyBlob = publicKeyBlob;
            m_name = name;
            m_version = version;
        }
 
        public StrongName2 Copy()
        {
            return new StrongName2(m_publicKeyBlob, m_name, m_version);
        }
 
        public bool IsSubsetOf(StrongName2 target)
        {
            // This StrongName2 is a subset of the target if it's public key blob is null no matter what
            if (this.m_publicKeyBlob == null)
                return true;
 
            // Subsets are always false if the public key blobs do not match
            if (!this.m_publicKeyBlob.Equals( target.m_publicKeyBlob ))
                return false;
 
            // We use null in strings to represent the "Anything" state.
            // Therefore, the logic to detect an individual subset is:
            //
            // 1. If the this string is null ("Anything" is a subset of any other).
            // 2. If the this string and target string are the same (equality is sufficient for a subset).
            //
            // The logic is reversed here to discover things that are not subsets.
            if (this.m_name != null)
            {
                if (target.m_name == null || !System.Security.Policy.StrongName.CompareNames( target.m_name, this.m_name ))
                    return false;
            }
 
            if ((Object) this.m_version != null)
            {
                if ((Object) target.m_version == null ||
                    target.m_version.CompareTo( this.m_version ) != 0)
                {
                    return false;
                }
            }
 
            return true;
        }
        
        public StrongName2 Intersect(StrongName2 target)
        {
            if (target.IsSubsetOf( this ))
                return target.Copy();
            else if (this.IsSubsetOf( target ))
                return this.Copy();
            else
                return null;
        }
 
        public bool Equals(StrongName2 target)
        {
            if (!target.IsSubsetOf(this))
                return false;
            if (!this.IsSubsetOf(target))
                return false;
            return true;
        }
    }
 
 
 
[System.Runtime.InteropServices.ComVisible(true)]
    [Serializable]
    sealed public class StrongNameIdentityPermission : CodeAccessPermission, IBuiltInPermission
    {
        //------------------------------------------------------
        //
        // PRIVATE STATE DATA
        //
        //------------------------------------------------------
 
        private bool m_unrestricted;
        private StrongName2[] m_strongNames;
 
        //------------------------------------------------------
        //
        // PUBLIC CONSTRUCTORS
        //
        //------------------------------------------------------
 
 
        public StrongNameIdentityPermission(PermissionState state)
        {
            if (state == PermissionState.Unrestricted)
            {
                m_unrestricted = true;
            }
            else if (state == PermissionState.None)
            {
                m_unrestricted = false;
            }
            else
            {
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
            }
        }
 
        public StrongNameIdentityPermission( StrongNamePublicKeyBlob blob, String name, Version version )
        {
            if (blob == null)
                throw new ArgumentNullException( "blob" );
            if (name != null && name.Equals( "" ))
                throw new ArgumentException( Environment.GetResourceString( "Argument_EmptyStrongName" ) );      
            Contract.EndContractBlock();
            m_unrestricted = false;
            m_strongNames = new StrongName2[1];
            m_strongNames[0] = new StrongName2(blob, name, version);
        }
 
 
        //------------------------------------------------------
        //
        // PUBLIC ACCESSOR METHODS
        //
        //------------------------------------------------------
 
        public StrongNamePublicKeyBlob PublicKey
        {
            set
            {
                if (value == null)
                    throw new ArgumentNullException( "PublicKey" );
                Contract.EndContractBlock();
                m_unrestricted = false;
                if(m_strongNames != null && m_strongNames.Length == 1)
                    m_strongNames[0].m_publicKeyBlob = value;
                else
                {
                    m_strongNames = new StrongName2[1];
                    m_strongNames[0] = new StrongName2(value, "", new Version());                   
                }
            }
 
            get
            {
                if(m_strongNames == null || m_strongNames.Length == 0)
                    return null;
                if(m_strongNames.Length > 1)
                    throw new NotSupportedException(Environment.GetResourceString("NotSupported_AmbiguousIdentity"));
                return m_strongNames[0].m_publicKeyBlob;
            }
        }
 
        public String Name
        {
            set
            {
                if (value != null && value.Length == 0)
                    throw new ArgumentException( Environment.GetResourceString("Argument_EmptyName" ));    
                Contract.EndContractBlock();
                m_unrestricted = false;
                if(m_strongNames != null && m_strongNames.Length == 1)
                    m_strongNames[0].m_name = value;
                else
                {
                    m_strongNames = new StrongName2[1];
                    m_strongNames[0] = new StrongName2(null, value, new Version());                 
                }
            }                    
 
            get
            {
                if(m_strongNames == null || m_strongNames.Length == 0)
                    return "";
                if(m_strongNames.Length > 1)
                    throw new NotSupportedException(Environment.GetResourceString("NotSupported_AmbiguousIdentity"));
                return m_strongNames[0].m_name;
            }
        }
 
        public Version Version
        {
            set
            {
                m_unrestricted = false;
                if(m_strongNames != null && m_strongNames.Length == 1)
                    m_strongNames[0].m_version = value;
                else
                {
                    m_strongNames = new StrongName2[1];
                    m_strongNames[0] = new StrongName2(null, "", value);
                }
            }
            
            get
            {
                if(m_strongNames == null || m_strongNames.Length == 0)
                    return new Version();
                if(m_strongNames.Length > 1)
                    throw new NotSupportedException(Environment.GetResourceString("NotSupported_AmbiguousIdentity"));
                return m_strongNames[0].m_version;
            }
        }
 
        //------------------------------------------------------
        //
        // PRIVATE AND PROTECTED HELPERS FOR ACCESSORS AND CONSTRUCTORS
        //
        //------------------------------------------------------
    
        //------------------------------------------------------
        //
        // CODEACCESSPERMISSION IMPLEMENTATION
        //
        //------------------------------------------------------
        
        //------------------------------------------------------
        //
        // IPERMISSION IMPLEMENTATION
        //
        //------------------------------------------------------
 
 
        public override IPermission Copy()
        {
            StrongNameIdentityPermission perm = new StrongNameIdentityPermission(PermissionState.None);
            perm.m_unrestricted = this.m_unrestricted;
            if(this.m_strongNames != null)
            {
                perm.m_strongNames = new StrongName2[this.m_strongNames.Length];
                int n;
                for(n = 0; n < this.m_strongNames.Length; n++)
                    perm.m_strongNames[n] = this.m_strongNames[n].Copy();
            }
            return perm;
        }
 
        public override bool IsSubsetOf(IPermission target)
        {
            if (target == null)
            {
                if(m_unrestricted)
                    return false;
                if(m_strongNames == null)
                    return true;
                if(m_strongNames.Length == 0)
                    return true;
                return false;
            }
            StrongNameIdentityPermission that = target as StrongNameIdentityPermission;
            if(that == null)
                throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
            if(that.m_unrestricted)
                return true;
            if(m_unrestricted)
                return false;
            if(this.m_strongNames != null)
            {
                foreach(StrongName2 snThis in m_strongNames)
                {
                    bool bOK = false;
                    if(that.m_strongNames != null)
                    {
                        foreach(StrongName2 snThat in that.m_strongNames)
                        {
                            if(snThis.IsSubsetOf(snThat))
                            {
                                bOK = true;
                                break;
                            }
                        }
                    }
                    if(!bOK)
                        return false;           
                }
            }
            return true;
        }
 
 
 
        public override IPermission Intersect(IPermission target)
        {
            if (target == null)
                return null;
            StrongNameIdentityPermission that = target as StrongNameIdentityPermission;
            if(that == null)
                throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
            if(this.m_unrestricted && that.m_unrestricted)
            {
                StrongNameIdentityPermission res = new StrongNameIdentityPermission(PermissionState.None);
                res.m_unrestricted = true;
                return res;
            }
            if(this.m_unrestricted)
                return that.Copy();
            if(that.m_unrestricted)
                return this.Copy();
            if(this.m_strongNames == null || that.m_strongNames == null || this.m_strongNames.Length == 0 || that.m_strongNames.Length == 0)
                return null;
            List<StrongName2> alStrongNames = new List<StrongName2>();
            foreach(StrongName2 snThis in this.m_strongNames)
            {
                foreach(StrongName2 snThat in that.m_strongNames)
                {
                    StrongName2 snInt = (StrongName2)snThis.Intersect(snThat);
                    if(snInt != null)
                        alStrongNames.Add(snInt);
                }
            }
            if(alStrongNames.Count == 0)
                return null;
            StrongNameIdentityPermission result = new StrongNameIdentityPermission(PermissionState.None);
            result.m_strongNames = alStrongNames.ToArray();
            return result;
        }
 
        public override IPermission Union(IPermission target)
        {
            if (target == null)
            {
                if((this.m_strongNames == null || this.m_strongNames.Length == 0) && !this.m_unrestricted)
                    return null;
                return this.Copy();
            }
            StrongNameIdentityPermission that = target as StrongNameIdentityPermission;
            if(that == null)
                throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
            if(this.m_unrestricted || that.m_unrestricted)
            {
                StrongNameIdentityPermission res = new StrongNameIdentityPermission(PermissionState.None);
                res.m_unrestricted = true;
                return res;
            }
            if (this.m_strongNames == null || this.m_strongNames.Length == 0)
            {
                if(that.m_strongNames == null || that.m_strongNames.Length == 0)
                    return null;
                return that.Copy();
            }
            if(that.m_strongNames == null || that.m_strongNames.Length == 0)
                return this.Copy();
            List<StrongName2> alStrongNames = new List<StrongName2>();
            foreach(StrongName2 snThis in this.m_strongNames)
                alStrongNames.Add(snThis);
            foreach(StrongName2 snThat in that.m_strongNames)
            {
                bool bDupe = false;
                foreach(StrongName2 sn in alStrongNames)
                {
                    if(snThat.Equals(sn))
                    {
                        bDupe = true;
                        break;
                    }
                }
                if(!bDupe)
                    alStrongNames.Add(snThat);
            }
            StrongNameIdentityPermission result = new StrongNameIdentityPermission(PermissionState.None);
            result.m_strongNames = alStrongNames.ToArray();
            return result;
        }
 
#if FEATURE_CAS_POLICY
        public override void FromXml(SecurityElement e)
        {
            m_unrestricted = false;
            m_strongNames = null;
            CodeAccessPermission.ValidateElement( e, this );
            String unr = e.Attribute( "Unrestricted" );
            if(unr != null && String.Compare(unr, "true", StringComparison.OrdinalIgnoreCase) == 0)
            {
                m_unrestricted = true;
                return;
            }
            String elBlob = e.Attribute("PublicKeyBlob");
            String elName = e.Attribute("Name");
            String elVersion = e.Attribute("AssemblyVersion");
            StrongName2 sn;
            List<StrongName2> al = new List<StrongName2>();
            if(elBlob != null || elName != null || elVersion != null)
            {
                sn = new StrongName2(
                                    (elBlob == null ? null : new StrongNamePublicKeyBlob(elBlob)), 
                                    elName, 
                                    (elVersion == null ? null : new Version(elVersion)));
                al.Add(sn);
            }
            ArrayList alChildren = e.Children;
            if(alChildren != null)
            {
                foreach(SecurityElement child in alChildren)
                {
                    elBlob = child.Attribute("PublicKeyBlob");
                    elName = child.Attribute("Name");
                    elVersion = child.Attribute("AssemblyVersion");
                    if(elBlob != null || elName != null || elVersion != null)
                    {
                        sn = new StrongName2(
                                            (elBlob == null ? null : new StrongNamePublicKeyBlob(elBlob)), 
                                            elName, 
                                            (elVersion == null ? null : new Version(elVersion)));
                        al.Add(sn);
                    }
                }
            }
            if(al.Count != 0)
                m_strongNames = al.ToArray();
        }
 
        public override SecurityElement ToXml()
        {
            SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.StrongNameIdentityPermission" );
            if (m_unrestricted)
                esd.AddAttribute( "Unrestricted", "true" );
            else if (m_strongNames != null)
            {
                if (m_strongNames.Length == 1)
                {
                    if (m_strongNames[0].m_publicKeyBlob != null)
                        esd.AddAttribute("PublicKeyBlob", Hex.EncodeHexString(m_strongNames[0].m_publicKeyBlob.PublicKey));
                    if (m_strongNames[0].m_name != null)
                        esd.AddAttribute("Name", m_strongNames[0].m_name);
                    if ((Object)m_strongNames[0].m_version != null)
                        esd.AddAttribute("AssemblyVersion", m_strongNames[0].m_version.ToString());
                }
                else
                {
                    int n;
                    for(n = 0; n < m_strongNames.Length; n++)
                    {
                        SecurityElement child = new SecurityElement("StrongName");
                        if (m_strongNames[n].m_publicKeyBlob != null)
                            child.AddAttribute("PublicKeyBlob", Hex.EncodeHexString(m_strongNames[n].m_publicKeyBlob.PublicKey));
                        if (m_strongNames[n].m_name != null)
                            child.AddAttribute("Name", m_strongNames[n].m_name);
                        if ((Object)m_strongNames[n].m_version != null)
                            child.AddAttribute("AssemblyVersion", m_strongNames[n].m_version.ToString());
                        esd.AddChild(child);
                    }
                }
            }
            return esd;
        }
#endif // FEATURE_CAS_POLICY
 
        /// <internalonly/>
        int IBuiltInPermission.GetTokenIndex()
        {
            return StrongNameIdentityPermission.GetTokenIndex();
        }
 
        internal static int GetTokenIndex()
        {
            return BuiltInPermissionIndex.StrongNameIdentityPermissionIndex;
        }
            
    }
}